Skip to content

Support for GodotConvert in signals #1192

Open
@bluenote10

Description

@bluenote10

I'm trying to convert from an rather old gdext version to the latest version. So far everything went smooth, very nice!

There is one thing that I couldn't solve so far though. Previously signals supported arguments that implemented the GodotConvert trait. This feature seems to have disappeared, and so far I couldn't figure out what's the equivalent in 0.3.1.

A very simple example: I have classes like this that use custom types as arguments of signals:

#[derive(GodotClass)]
#[class(base=Control)]
pub struct CustomProgressBar {
    base: Base<Control>,
    // ...
}

#[godot_api]
impl CustomProgressBar {
    #[signal]
    fn progress_change_request(progress: f32, event_kind: DragEventKind);
}

In this case, DragEventKind is a very simple enum, and implements the GodotConvert trait as follows:

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum DragEventKind {
    DragStart,
    Drag,
    DragEnd,
}

impl GodotConvert for DragEventKind {
    type Via = i32;
}

impl ToGodot for DragEventKind {
    type ToVia<'v> = i32;

    fn to_godot(&self) -> i32 {
        match self {
            DragEventKind::DragStart => 0,
            DragEventKind::Drag => 1,
            DragEventKind::DragEnd => 2,
        }
    }
}

impl FromGodot for DragEventKind {
    fn try_from_godot(d: i32) -> Result<Self, ConvertError> {
        match d {
            0 => Ok(DragEventKind::DragStart),
            1 => Ok(DragEventKind::Drag),
            2 => Ok(DragEventKind::DragEnd),
            _ => Err(ConvertError::new(format!(
                "Failed to convert DragEventKind for value {}",
                d
            ))),
        }
    }
}

With this setup it was possible to emit and receive custom types like this is a semi-type-safe way.

As far as I can see the new signal system now wants me to implement the ParamType trait instead, but I couldn't really figure out what's the equivalent of the Via type.

How could one solve this with the new system? Would it make sense to add a blanket implementation for ParamType (or AsArg?) if they support GodotConvert anyway?


For the record, the compile error of such code simply is:

82 | #[godot_api]
   | ^^^^^^^^^^^^ the trait `ParamType` is not implemented for `DragEventKind`

EDIT: I've noticed that as a temporary work-around I can use #[godot_api(no_typed_signals)], which seems to switch to the old system with GodotConvert support to get things to compile. Of course, then I can also only use the old-school string-based emit_signal function.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions