rktprof / godot-ios-extensions

Swift based iOS Extensions
MIT License
15 stars 2 forks source link

Thank you for sharing this. How do we use the .framework files. #1

Open zaddok opened 3 months ago

zaddok commented 3 months ago

This looks like great work, and it appears that it will save me much time. How do we use the .framework files built by the build script? Ive seen gdextension files use .a and .dylib and .so but never .framework

I wonder if you would mind clarifying with perhaps a sample gdextension file.

Thanks again for sharing your work. [I myself am trying to get local notifications into a module for Godot. Happy to share my work back into this repo once I get it working on a phone]

zaddok commented 3 months ago

I got it working. Perhaps just a note in the readme file to use build.sh, then copy the bin files over go Godot, and create something like this (mine that works):

[configuration]
entry_symbol = "swift_entry_point"
compatibility_minimum = 4.2

[libraries]
macos.debug = "res://notifications/macos/libSwiftNotifications.dylib"
ios.debug = "res://notifications/ios/SwiftNotifications.framework"

[dependencies]
macos.debug = {"res://notifications/macos/libSwiftGodot.dylib" : ""}
ios.debug = {"res://notifications/ios/SwiftGodot.framework" : ""}

Although perhaps it needs a release version in there, I am not that far yet.

rktprof commented 3 months ago

Hello! The .framework file can be used just like .dylib on iOS, this is my .gdextension file for the GameCenter extension

[configuration]
entry_symbol = "game_center_init"
compatibility_minimum = 4.2

[libraries]
macos.debug = "res://bin/macos/libGameCenter.dylib"
ios.debug = "res://bin/ios/GameCenter.framework"

[dependencies]
macos.debug = {"res://bin/macos/libSwiftGodot.dylib" : ""}
ios.debug = {"res://bin/ios/SwiftGodot.framework" : ""}

Let me know if you run into any issues, I try to keep things readable and swift is pretty good for that so hopefully you can get by without any documentation as I haven't gotten around to that yet (I'm developing these as I need them for my project)

Some of the biggest gotchas are with the callbacks as godot will just fail silently if the parameters aren't exactly correct and I have to use Variants so you just have to know what and how the data arrives (currently you have to look at the swift classes for that).

Another thing is threads, I get around that by having a game_center_service.gd class as an intermediate that takes the data and passes it along using call_deferred() as that seems to bring it back to the main thread (intended or not, I'm not sure)

And you can use the class names but if you don't build the plugins for the platform you're on godot will fail, so I use a workaround with ClassDB

As an example, this is how I handle authentication

const GAME_CENTER_SINGLETON: String = "GameCenter" # The Swift ClassName
if (ClassDB.class_exists(GAME_CENTER_SINGLETON)):
    print("Authenticating with GameCenter...")
    _game_center = ClassDB.instantiate(GAME_CENTER_SINGLETON)
    _game_center.authenticate(func(error: Variant, data: Variant) -> void:
        if (error == OK):
            var player: Player=Player.new()
            player.alias=data.alias
            player.display_name=data.displayName
            player.game_player_id=data.gamePlayerID
            player.team_player_id=data.teamPlayerID
            player.is_underage=data.isUnderage
            player.is_multiplayer_gaming_restricted=data.isMultiplayerGamingRestricted
            player.is_personalized_communication_restricted=data.isPersonalizedCommunicationRestricted

            on_complete.call_deferred(player)
        else:
            print("Failed to authenticate: %s (%s)" % [data, error])
            on_complete.call_deferred(null)
    )
zaddok commented 3 months ago

Thank you for sharing, these are helpful tips. I am going to rework my (now working, yaay!) local notification swift module, and do a pull request, probably tomorrow. I just want to make my code look as close as yours to possible, you clearly have more experience than me. Feel free to take pull request as is public domain, or reject it due to not wanting to maintain someone else's code, that would also be completely understandable :)

rktprof commented 3 months ago

I started learning swift (and I'm loving it) with this project so there might be swiftier ways of doing it, I'm currently debating wether to have the callable functions use snake_case or not. As such, I probably do some breaking changes every now and then but hopefully it's more semantic where you might have to rename something and not rework something completely

I did plan on adding a notification system in the future, I just got matchmaking working but I haven't even gotten around to testing if the IAP plugin works yet =)

zaddok commented 3 months ago

We're both learning. :) I am quite pragmatic about this. Don't stress about breaking things or renaming things. To be honest, it seems to me like the code itself is rather simple, it's actually building and joining everything together that is the difficult part. I think your right about using call_deferred to avoid thread issues, and I am also unclear if call_deferred "accidentally" fixes threading problems, or if its by design (and thus safe). I was thinking of digging into the core Godot C++ code to try and find out. But it would be nice if I can find someone who knows the core Godot code well enough to clarify this.