Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions godot-codegen/src/conv/type_conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,8 @@ fn to_rust_type_uncached(full_ty: &GodotTy, ctx: &mut Context) -> RustTy {

RustTy::EngineClass {
tokens: quote! { Gd<#qualified_class> },
arg_view: quote! { ObjectArg<#qualified_class> },
impl_as_arg: quote! { impl AsObjectArg<#qualified_class> },
object_arg: quote! { ObjectArg<#qualified_class> },
impl_as_object_arg: quote! { impl AsObjectArg<#qualified_class> },
inner_class: ty,
}
}
Expand Down Expand Up @@ -266,7 +266,7 @@ fn to_rust_expr_inner(expr: &str, ty: &RustTy, is_inner: bool) -> TokenStream {
return match ty {
RustTy::BuiltinIdent(ident) if ident == "Variant" => quote! { Variant::nil() },
RustTy::EngineClass { .. } => {
quote! { ObjectArg::null() }
quote! { Gd::null_arg() }
}
_ => panic!("null not representable in target type {ty:?}"),
}
Expand Down
23 changes: 17 additions & 6 deletions godot-codegen/src/generator/default_parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,30 +247,33 @@ fn make_extender(
default_value,
} = param;

let type_ = type_.param_decl();
let (field_type, needs_conversion) = type_.private_field_decl();

// Initialize with default parameters where available, forward constructor args otherwise
let init = if let Some(value) = default_value {
quote! { #name: #value }
make_field_init(name, value, needs_conversion)
} else {
quote! { #name }
};

result.builder_fields.push(quote! { #name: #type_ });
result.builder_fields.push(quote! { #name: #field_type });
result.builder_args.push(quote! { self.#name });
result.builder_inits.push(init);
}

for param in default_fn_params {
let FnParam { name, type_, .. } = param;
let type_ = type_.param_decl();
let param_type = type_.param_decl();
let (_, field_needs_conversion) = type_.private_field_decl();

let field_init = make_field_init(name, &quote! { value }, field_needs_conversion);

let method = quote! {
#[inline]
pub fn #name(self, value: #type_) -> Self {
pub fn #name(self, value: #param_type) -> Self {
// Currently not testing whether the parameter was already set
Self {
#name: value,
#field_init,
..self
}
}
Expand All @@ -281,3 +284,11 @@ fn make_extender(

result
}

fn make_field_init(name: &Ident, expr: &TokenStream, needs_conversion: bool) -> TokenStream {
if needs_conversion {
quote! { #name: #expr.as_object_arg() }
} else {
quote! { #name: #expr }
}
}
10 changes: 5 additions & 5 deletions godot-codegen/src/generator/functions_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -320,15 +320,15 @@ pub(crate) fn make_params_exprs<'a>(
// Objects (Gd<T>) use implicit conversions via AsObjectArg. Only use in non-virtual functions.
match &param.type_ {
RustTy::EngineClass {
arg_view,
impl_as_arg,
object_arg,
impl_as_object_arg,
..
} if !is_virtual => {
// Parameter declarations in signature: impl AsObjectArg<T>
if param_is_impl_asarg {
params.push(quote! { #param_name: #impl_as_arg });
params.push(quote! { #param_name: #impl_as_object_arg });
} else {
params.push(quote! { #param_name: #arg_view });
params.push(quote! { #param_name: #object_arg });
}

// Argument names in function body: arg.as_object_arg() vs. arg
Expand All @@ -338,7 +338,7 @@ pub(crate) fn make_params_exprs<'a>(
arg_names.push(quote! { #param_name });
}

param_types.push(quote! { #arg_view });
param_types.push(quote! { #object_arg });
}

_ => {
Expand Down
16 changes: 12 additions & 4 deletions godot-codegen/src/models/domain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -621,10 +621,10 @@ pub enum RustTy {
tokens: TokenStream,

/// Tokens with `ObjectArg<T>` (used in `type CallSig` tuple types).
arg_view: TokenStream,
object_arg: TokenStream,

/// Signature declaration with `impl AsObjectArg<T>`.
impl_as_arg: TokenStream,
impl_as_object_arg: TokenStream,

/// only inner `T`
#[allow(dead_code)] // only read in minimal config
Expand All @@ -639,12 +639,20 @@ impl RustTy {
pub fn param_decl(&self) -> TokenStream {
match self {
RustTy::EngineClass {
arg_view: raw_gd, ..
} => raw_gd.clone(),
impl_as_object_arg, ..
} => impl_as_object_arg.clone(),
other => other.to_token_stream(),
}
}

/// Returns `( <field tokens>, <needs .as_object_arg()> )`.
pub fn private_field_decl(&self) -> (TokenStream, bool) {
match self {
RustTy::EngineClass { object_arg, .. } => (object_arg.clone(), true),
other => (other.to_token_stream(), false),
}
}

pub fn return_decl(&self) -> TokenStream {
match self {
Self::EngineClass { tokens, .. } => quote! { -> Option<#tokens> },
Expand Down