Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Treat Signals Declared In Swift Like Signals Declared In Godot #586

Open
samdeane opened this issue Oct 24, 2024 · 2 comments
Open

Treat Signals Declared In Swift Like Signals Declared In Godot #586

samdeane opened this issue Oct 24, 2024 · 2 comments

Comments

@samdeane
Copy link
Contributor

samdeane commented Oct 24, 2024

Imported Signals

When we import a signal from Godot, we generate a helper class and a computed property, which allows us to connect to it in a very Swift-like manner:

func setupBot (robot: Node) {
    robot.ready.connect {
        print ("The robot's node is ready")
    }
}

If the signal has parameters, these are surfaced correctly in the closure:

obj.signalWithParams.connect { param1, param2 in 
  ...
}

Signals Defined In Swift

However, when we define a signal in Swift using the #signal macro, we create a static property on the Swift class.

This requires a different, less intuitive, less idiomatic syntax for connected to or emitting signals:

@Godot public class SBActor: Object {
  #signal("weapons_changed")
    
  func changeWeapon(_ weapon: SBWeapon) {
    emit(signal: SBActor.weaponsChanged)
  }
}

@Godot public class SBHud: Object {
  func connectToActor(_ actor: SBActor) {
    actor.connect(signal: SBActor.weaponsChanged, to: self, method: "updateWeapons")
  }

  @Callable func updateWeapons() {
    // update the HUD UI here...
  }
}

It should be possible to re-write the signal support so that Swift-side signals are implemented using the same helper classes as imported ones. This should result in a more uniform interface, and less code.

This could be a breaking change (if we alter the #signal macro), but I think it could probably be done instead as an additive change, using a different macro (possibly @Signal). Any implementation would probably be built on top of #42.

@samdeane
Copy link
Contributor Author

samdeane commented Oct 24, 2024

A solution should result in syntax more like this:

@Godot public class SBActor: Object {
  @Signal var weaponsChanged   // signal will be exposed to Godot as "weapons_changed"
    
  func changeWeapon(_ weapon: SBWeapon) {
    weaponsChanged.emit()
  }
}

@Godot public class SBHud: Object {
  func connectToActor(_ actor: SBActor) {
    actor.weaponsChanged.connect {
      // update the HUD UI here...
  }
}

@samdeane
Copy link
Contributor Author

It should also support signal parameters properly:

@Godot public class SBActor: Object {
  @Signal(args: [Int.self]) var healthChanged   // signal will be exposed to Godot as "health_changed, <new-health>"
    
  func hit(_ amount: Int) {
    health -= amount
    healthChanged.emit(health)
  }
}

@Godot public class SBHud: Object {
  func connectToActor(_ actor: SBActor) {
    actor.healthChanged.connect { health in
      // update the HUD UI here...
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant