├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── addons └── google_play_game_services_manager │ ├── plugin.cfg │ ├── plugin.gd │ └── singleton.gd ├── android ├── .build_version └── plugins │ ├── GodotGooglePlayGameServices.gdap │ └── GodotGooglePlayGameServices.release.aar ├── assets └── images │ ├── brand │ ├── android_icon.svg │ ├── android_icon.svg.import │ ├── games_controller.png │ ├── games_controller.png.import │ ├── github-social-preview.png │ ├── github-social-preview.png.import │ ├── github-social-preview.svg │ ├── github-social-preview.svg.import │ ├── godot_logo.svg │ ├── godot_logo.svg.import │ ├── grafico_funciones.png │ ├── grafico_funciones.png.import │ ├── ic_launcher_png-playstore.png │ ├── ic_launcher_png-playstore.png.import │ ├── icon.png │ ├── icon.png.import │ ├── icon.svg │ └── icon.svg.import │ └── screenshots │ ├── achievements.png │ ├── achievements.png.import │ ├── leaderboards.png │ ├── leaderboards.png.import │ ├── sign_in.png │ ├── sign_in.png.import │ ├── unlock_achievement.png │ └── unlock_achievement.png.import ├── example ├── achievements.gd ├── achievements.tscn ├── events.gd ├── events.tscn ├── leaderboards.gd ├── leaderboards.tscn ├── main.gd ├── main.tscn ├── menu.gd ├── menu.tscn ├── players.gd ├── players.tscn ├── resources │ ├── Roboto-Regular.ttf │ └── theme.tres ├── sign_in.gd ├── sign_in.tscn ├── snapshots.gd └── snapshots.tscn ├── icon.png ├── icon.png.import └── project.godot /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Explicitly declare text files you want to always be normalized and converted 5 | # to native line endings on checkout. 6 | *.cpp text 7 | *.c text 8 | *.h text 9 | *.gd text 10 | *.cs text 11 | 12 | # Declare files that will always have CRLF line endings on checkout. 13 | *.sln text eol=crlf 14 | 15 | # Denote all files that are truly binary and should not be modified. 16 | *.png binary 17 | *.jpg binary 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Godot-specific ignores 2 | .import/ 3 | export.cfg 4 | export_presets.cfg 5 | 6 | # Imported translations (automatically generated from CSV files) 7 | *.translation 8 | 9 | # Mono-specific ignores 10 | .mono/ 11 | data_*/ 12 | 13 | # Mac de los huevos 14 | .DS_Store 15 | 16 | # VS Code 17 | .vscode 18 | 19 | # Jetbrains 20 | /.idea/ 21 | 22 | # Android 23 | *.jks 24 | android/build 25 | android/exports 26 | 27 | # Project-specific ignores 28 | /release 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Fredia Huya-Kouadio 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Plugin Icon](assets/images/brand/github-social-preview.png) 2 | 3 | [![Android version and API level](https://img.shields.io/badge/Android-API%20Level%2033-darkgreen.svg)](https://developer.android.com) 4 | [![Godot version](https://img.shields.io/badge/Godot%20Engine-3.5.3-blue.svg)](https://github.com/godotengine/godot/) 5 | [![Google Play Game Services version](https://img.shields.io/badge/Play%20Games%20Services%20v2-17.0.0-green.svg)](https://developers.google.com/games/services/android/quickstart) 6 | 7 | > ⚠️ A **Godot 4.2+** version of this plugin can be found [here](https://github.com/Iakobs/godot-play-game-services)! 8 | 9 | > ⚠️ This plugin **requires** [Google Play Games Services for Godot](https://github.com/Iakobs/godot-google-play-game-services-android-plugin), which is a **native plugin** for Android. The addon on the current repository only provide a global singleton with **code completion** out-of-the-box, but it's not a requirement. 10 | 11 | > ⚠️ In order to use the Google Play Game Services, you will need a Google Play Console developer account, which involves a **once in a lifetime payment of $25** at the time of writing (January 2024). 12 | 13 | # Table of contents 14 | - [Purpose](#purpose) 15 | - [How to use this plugin](#how-to-use-this-plugin) 16 | - [Autoload](#autoload) 17 | - [Example project](#example-project) 18 | - [Reference](#reference) 19 | - [Signals](#signals) 20 | - [Methods](#methods) 21 | 22 | # Purpose 23 | 24 | This is a godot 3.5+ plugin for easier integration with the [Godot Google Play Game Services Android Plugin](https://github.com/Iakobs/godot-google-play-game-services-android-plugin). While this plugin is by no means necessary to integrate Google Play Games Services to your godot project, it provides a layer of abstraction on top of the Android plugin, giving you some interesting aids like **code completion** or mapping to **typed objects**. 25 | 26 | # How to use this plugin 27 | 28 | This is a normal godot plugin. Just add the plugin folder called `google_play_game_services_manager` to your `addons` folder, and you should be good to go. 29 | 30 | For further information on how to get your Google credentials for the integration, achievements, leaderboards, etc. please read the docs in the [Android plugin](https://github.com/Iakobs/godot-google-play-game-services-android-plugin). 31 | 32 | # Autoload 33 | 34 | The plugin provides an autoload that connect with the Android native plugin, organised in a fashion that follows the Google Play Games Services main features, like Sign In, Achievements, Leaderboards, etc. 35 | 36 | Communication with Google Play Game Services is asynchronous, this means that you have to heavily rely on signals. The autoload methods call the Game Services and provides the subsequent signals for results. 37 | 38 | These are the autoloads that the plugin provides so far, with their corresponding methods: 39 | 40 | # Example project 41 | 42 | Included with this plugin, there is a demo project that you can run to see the features of the integration with Google Play Game Services. There are some steps that you have to do first, though, which are described in the [Android native plugin docs](https://github.com/Iakobs/godot-google-play-game-services-android-plugin#configure-your-editor-android-settings). 43 | 44 | > ⚠️ There are some ids from your game leaderboards, achievements, etc. that you need to change in the demo project interface. 45 | 46 | # Reference 47 | 48 | In this document is listed the autoload signals and methods available for use inside Godot with GDScript. 49 | 50 | After you install the addon and enable it in `Project Settings...` > `Plugins`, you should be able to access its functionalities through the singleton: 51 | 52 | ```gdscript 53 | GooglePlayGamesServices.snapshots_load_game("mysavegame") 54 | ``` 55 | 56 | ## Signals 57 | 58 | These signals belong to the singleton and can be used by connecting them to a method. 59 | 60 | ```gdscript 61 | func _ready() -> void: 62 | GooglePlayGamesServices.connect("leaderboards_all_loaded", self, "_on_leaderboards_all_loaded") 63 | GooglePlayGamesServices.leaderboards_load_all(true) 64 | 65 | 66 | func _on_leaderboards_all_loaded(leaderboards: Array) -> void: 67 | prints(leaderboards) 68 | ``` 69 | 70 | ### Achievements 71 | 72 | #### achievements_loaded(achievements: Array[Dictionary]) 73 | 74 | This signal is emitted when calling the `achievements_load` method. 75 | Returns an array of dictionaries representing the [Achievement](https://developers.google.com/android/reference/com/google/android/gms/games/achievement/Achievement) object. 76 | 77 | #### achievements_revealed(revealed: bool, achievement_id: String) 78 | 79 | This signal is emitted when calling the `achievements_reveal` method. 80 | Returns `true` if the achievement is revealed and `false` otherwise. Also returns the id of the achievement. 81 | 82 | #### achievements_unlocked(is_unlocked: bool, achievement_id: String) 83 | 84 | This signal is emitted when calling the `achievements_increment` or `achievements_unlock` methods. 85 | Returns `true` if the achievement is unlocked or `false` otherwise. Also returns the id of the achievement. 86 | 87 | ### Events 88 | 89 | #### events_loaded(events: Array[Dictionary]) 90 | 91 | This signal is emitted when calling the `events_load` method. 92 | Returns an array of dictionaries representing the [Event](https://developers.google.com/android/reference/com/google/android/gms/games/event/Event) object. 93 | 94 | #### events_loaded_by_ids(events: Array[Dictionary]) 95 | 96 | This signal is emitted when calling the `events_load_by_ids` method. 97 | Returns an array of dictionaries representing the [Event](https://developers.google.com/android/reference/com/google/android/gms/games/event/Event) object. 98 | 99 | ### Leaderboards 100 | 101 | #### leaderboards_score_submitted(submitted: bool, leaderboard_id: String) 102 | 103 | This signal is emitted when calling the `leaderboards_submit_score` method. 104 | Returns `true` if the score is submitted. `false` otherwise. Also returns the id of the leaderboard. 105 | 106 | #### leaderboards_score_loaded(leaderboard_id: String, score: Dictionary) 107 | 108 | This signal is emitted when calling the `leaderboards_load_player_score` method. 109 | Return the leaderboard id and a dictionary representing the [LeaderboardScore](https://developers.google.com/android/reference/com/google/android/gms/games/leaderboard/LeaderboardScore). 110 | 111 | #### leaderboards_all_loaded(leaderboards: Array[Dictionary]) 112 | 113 | This signal is emitted when calling the `leaderboards_load_all` method. 114 | Returns an array of dictionaries representing the [Leaderboard](https://developers.google.com/android/reference/com/google/android/gms/games/leaderboard/Leaderboard) object. 115 | 116 | #### leaderboards_loaded(leaderboard: Dictionary) 117 | 118 | This signal is emitted when calling the `leaderboards_load` method. 119 | Returns a dictionary representing the [Leaderboard](https://developers.google.com/android/reference/com/google/android/gms/games/leaderboard/Leaderboard) object. 120 | 121 | #### leaderboards_player_centered_scores_loaded(leaderboard_id: String, leaderboard_scores: Dictionary) 122 | 123 | This signal is emitted when calling the `leaderboards_load_player_centered_scores` method. Returns the leaderboard id and a dictionary representing the [LeaderboardScores](https://developers.google.com/android/reference/com/google/android/gms/games/LeaderboardsClient.LeaderboardScores) object. 124 | 125 | #### leaderboards_top_scores_loaded(leaderboard_id: String, leaderboard_scores: Dictionary) 126 | 127 | This signal is emitted when calling the `leaderboards_load_top_scores` method. Returns the leaderboard id and a dictionary representing the [LeaderboardScores](https://developers.google.com/android/reference/com/google/android/gms/games/LeaderboardsClient.LeaderboardScores) object. 128 | 129 | ### Players 130 | 131 | #### players_current_loaded(player: Dictionary) 132 | 133 | This signal is emitted when calling the `players_load_current_player` method. 134 | Returns an dictionary representing the [Player](https://developers.google.com/android/reference/com/google/android/gms/games/Player) object. 135 | 136 | #### players_friends_loaded(friends: Array[Dictionary]) 137 | 138 | This signal is emitted when calling the `players_load_friends` method. 139 | Returns an array of dictionaries representing the [Player](https://developers.google.com/android/reference/com/google/android/gms/games/Player) object. 140 | 141 | #### players_searched(player: Dictionary) 142 | 143 | This signal is emitted when selecting a player in the search window that is being displayed after calling the [players_search] method. Returns an dictionary representing the [Player](https://developers.google.com/android/reference/com/google/android/gms/games/Player) object. 144 | 145 | ### Sign In 146 | 147 | #### sign_in_user_authenticated(is_authenticated: bool) 148 | 149 | This signal is emitted when calling the `sign_in_is_authenticated` and `sign_in_show_popup` methods. 150 | Returns `true` if the user is authenticated or `false` otherwise. 151 | 152 | #### sign_in_requested_server_side_access(token: String) 153 | 154 | This signal is emitted when calling the `sign_in_request_server_side_access` method. 155 | Returns an OAuth 2.0 authorization token as a string. 156 | 157 | ### Snapshots 158 | 159 | #### snapshots_game_saved(saved: bool, file_name: String, description: String) 160 | 161 | This signal is emitted when calling the `snapshots_save_game` method. 162 | Returns a boolean indicating if the game was saved or not, and the name and description of the save file. 163 | 164 | #### snapshots_game_loaded(snapshot: Dictionary) 165 | 166 | This signal is emitted when calling the `snapshots_load_game` method or after selecting a saved game in the window opened by the `snapshots_show_saved_games` method. 167 | Returns an dictionary representing the [Snapshot](https://developers.google.com/android/reference/com/google/android/gms/games/snapshot/Snapshot) object. 168 | 169 | As the loaded content is a byte array, convert it to a string first using `snapshot["content].get_string_from_utf8()`. 170 | 171 | #### snapshots_conflict_emitted(conflict: Dictionary) 172 | 173 | This signal is emitted when saving or loading a game, whenever a conflict occurs. 174 | Returns an dictionary representing [SnapshotConflict](https://developers.google.com/android/reference/com/google/android/gms/games/SnapshotsClient.SnapshotConflict) object. 175 | 176 | ## Methods 177 | 178 | ### Achievements 179 | 180 | #### achievements_increment(achievement_id: String, amount: int) 181 | 182 | Increments an achievement by the given number of steps. 183 | The achievement must be an incremental achievement. 184 | Once an achievement reaches at least the maximum number of steps, it will be unlocked automatically. 185 | Any further increments will be ignored. 186 | This is the fire-and-forget form of the API (no signals are emitted). 187 | 188 | #### achievements_load(force_reload: bool) 189 | 190 | Loads the achievement data for the currently signed-in player. Emits `achievements_loaded`. 191 | 192 | #### achievements_reveal(achievement_id: String) 193 | 194 | Reveals a hidden achievement to the currently signed-in player. If the achievement has already been unlocked, this will have no effect. Emits `achievements_revealed`. 195 | 196 | #### achievements_show() 197 | 198 | Shows a native popup to browse game achievements of the currently signed-in player. 199 | 200 | #### achievements_unlock(achievement_id: String) 201 | 202 | Unlocks an achievement for the currently signed in player. If the achievement is hidden this will reveal it to the player. Emits `achievements_unlocked`. 203 | 204 | ### Events 205 | 206 | #### events_increment(event_id: String, amount: int) 207 | 208 | Increments an event specified by eventId by the given number of steps. 209 | This is the fire-and-forget form of the API (no signals are emitted). 210 | 211 | #### events_load(force_reload: bool) 212 | 213 | Loads the event data for the currently signed-in player. Emits `events_loaded`. 214 | 215 | #### events_load_by_ids(force_reload: bool, event_ids: Array[String]) 216 | 217 | Loads the event data for the currently signed-in player for the specified ids. Emits `events_loaded_by_ids`. 218 | 219 | ### Leaderboards 220 | 221 | #### leaderboards_show_all() 222 | 223 | Shows a native popup to browse all leaderboards. 224 | 225 | #### leaderboards_show(leaderboard_id: String) 226 | 227 | Shows a native popup to browse the specified leaderboard. 228 | 229 | #### leaderboards_show_for_time_span(leaderboard_id: String, time_span: Int) 230 | 231 | Shows a native popup to browse the specified leaderboard for the specified time span. 232 | 233 | #### leaderboards_show_for_time_span_and_collection(leaderboard_id: String, time_span: int, collection: int) 234 | 235 | Shows a native popup to browse the specified leaderboard for the specified time span and collection. 236 | 237 | #### leaderboards_submit_score(leaderboard_id: String, score: float) 238 | 239 | Submits a score to the specified leaderboard. Emits `leaderboards_score_submitted`. 240 | 241 | #### leaderboards_load_player_score(leaderboard_id: String, time_span: int, collection: int) 242 | 243 | Loads the player's score for the specified leaderboard. Emits `leaderboards_score_loaded`. 244 | 245 | #### leaderboards_load_all(force_reload: bool) 246 | 247 | Loads the leaderboard data for the currently signed-in player. Emits `leaderboards_all_loaded`. 248 | 249 | #### leaderboards_load(leaderboard_id: String, force_reload: bool) 250 | 251 | Loads the leaderboard data for the currently signed-in player. Emits `leaderboards_loaded` 252 | 253 | #### leaderboards_load_player_centered_scores(leaderboard_id: String, time_span: int, collection: int, max_results: int, force_reload: bool) 254 | 255 | Loads the selected leaderboard and an array of scores for that leaderboard, centered in the currently signed in player. Emits the `leaderboards_player_centered_scores_loaded` signal. 256 | 257 | #### leaderboards_load_top_scores(leaderboard_id: String, time_span: int, collection: int, max_results: int, force_reload: bool) 258 | 259 | Loads the selected leaderboard and an array of scores for that leaderboard. Emits the `leaderboards_top_scores_loaded` signal. 260 | 261 | ### Players 262 | 263 | #### players_compare_profile(other_player_id: String) 264 | 265 | Shows a native popup to compare two players. 266 | 267 | #### players_compare_profile_with_alternative_name_hints(other_player_id: String, other_player_in_game_name: String, current_player_in_game_name: String) 268 | 269 | Shows a native popup to compare two players with alternative name hints. 270 | 271 | #### players_load_current_player(force_reload: bool) 272 | 273 | Loads the player data for the currently signed-in player. Emits `players_current_loaded`. 274 | 275 | #### players_load_friends(page_size: int, force_reload: bool, ask_for_permission: bool) 276 | 277 | Loads the friends data for the currently signed-in player. Emits `players_friends_loaded`. 278 | 279 | #### players_search() 280 | 281 | Shows a native popup to search for players. Emits `players_searched`. 282 | 283 | ### Sign in 284 | 285 | #### sign_in_is_authenticated() 286 | 287 | Checks if the user is signed in. Emits `sign_in_user_authenticated`. 288 | 289 | #### sign_in_show_popup() 290 | 291 | Signs in the user. Emits `sign_in_user_authenticated`. 292 | 293 | #### sign_in_request_server_side_access(server_client_id: String, force_refresh_token: bool) 294 | 295 | Requests server-side access for the specified server client ID. Emits `sign_in_requested_server_side_access`. 296 | 297 | ### Snapshots 298 | 299 | #### snapshots_load_game(file_name: String) 300 | 301 | Loads a game from the specified file. Emits `snapshots_game_loaded` or `snapshots_conflict_emitted`. 302 | 303 | #### snapshots_save_game(file_name: String, description: String, save_data: PoolByteArray, played_time_millis: int, progress_value: int) 304 | 305 | Saves a game to the specified file. If saving a string, convert it to a byte array first using `"value".to_utf8()` before passing it as `save_data`. Emits `snapshots_game_saved` or `snapshots_conflict_emitted`. 306 | 307 | #### snapshots_show_saved_games(title: String, allow_add_button: bool, allow_delete: bool, max_snapshots: int) 308 | 309 | Shows a native popup to browse saved games. Emits `snapshots_game_loaded`. 310 | -------------------------------------------------------------------------------- /addons/google_play_game_services_manager/plugin.cfg: -------------------------------------------------------------------------------- 1 | [plugin] 2 | 3 | name="GooglePlayGameServicesManager" 4 | description="A plugin that exposes some Singletons connected to the Google Play Game Services android plugin https://github.com/Iakobs/godot-google-play-game-services-android-plugin" 5 | author="Jacob Ibáñez Sánchez & Joel Gomes da Silva" 6 | version="2.0" 7 | script="plugin.gd" 8 | -------------------------------------------------------------------------------- /addons/google_play_game_services_manager/plugin.gd: -------------------------------------------------------------------------------- 1 | tool 2 | extends EditorPlugin 3 | 4 | 5 | const SINGLETON_NAME := "GooglePlayGamesServices" 6 | const SINGLETON_PATH := "res://addons/google_play_game_services_manager/singleton.gd" 7 | 8 | 9 | # Built-in overrides 10 | func enable_plugin() -> void: 11 | add_autoload_singleton(SINGLETON_NAME, SINGLETON_PATH) 12 | 13 | 14 | func disable_plugin() -> void: 15 | remove_autoload_singleton(SINGLETON_NAME) 16 | -------------------------------------------------------------------------------- /addons/google_play_game_services_manager/singleton.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | 4 | # Signals 5 | # Achievements 6 | signal achievements_loaded(achievements) 7 | signal achievements_revealed(revealed, achievement_id) 8 | signal achievements_unlocked(is_unlocked, achievement_id) 9 | 10 | # Events 11 | signal events_loaded(events) 12 | signal events_loaded_by_ids(events) 13 | 14 | # Leaderboards 15 | signal leaderboards_score_submitted(submitted, leaderboard_id) 16 | signal leaderboards_score_loaded(leaderboard_id, score) 17 | signal leaderboards_all_loaded(leaderboards) 18 | signal leaderboards_loaded(leaderboard) 19 | signal leaderboards_player_centered_scores_loaded(leaderboard_id, leaderboard_scores) 20 | signal leaderboards_top_scores_loaded(leaderboard_id, leaderboard_scores) 21 | 22 | # Players 23 | signal players_current_loaded(player) 24 | signal players_friends_loaded(friends) 25 | signal players_searched(player) 26 | 27 | # Sign In 28 | signal sign_in_user_authenticated(is_authenticated) 29 | signal sign_in_requested_server_side_access(token) 30 | 31 | # Snapshots 32 | signal snapshots_game_saved(saved, file_name, description) 33 | signal snapshots_game_loaded(snapshot) 34 | signal snapshots_conflict_emitted(conflict) 35 | 36 | # Helper 37 | signal image_stored(image) 38 | 39 | 40 | # Enums 41 | enum TimeSpan { 42 | TIME_SPAN_DAILY = 0, 43 | TIME_SPAN_WEEKLY = 1, 44 | TIME_SPAN_ALL_TIME = 2 45 | } 46 | 47 | enum Collection { 48 | COLLECTION_PUBLIC = 0, 49 | COLLECTION_FRIENDS = 3 50 | } 51 | 52 | 53 | # Variables 54 | var android_plugin: JNISingleton 55 | 56 | 57 | # Built-in overrides 58 | func _ready() -> void: 59 | if OS.get_name() != "Android": 60 | return 61 | 62 | if Engine.has_singleton("GodotGooglePlayGameServices"): 63 | android_plugin = Engine.get_singleton("GodotGooglePlayGameServices") 64 | else: 65 | prints("No Google Play Game Services Android plugin found for", name) 66 | 67 | if not android_plugin: 68 | return 69 | 70 | # Achievements 71 | android_plugin.connect("achievementsLoaded", self, "_on_achievements_loaded") 72 | android_plugin.connect("achievementsRevealed", self, "_on_achievements_revealed") 73 | android_plugin.connect("achievementsUnlocked", self, "_on_achievements_unlocked") 74 | 75 | # Events 76 | android_plugin.connect("eventsLoaded", self, "_on_events_loaded") 77 | android_plugin.connect("eventsLoadedByIds", self, "_on_events_loaded_by_ids") 78 | 79 | # Leaderboards 80 | android_plugin.connect("leaderboardsScoreSubmitted", self, "_on_leaderboards_score_submitted") 81 | android_plugin.connect("leaderboardsScoreLoaded", self, "_on_leaderboards_score_loaded") 82 | android_plugin.connect("leaderboardsAllLoaded", self, "_on_leaderboards_all_loaded") 83 | android_plugin.connect("leaderboardsLoaded", self, "_on_leaderboards_loaded") 84 | android_plugin.connect("leaderboardsPlayerCenteredScoresLoaded", self, "_on_leaderboards_load_player_centered_scores") 85 | android_plugin.connect("leaderboardsTopScoresLoaded", self, "_on_leaderboards_load_top_scores") 86 | 87 | # Players 88 | android_plugin.connect("playersCurrentLoaded", self, "_on_players_current_loaded") 89 | android_plugin.connect("playersFriendsLoaded", self, "_on_players_friends_loaded") 90 | android_plugin.connect("playersSearched", self, "_on_players_searched") 91 | 92 | # Sign In 93 | android_plugin.connect("signInUserAuthenticated", self, "_on_sign_in_user_authenticated") 94 | android_plugin.connect("signInRequestedServerSideAccess", self, "_on_sign_in_requested_server_side_access") 95 | 96 | # Snapshots 97 | android_plugin.connect("snapshotsGameSaved", self, "_on_snapshots_game_saved") 98 | android_plugin.connect("snapshotsGameLoaded", self, "_on_snapshots_game_loaded") 99 | android_plugin.connect("snapshotsConflictEmitted", self, "_on_snapshots_conflict_emitted") 100 | 101 | # Helper 102 | android_plugin.connect("imageStored", self, "_on_image_stored") 103 | 104 | android_plugin.initialize() 105 | 106 | 107 | # Public methods 108 | # Achievements 109 | func achievements_increment(achievement_id: String, amount: int, immediate := true) -> void: 110 | if android_plugin: 111 | android_plugin.achievementsIncrement(achievement_id, amount, immediate) 112 | 113 | 114 | func achievements_load(force_reload := false) -> void: 115 | if android_plugin: 116 | android_plugin.achievementsLoad(force_reload) 117 | 118 | 119 | func achievements_reveal(achievement_id: String, immediate := true) -> void: 120 | if android_plugin: 121 | android_plugin.achievementsReveal(achievement_id, immediate) 122 | 123 | 124 | func achievements_set_steps(achievement_id: String, amount: int, immediate := true) -> void: 125 | if android_plugin: 126 | android_plugin.achievementsSetSteps(achievement_id, amount, immediate) 127 | 128 | 129 | func achievements_show() -> void: 130 | if android_plugin: 131 | android_plugin.achievementsShow() 132 | 133 | 134 | func achievements_unlock(achievement_id: String, immediate := true) -> void: 135 | if android_plugin: 136 | android_plugin.achievementsUnlock(achievement_id, immediate) 137 | 138 | 139 | # Events 140 | func events_increment(event_id: String, amount: int) -> void: 141 | if android_plugin: 142 | android_plugin.eventsIncrement(event_id, amount) 143 | 144 | 145 | func events_load(force_reload: bool) -> void: 146 | if android_plugin: 147 | android_plugin.eventsLoad(force_reload) 148 | 149 | 150 | func events_load_by_ids(force_reload: bool, event_ids: Array) -> void: 151 | if android_plugin: 152 | android_plugin.eventsLoadByIds(force_reload, event_ids) 153 | 154 | 155 | # Leaderboards 156 | func leaderboards_show_all() -> void: 157 | if android_plugin: 158 | android_plugin.leaderboardsShowAll() 159 | 160 | 161 | func leaderboards_show(leaderboard_id: String) -> void: 162 | if android_plugin: 163 | android_plugin.leaderboardsShow(leaderboard_id) 164 | 165 | 166 | func leaderboards_show_for_time_span(leaderboard_id: String, time_span: int) -> void: 167 | if android_plugin: 168 | android_plugin.leaderboardsShowForTimeSpan(leaderboard_id, time_span) 169 | 170 | 171 | func leaderboards_show_for_time_span_and_collection(leaderboard_id: String, time_span: int, collection: int) -> void: 172 | if android_plugin: 173 | android_plugin.leaderboardsShowForTimeSpanAndCollection(leaderboard_id, time_span, collection) 174 | 175 | 176 | func leaderboards_submit_score(leaderboard_id: String, score: float) -> void: 177 | if android_plugin: 178 | android_plugin.leaderboardsSubmitScore(leaderboard_id, score) 179 | 180 | 181 | func leaderboards_load_player_score(leaderboard_id: String, time_span: int, collection: int) -> void: 182 | if android_plugin: 183 | android_plugin.leaderboardsLoadPlayerScore(leaderboard_id, time_span, collection) 184 | 185 | 186 | func leaderboards_load_all(force_reload: bool) -> void: 187 | if android_plugin: 188 | android_plugin.leaderboardsLoadAll(force_reload) 189 | 190 | 191 | func leaderboards_load(leaderboard_id: String, force_reload: bool) -> void: 192 | if android_plugin: 193 | android_plugin.leaderboardsLoad(leaderboard_id, force_reload) 194 | 195 | 196 | func leaderboards_load_player_centered_scores(leaderboard_id: String, time_span: int, collection: int, max_results: int, force_reload: bool) -> void: 197 | if android_plugin: 198 | android_plugin.leaderboardsLoadPlayerCenteredScores(leaderboard_id, time_span, collection, max_results, force_reload) 199 | 200 | 201 | func leaderboards_load_top_scores(leaderboard_id: String, time_span: int, collection: int, max_results: int, force_reload: bool) -> void: 202 | if android_plugin: 203 | android_plugin.leaderboardsLoadTopScores(leaderboard_id, time_span, collection, max_results, force_reload) 204 | 205 | 206 | # Players 207 | func players_compare_profile(other_player_id: String, other_player_in_game_name := "", current_player_in_game_name := "") -> void: 208 | if android_plugin: 209 | android_plugin.playersCompareProfile(other_player_id) 210 | 211 | 212 | func players_compare_profile_with_alternative_name_hints(other_player_id: String, other_player_in_game_name: String, current_player_in_game_name: String) -> void: 213 | if android_plugin: 214 | android_plugin.playersCompareProfileWithAlternativeNameHints( 215 | other_player_id, 216 | other_player_in_game_name, 217 | current_player_in_game_name 218 | ) 219 | 220 | 221 | func players_load_current(force_reload: bool) -> void: 222 | if android_plugin: 223 | android_plugin.playersLoadCurrent(force_reload) 224 | 225 | 226 | func players_load_friends(page_size: int, force_reload: bool, ask_for_permission: bool) -> void: 227 | if android_plugin: 228 | android_plugin.playersLoadFriends(page_size, force_reload, ask_for_permission) 229 | 230 | 231 | func players_search() -> void: 232 | if android_plugin: 233 | android_plugin.playersSearch() 234 | 235 | 236 | # Sign In 237 | func sign_in_is_authenticated() -> void: 238 | if android_plugin: 239 | android_plugin.signInIsAuthenticated() 240 | 241 | 242 | func sign_in_request_server_side_access(client_id: String, force_refresh_token: bool) -> void: 243 | if android_plugin: 244 | android_plugin.signInRequestServerSideAccess(client_id, force_refresh_token) 245 | 246 | 247 | func sign_in_show_popup() -> void: 248 | if android_plugin: 249 | android_plugin.signInShowPopup() 250 | 251 | 252 | # Snapshots 253 | func snapshots_load_game(file_name: String) -> void: 254 | if android_plugin: 255 | android_plugin.snapshotsLoadGame(file_name) 256 | 257 | 258 | func snapshots_save_game( 259 | file_name: String, 260 | description: String, 261 | save_data: PoolByteArray, 262 | played_time_millis: int, 263 | progress_value: int 264 | ) -> void: 265 | if android_plugin: 266 | android_plugin.snapshotsSaveGame(file_name, description, save_data, played_time_millis, progress_value) 267 | 268 | 269 | func snapshots_show_saved_games(title: String, allow_add_button: bool, allow_delete: bool, max_snapshots: int) -> void: 270 | if android_plugin: 271 | android_plugin.snapshotsShowSavedGames(title, allow_add_button, allow_delete, max_snapshots) 272 | 273 | 274 | # Event handlers 275 | # Achievements 276 | func _on_achievements_loaded(achievements: String) -> void: 277 | emit_signal("achievements_loaded", JSON.parse(achievements).result) 278 | 279 | 280 | func _on_achievements_revealed(revealed: bool, achievement_id: String) -> void: 281 | emit_signal("achievements_revealed", revealed, achievement_id) 282 | 283 | 284 | func _on_achievements_unlocked(is_unlocked: bool, achievement_id: String) -> void: 285 | emit_signal("achievements_unlocked", is_unlocked, achievement_id) 286 | 287 | 288 | func _on_events_loaded(events: String) -> void: 289 | emit_signal("events_loaded", JSON.parse(events).result) 290 | 291 | 292 | func _on_events_loaded_by_ids(events: String) -> void: 293 | emit_signal("events_loaded_by_ids", JSON.parse(events).result) 294 | 295 | 296 | # Leaderboards 297 | func _on_leaderboards_score_submitted(submitted: bool, leaderboard_id: String) -> void: 298 | emit_signal("leaderboards_score_submitted", submitted, leaderboard_id) 299 | 300 | 301 | func _on_leaderboards_score_loaded(leaderboard_id: String, score: String) -> void: 302 | emit_signal("leaderboards_score_loaded", leaderboard_id, JSON.parse(score).result) 303 | 304 | 305 | func _on_leaderboards_all_loaded(leaderboards: String) -> void: 306 | emit_signal("leaderboards_all_loaded", JSON.parse(leaderboards).result) 307 | 308 | 309 | func _on_leaderboards_loaded(leaderboard: String) -> void: 310 | emit_signal("leaderboards_loaded", JSON.parse(leaderboard).result) 311 | 312 | 313 | func _on_leaderboards_load_player_centered_scores(leaderboard_id: String, scores: String) -> void: 314 | emit_signal("leaderboards_player_centered_scores_loaded", leaderboard_id, JSON.parse(scores).result) 315 | 316 | 317 | func _on_leaderboards_load_top_scores(leaderboard_id: String, scores: String) -> void: 318 | emit_signal("leaderboards_top_scores_loaded", leaderboard_id, JSON.parse(scores).result) 319 | 320 | # Players 321 | func _on_players_current_loaded(player: String) -> void: 322 | emit_signal("players_current_loaded", JSON.parse(player).result) 323 | 324 | 325 | func _on_players_friends_loaded(friends: String) -> void: 326 | emit_signal("players_friends_loaded", JSON.parse(friends).result) 327 | 328 | 329 | func _on_players_searched(player: String) -> void: 330 | emit_signal("players_friends_loaded", JSON.parse(player).result) 331 | 332 | 333 | # Sign In 334 | func _on_sign_in_user_authenticated(_is_authenticated: bool) -> void: 335 | emit_signal("sign_in_user_authenticated", _is_authenticated) 336 | 337 | 338 | func _on_sign_in_requested_server_side_access(token: String) -> void: 339 | emit_signal("sign_in_requested_server_side_access", token) 340 | 341 | 342 | # Snapshots 343 | func _on_snapshots_game_saved(saved: bool, file_name: String, description: String) -> void: 344 | emit_signal("snapshots_game_saved", saved, file_name, description) 345 | 346 | 347 | func _on_snapshots_game_loaded(snapshot: String) -> void: 348 | var parsed_snapshot: Dictionary = JSON.parse(snapshot).result 349 | var content: Array = parsed_snapshot.get("content", []) 350 | 351 | if typeof(content) == TYPE_ARRAY: 352 | parsed_snapshot["content"] = PoolByteArray(content) 353 | 354 | emit_signal("snapshots_game_loaded", parsed_snapshot) 355 | 356 | 357 | func _on_snapshots_conflict_emitted(conflict: String) -> void: 358 | emit_signal("snapshots_conflict_emitted", JSON.parse(conflict).result) 359 | 360 | 361 | func _on_image_stored(image: String) -> void: 362 | emit_signal("image_stored", image) 363 | -------------------------------------------------------------------------------- /android/.build_version: -------------------------------------------------------------------------------- 1 | 3.5.3.stable 2 | -------------------------------------------------------------------------------- /android/plugins/GodotGooglePlayGameServices.gdap: -------------------------------------------------------------------------------- 1 | [config] 2 | 3 | name="GodotGooglePlayGameServices" 4 | binary_type="local" 5 | binary="GodotGooglePlayGameServices.release.aar" 6 | 7 | [dependencies] 8 | 9 | remote=["com.google.android.gms:play-services-games-v2:17.0.0", "com.google.code.gson:gson:2.10.1"] -------------------------------------------------------------------------------- /android/plugins/GodotGooglePlayGameServices.release.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Iakobs/godot-google-play-game-services-plugin/6265a74c370e63d7194fc0035e3770a1bf0d1e43/android/plugins/GodotGooglePlayGameServices.release.aar -------------------------------------------------------------------------------- /assets/images/brand/android_icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 198 | -------------------------------------------------------------------------------- /assets/images/brand/android_icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="keep" 4 | -------------------------------------------------------------------------------- /assets/images/brand/games_controller.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Iakobs/godot-google-play-game-services-plugin/6265a74c370e63d7194fc0035e3770a1bf0d1e43/assets/images/brand/games_controller.png -------------------------------------------------------------------------------- /assets/images/brand/games_controller.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="keep" 4 | -------------------------------------------------------------------------------- /assets/images/brand/github-social-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Iakobs/godot-google-play-game-services-plugin/6265a74c370e63d7194fc0035e3770a1bf0d1e43/assets/images/brand/github-social-preview.png -------------------------------------------------------------------------------- /assets/images/brand/github-social-preview.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="keep" 4 | -------------------------------------------------------------------------------- /assets/images/brand/github-social-preview.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="keep" 4 | -------------------------------------------------------------------------------- /assets/images/brand/godot_logo.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /assets/images/brand/godot_logo.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="keep" 4 | -------------------------------------------------------------------------------- /assets/images/brand/grafico_funciones.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Iakobs/godot-google-play-game-services-plugin/6265a74c370e63d7194fc0035e3770a1bf0d1e43/assets/images/brand/grafico_funciones.png -------------------------------------------------------------------------------- /assets/images/brand/grafico_funciones.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="keep" 4 | -------------------------------------------------------------------------------- /assets/images/brand/ic_launcher_png-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Iakobs/godot-google-play-game-services-plugin/6265a74c370e63d7194fc0035e3770a1bf0d1e43/assets/images/brand/ic_launcher_png-playstore.png -------------------------------------------------------------------------------- /assets/images/brand/ic_launcher_png-playstore.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="keep" 4 | -------------------------------------------------------------------------------- /assets/images/brand/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Iakobs/godot-google-play-game-services-plugin/6265a74c370e63d7194fc0035e3770a1bf0d1e43/assets/images/brand/icon.png -------------------------------------------------------------------------------- /assets/images/brand/icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="keep" 4 | -------------------------------------------------------------------------------- /assets/images/brand/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 200 | -------------------------------------------------------------------------------- /assets/images/brand/icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="keep" 4 | -------------------------------------------------------------------------------- /assets/images/screenshots/achievements.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Iakobs/godot-google-play-game-services-plugin/6265a74c370e63d7194fc0035e3770a1bf0d1e43/assets/images/screenshots/achievements.png -------------------------------------------------------------------------------- /assets/images/screenshots/achievements.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="keep" 4 | -------------------------------------------------------------------------------- /assets/images/screenshots/leaderboards.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Iakobs/godot-google-play-game-services-plugin/6265a74c370e63d7194fc0035e3770a1bf0d1e43/assets/images/screenshots/leaderboards.png -------------------------------------------------------------------------------- /assets/images/screenshots/leaderboards.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="keep" 4 | -------------------------------------------------------------------------------- /assets/images/screenshots/sign_in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Iakobs/godot-google-play-game-services-plugin/6265a74c370e63d7194fc0035e3770a1bf0d1e43/assets/images/screenshots/sign_in.png -------------------------------------------------------------------------------- /assets/images/screenshots/sign_in.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="keep" 4 | -------------------------------------------------------------------------------- /assets/images/screenshots/unlock_achievement.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Iakobs/godot-google-play-game-services-plugin/6265a74c370e63d7194fc0035e3770a1bf0d1e43/assets/images/screenshots/unlock_achievement.png -------------------------------------------------------------------------------- /assets/images/screenshots/unlock_achievement.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="keep" 4 | -------------------------------------------------------------------------------- /example/achievements.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | 4 | # Variables 5 | onready var _line_edit_output: LineEdit = find_node("LineEditOutput") 6 | onready var _line_edit_achievement_id: LineEdit = find_node("LineEditAchievementId") 7 | onready var _spin_box_amount: SpinBox = find_node("SpinBoxAmount") 8 | onready var _check_button_force_reload: CheckButton = find_node("CheckButtonForceReload") 9 | onready var _check_button_immediate: CheckButton = find_node("CheckButtonImmediate") 10 | 11 | 12 | # Built-in overrides 13 | func _ready() -> void: 14 | GooglePlayGamesServices.connect("achievements_unlocked", self, "_on_achievements_unlocked") 15 | GooglePlayGamesServices.connect("achievements_loaded", self, "_on_achievements_loaded") 16 | GooglePlayGamesServices.connect("achievements_revealed", self, "_on_achievements_revealed") 17 | 18 | 19 | # Event handlers 20 | # Buttons 21 | func _on_ButtonIncrement_pressed() -> void: 22 | GooglePlayGamesServices.achievements_increment( 23 | _line_edit_achievement_id.text, 24 | int(_spin_box_amount.value), 25 | _check_button_immediate.pressed) 26 | 27 | 28 | func _on_ButtonLoad_pressed() -> void: 29 | GooglePlayGamesServices.achievements_load(_check_button_force_reload.pressed) 30 | 31 | 32 | func _on_ButtonReveal_pressed() -> void: 33 | GooglePlayGamesServices.achievements_reveal(_line_edit_achievement_id.text, _check_button_immediate.pressed) 34 | 35 | 36 | func _on_ButtonSetSteps_pressed() -> void: 37 | GooglePlayGamesServices.achievements_set_steps( 38 | _line_edit_achievement_id.text, 39 | int(_spin_box_amount.value), 40 | _check_button_immediate.pressed) 41 | 42 | 43 | func _on_ButtonShow_pressed() -> void: 44 | GooglePlayGamesServices.achievements_show() 45 | 46 | 47 | func _on_ButtonUnlock_pressed() -> void: 48 | GooglePlayGamesServices.achievements_unlock(_line_edit_achievement_id.text, _check_button_immediate.pressed) 49 | 50 | 51 | # Return values 52 | func _on_achievements_loaded(achievements: Array) -> void: 53 | var value := str(achievements) 54 | _line_edit_output.text = value 55 | prints(value) 56 | 57 | 58 | func _on_achievements_unlocked(is_unlocked: bool, achievement_id: String) -> void: 59 | var value := "unlocked: " + str(is_unlocked) + " (%s)" % achievement_id 60 | _line_edit_output.text = value 61 | prints(value) 62 | 63 | 64 | func _on_achievements_revealed(revealed: bool, achievement_id: String) -> void: 65 | var value := "revealed: " + str(revealed) + " (%s)" % achievement_id 66 | _line_edit_output.text = value 67 | prints(value) 68 | -------------------------------------------------------------------------------- /example/achievements.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://example/achievements.gd" type="Script" id=1] 4 | [ext_resource path="res://example/resources/theme.tres" type="Theme" id=2] 5 | 6 | [node name="Achievements" type="Control"] 7 | anchor_right = 1.0 8 | anchor_bottom = 1.0 9 | size_flags_horizontal = 3 10 | size_flags_vertical = 3 11 | theme = ExtResource( 2 ) 12 | script = ExtResource( 1 ) 13 | 14 | [node name="VBoxContainer" type="VBoxContainer" parent="."] 15 | anchor_right = 1.0 16 | anchor_bottom = 1.0 17 | size_flags_horizontal = 3 18 | size_flags_vertical = 3 19 | 20 | [node name="LabelTitle" type="Label" parent="VBoxContainer"] 21 | margin_right = 720.0 22 | margin_bottom = 87.0 23 | size_flags_horizontal = 3 24 | size_flags_vertical = 7 25 | text = "Achievements" 26 | align = 1 27 | valign = 1 28 | 29 | [node name="LineEditOutput" type="LineEdit" parent="VBoxContainer"] 30 | margin_top = 91.0 31 | margin_right = 720.0 32 | margin_bottom = 179.0 33 | size_flags_horizontal = 3 34 | size_flags_vertical = 3 35 | align = 1 36 | virtual_keyboard_enabled = false 37 | placeholder_text = "Output" 38 | caret_blink = true 39 | caret_blink_speed = 0.5 40 | 41 | [node name="LabelEndpoints" type="Label" parent="VBoxContainer"] 42 | margin_top = 183.0 43 | margin_right = 720.0 44 | margin_bottom = 271.0 45 | size_flags_horizontal = 3 46 | size_flags_vertical = 7 47 | text = "Endpoints" 48 | align = 1 49 | valign = 2 50 | 51 | [node name="ButtonIncrement" type="Button" parent="VBoxContainer"] 52 | margin_top = 275.0 53 | margin_right = 720.0 54 | margin_bottom = 362.0 55 | focus_mode = 0 56 | size_flags_horizontal = 3 57 | size_flags_vertical = 3 58 | enabled_focus_mode = 0 59 | text = "Increment (AchId, Amount, Immediate)" 60 | expand_icon = true 61 | 62 | [node name="ButtonLoad" type="Button" parent="VBoxContainer"] 63 | margin_top = 366.0 64 | margin_right = 720.0 65 | margin_bottom = 454.0 66 | focus_mode = 0 67 | size_flags_horizontal = 3 68 | size_flags_vertical = 3 69 | enabled_focus_mode = 0 70 | text = "Load (ForceReload)" 71 | expand_icon = true 72 | 73 | [node name="ButtonReveal" type="Button" parent="VBoxContainer"] 74 | margin_top = 458.0 75 | margin_right = 720.0 76 | margin_bottom = 546.0 77 | focus_mode = 0 78 | size_flags_horizontal = 3 79 | size_flags_vertical = 3 80 | enabled_focus_mode = 0 81 | text = "Reveal (AchId, Immediate)" 82 | expand_icon = true 83 | 84 | [node name="ButtonSetSteps" type="Button" parent="VBoxContainer"] 85 | margin_top = 550.0 86 | margin_right = 720.0 87 | margin_bottom = 638.0 88 | focus_mode = 0 89 | size_flags_horizontal = 3 90 | size_flags_vertical = 3 91 | enabled_focus_mode = 0 92 | text = "Set Steps (AchId, Amount, Immediate)" 93 | expand_icon = true 94 | 95 | [node name="ButtonShow" type="Button" parent="VBoxContainer"] 96 | margin_top = 642.0 97 | margin_right = 720.0 98 | margin_bottom = 729.0 99 | focus_mode = 0 100 | size_flags_horizontal = 3 101 | size_flags_vertical = 3 102 | enabled_focus_mode = 0 103 | text = "Show" 104 | expand_icon = true 105 | 106 | [node name="ButtonUnlock" type="Button" parent="VBoxContainer"] 107 | margin_top = 733.0 108 | margin_right = 720.0 109 | margin_bottom = 821.0 110 | focus_mode = 0 111 | size_flags_horizontal = 3 112 | size_flags_vertical = 3 113 | enabled_focus_mode = 0 114 | text = "Unlock (AchId, Immediate)" 115 | expand_icon = true 116 | 117 | [node name="LabelParameters" type="Label" parent="VBoxContainer"] 118 | margin_top = 825.0 119 | margin_right = 720.0 120 | margin_bottom = 913.0 121 | size_flags_horizontal = 3 122 | size_flags_vertical = 7 123 | text = "Parameters" 124 | align = 1 125 | valign = 2 126 | 127 | [node name="LineEditAchievementId" type="LineEdit" parent="VBoxContainer"] 128 | margin_top = 917.0 129 | margin_right = 720.0 130 | margin_bottom = 1004.0 131 | size_flags_horizontal = 3 132 | size_flags_vertical = 3 133 | text = "CgkIy_Lnrp4ZEAIQDA" 134 | align = 1 135 | placeholder_text = "Achievement Id (AchId)" 136 | caret_blink = true 137 | caret_blink_speed = 0.5 138 | 139 | [node name="SpinBoxAmount" type="SpinBox" parent="VBoxContainer"] 140 | margin_top = 1008.0 141 | margin_right = 720.0 142 | margin_bottom = 1096.0 143 | size_flags_horizontal = 3 144 | size_flags_vertical = 3 145 | max_value = 1000.0 146 | value = 1.0 147 | rounded = true 148 | align = 1 149 | prefix = "Amount" 150 | 151 | [node name="CheckButtonForceReload" type="CheckButton" parent="VBoxContainer"] 152 | margin_top = 1100.0 153 | margin_right = 720.0 154 | margin_bottom = 1188.0 155 | size_flags_horizontal = 3 156 | size_flags_vertical = 3 157 | pressed = true 158 | text = "Force Reload" 159 | align = 1 160 | 161 | [node name="CheckButtonImmediate" type="CheckButton" parent="VBoxContainer"] 162 | margin_top = 1192.0 163 | margin_right = 720.0 164 | margin_bottom = 1280.0 165 | size_flags_horizontal = 3 166 | size_flags_vertical = 3 167 | pressed = true 168 | text = "Immediate" 169 | align = 1 170 | 171 | [connection signal="pressed" from="VBoxContainer/ButtonIncrement" to="." method="_on_ButtonIncrement_pressed"] 172 | [connection signal="pressed" from="VBoxContainer/ButtonLoad" to="." method="_on_ButtonLoad_pressed"] 173 | [connection signal="pressed" from="VBoxContainer/ButtonReveal" to="." method="_on_ButtonReveal_pressed"] 174 | [connection signal="pressed" from="VBoxContainer/ButtonSetSteps" to="." method="_on_ButtonSetSteps_pressed"] 175 | [connection signal="pressed" from="VBoxContainer/ButtonShow" to="." method="_on_ButtonShow_pressed"] 176 | [connection signal="pressed" from="VBoxContainer/ButtonUnlock" to="." method="_on_ButtonUnlock_pressed"] 177 | -------------------------------------------------------------------------------- /example/events.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | 4 | # Variables 5 | onready var _line_edit_output: LineEdit = find_node("LineEditOutput") 6 | onready var _line_edit_event_id: LineEdit = find_node("LineEditEventId") 7 | onready var _check_button_force_reload: CheckButton = find_node("CheckButtonForceReload") 8 | 9 | 10 | # Built-in overrides 11 | func _ready() -> void: 12 | GooglePlayGamesServices.connect("events_loaded", self, "_on_events_loaded") 13 | GooglePlayGamesServices.connect("events_loaded_by_ids", self, "_on_events_loaded") 14 | 15 | 16 | # Event handlers 17 | # Buttons 18 | func _on_ButtonIncrement_pressed() -> void: 19 | GooglePlayGamesServices.events_increment(_line_edit_event_id.text, 1) 20 | 21 | 22 | func _on_ButtonLoad_pressed() -> void: 23 | GooglePlayGamesServices.events_load(_check_button_force_reload.pressed) 24 | 25 | 26 | func _on_ButtonLoadByIds_pressed() -> void: 27 | GooglePlayGamesServices.events_load_by_ids( 28 | _check_button_force_reload.pressed, 29 | _line_edit_event_id.text.split(",", false)) 30 | 31 | 32 | # Return values 33 | func _on_events_loaded(events: Array) -> void: 34 | var value := str(events) 35 | _line_edit_output.text = value 36 | prints(value) 37 | -------------------------------------------------------------------------------- /example/events.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://example/events.gd" type="Script" id=1] 4 | [ext_resource path="res://example/resources/theme.tres" type="Theme" id=2] 5 | 6 | [node name="Events" type="Control"] 7 | anchor_right = 1.0 8 | anchor_bottom = 1.0 9 | size_flags_horizontal = 3 10 | size_flags_vertical = 3 11 | theme = ExtResource( 2 ) 12 | script = ExtResource( 1 ) 13 | 14 | [node name="VBoxContainer" type="VBoxContainer" parent="."] 15 | anchor_right = 1.0 16 | anchor_bottom = 1.0 17 | size_flags_horizontal = 3 18 | size_flags_vertical = 3 19 | 20 | [node name="LabelTitle" type="Label" parent="VBoxContainer"] 21 | margin_right = 720.0 22 | margin_bottom = 124.0 23 | size_flags_horizontal = 3 24 | size_flags_vertical = 7 25 | text = "Events" 26 | align = 1 27 | valign = 1 28 | 29 | [node name="LineEditOutput" type="LineEdit" parent="VBoxContainer"] 30 | margin_top = 128.0 31 | margin_right = 720.0 32 | margin_bottom = 252.0 33 | size_flags_horizontal = 3 34 | size_flags_vertical = 3 35 | align = 1 36 | virtual_keyboard_enabled = false 37 | placeholder_text = "Output" 38 | caret_blink = true 39 | caret_blink_speed = 0.5 40 | 41 | [node name="LabelEndpoints" type="Label" parent="VBoxContainer"] 42 | margin_top = 256.0 43 | margin_right = 720.0 44 | margin_bottom = 381.0 45 | size_flags_horizontal = 3 46 | size_flags_vertical = 7 47 | text = "Endpoints" 48 | align = 1 49 | valign = 2 50 | 51 | [node name="ButtonIncrement" type="Button" parent="VBoxContainer"] 52 | margin_top = 385.0 53 | margin_right = 720.0 54 | margin_bottom = 509.0 55 | focus_mode = 0 56 | size_flags_horizontal = 3 57 | size_flags_vertical = 3 58 | enabled_focus_mode = 0 59 | text = "Increment Event (EvId, Amount)" 60 | expand_icon = true 61 | 62 | [node name="ButtonLoad" type="Button" parent="VBoxContainer"] 63 | margin_top = 513.0 64 | margin_right = 720.0 65 | margin_bottom = 638.0 66 | focus_mode = 0 67 | size_flags_horizontal = 3 68 | size_flags_vertical = 3 69 | enabled_focus_mode = 0 70 | text = "Load Events (ForceReload)" 71 | expand_icon = true 72 | 73 | [node name="ButtonLoadByIds" type="Button" parent="VBoxContainer"] 74 | margin_top = 642.0 75 | margin_right = 720.0 76 | margin_bottom = 766.0 77 | focus_mode = 0 78 | size_flags_horizontal = 3 79 | size_flags_vertical = 3 80 | enabled_focus_mode = 0 81 | text = "Load Events By Ids (ForceReload, EvIds)" 82 | expand_icon = true 83 | 84 | [node name="LabelParameters" type="Label" parent="VBoxContainer"] 85 | margin_top = 770.0 86 | margin_right = 720.0 87 | margin_bottom = 894.0 88 | size_flags_horizontal = 3 89 | size_flags_vertical = 7 90 | text = "Parameters" 91 | align = 1 92 | valign = 2 93 | 94 | [node name="LineEditEventId" type="LineEdit" parent="VBoxContainer"] 95 | margin_top = 898.0 96 | margin_right = 720.0 97 | margin_bottom = 1023.0 98 | size_flags_horizontal = 3 99 | size_flags_vertical = 3 100 | text = "CgkIy_Lnrp4ZEAIQDQ" 101 | align = 1 102 | placeholder_text = "Event Id (EvId)" 103 | caret_blink = true 104 | caret_blink_speed = 0.5 105 | 106 | [node name="SpinBoxAmount" type="SpinBox" parent="VBoxContainer"] 107 | margin_top = 1027.0 108 | margin_right = 720.0 109 | margin_bottom = 1151.0 110 | size_flags_horizontal = 3 111 | size_flags_vertical = 3 112 | max_value = 1000.0 113 | value = 1.0 114 | rounded = true 115 | align = 1 116 | prefix = "Amount" 117 | 118 | [node name="CheckButtonForceReload" type="CheckButton" parent="VBoxContainer"] 119 | margin_top = 1155.0 120 | margin_right = 720.0 121 | margin_bottom = 1280.0 122 | size_flags_horizontal = 3 123 | size_flags_vertical = 3 124 | pressed = true 125 | text = "Force Reload" 126 | align = 1 127 | 128 | [connection signal="pressed" from="VBoxContainer/ButtonIncrement" to="." method="_on_ButtonIncrement_pressed"] 129 | [connection signal="pressed" from="VBoxContainer/ButtonLoad" to="." method="_on_ButtonLoad_pressed"] 130 | [connection signal="pressed" from="VBoxContainer/ButtonLoadByIds" to="." method="_on_ButtonLoadByIds_pressed"] 131 | -------------------------------------------------------------------------------- /example/leaderboards.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | 4 | # Variables 5 | onready var _line_edit_leaderboards_output: LineEdit = find_node("LineEditLeaderboardsOutput") 6 | onready var _line_edit_leaderboard_id: LineEdit = find_node("LineEditLeaderboardId") 7 | onready var _spin_box_score: SpinBox = find_node("SpinBoxScore") 8 | onready var _check_button_leaderboards_force_reload: CheckButton = find_node("CheckButtonLeaderboardsForceReload") 9 | onready var _slider_timespan: HSlider = find_node("HSliderTimespan") 10 | onready var _slider_leaderboards_collection: HSlider = find_node("HSliderLeaderboardsCollection") 11 | 12 | 13 | # Built-in overrides 14 | func _ready() -> void: 15 | GooglePlayGamesServices.connect("leaderboards_score_submitted", self, "_on_leaderboards_score_submitted") 16 | GooglePlayGamesServices.connect("leaderboards_score_loaded", self, "_on_leaderboards_score_loaded") 17 | GooglePlayGamesServices.connect("leaderboards_all_loaded", self, "_on_leaderboards_all_loaded") 18 | GooglePlayGamesServices.connect("leaderboards_loaded", self, "_on_leaderboards_loaded") 19 | 20 | 21 | # Event handlers 22 | # Buttons 23 | func _on_ButtonShowAllLeaderboards_pressed() -> void: 24 | GooglePlayGamesServices.leaderboards_show_all() 25 | 26 | 27 | func _on_ButtonShowLeaderboard_pressed() -> void: 28 | GooglePlayGamesServices.leaderboards_show(_line_edit_leaderboard_id.text) 29 | 30 | 31 | func _on_ButtonShowLBForTS_pressed() -> void: 32 | GooglePlayGamesServices.leaderboards_show_for_time_span( 33 | _line_edit_leaderboard_id.text, 34 | int(_slider_timespan.value)) 35 | 36 | 37 | func _on_ButtonShowLBForTSAndCollection_pressed() -> void: 38 | GooglePlayGamesServices.leaderboards_show_for_time_span_and_collection( 39 | _line_edit_leaderboard_id.text, 40 | int(_slider_timespan.value), 41 | int(_slider_leaderboards_collection.value)) 42 | 43 | 44 | func _on_ButtonSubmitScore_pressed() -> void: 45 | GooglePlayGamesServices.leaderboards_submit_score(_line_edit_leaderboard_id.text, _spin_box_score.value) 46 | 47 | 48 | func _on_ButtonLoadPlayerScore_pressed() -> void: 49 | GooglePlayGamesServices.leaderboards_load_player_score( 50 | _line_edit_leaderboard_id.text, 51 | int(_slider_timespan.value), 52 | int(_slider_leaderboards_collection.value)) 53 | 54 | 55 | func _on_ButtonLoadAllLeaderboards_pressed() -> void: 56 | GooglePlayGamesServices.leaderboards_load_all(_check_button_leaderboards_force_reload.pressed) 57 | 58 | 59 | func _on_ButtonLoadLeaderboard_pressed() -> void: 60 | GooglePlayGamesServices.leaderboards_load( 61 | _line_edit_leaderboard_id.text, 62 | _check_button_leaderboards_force_reload.pressed) 63 | 64 | 65 | # Return values 66 | func _on_leaderboards_score_submitted(submitted: bool, leaderboard_id: String) -> void: 67 | var value := "submitted: " + str(submitted) + " (%s)" % leaderboard_id 68 | _line_edit_leaderboards_output.text = value 69 | prints(value) 70 | 71 | 72 | func _on_leaderboards_score_loaded(leaderboard_id: String, score: Dictionary) -> void: 73 | var value := "score: " + str(score) + ", leaderboard: " + str(leaderboard_id) 74 | _line_edit_leaderboards_output.text = value 75 | prints(value) 76 | 77 | 78 | func _on_leaderboards_all_loaded(leaderboards: Array) -> void: 79 | var value := "leaderboards: " + str(leaderboards) 80 | _line_edit_leaderboards_output.text = value 81 | prints(value) 82 | 83 | 84 | func _on_leaderboards_loaded(leaderboard: Dictionary) -> void: 85 | var value := "leaderboard: " + str(leaderboard) 86 | _line_edit_leaderboards_output.text = value 87 | prints(value) 88 | -------------------------------------------------------------------------------- /example/leaderboards.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://example/leaderboards.gd" type="Script" id=1] 4 | [ext_resource path="res://example/resources/theme.tres" type="Theme" id=2] 5 | 6 | [node name="Leaderboards" type="Control"] 7 | anchor_right = 1.0 8 | anchor_bottom = 1.0 9 | size_flags_horizontal = 3 10 | size_flags_vertical = 3 11 | theme = ExtResource( 2 ) 12 | script = ExtResource( 1 ) 13 | 14 | [node name="VBoxContainer" type="VBoxContainer" parent="."] 15 | anchor_right = 1.0 16 | anchor_bottom = 1.0 17 | size_flags_horizontal = 3 18 | size_flags_vertical = 3 19 | 20 | [node name="LabelTitle" type="Label" parent="VBoxContainer"] 21 | margin_right = 720.0 22 | margin_bottom = 71.0 23 | size_flags_horizontal = 3 24 | size_flags_vertical = 7 25 | text = "Leaderboards" 26 | align = 1 27 | valign = 1 28 | 29 | [node name="LineEditLeaderboardsOutput" type="LineEdit" parent="VBoxContainer"] 30 | margin_top = 75.0 31 | margin_right = 720.0 32 | margin_bottom = 147.0 33 | size_flags_horizontal = 3 34 | size_flags_vertical = 3 35 | align = 1 36 | virtual_keyboard_enabled = false 37 | placeholder_text = "Output" 38 | caret_blink = true 39 | caret_blink_speed = 0.5 40 | 41 | [node name="LabelEndpoints" type="Label" parent="VBoxContainer"] 42 | margin_top = 151.0 43 | margin_right = 720.0 44 | margin_bottom = 222.0 45 | size_flags_horizontal = 3 46 | size_flags_vertical = 7 47 | text = "Endpoints" 48 | align = 1 49 | valign = 2 50 | 51 | [node name="ButtonShowAllLeaderboards" type="Button" parent="VBoxContainer"] 52 | margin_top = 226.0 53 | margin_right = 720.0 54 | margin_bottom = 298.0 55 | focus_mode = 0 56 | size_flags_horizontal = 3 57 | size_flags_vertical = 3 58 | enabled_focus_mode = 0 59 | text = "Show All Leaderboards" 60 | expand_icon = true 61 | 62 | [node name="ButtonShowLeaderboard" type="Button" parent="VBoxContainer"] 63 | margin_top = 302.0 64 | margin_right = 720.0 65 | margin_bottom = 373.0 66 | focus_mode = 0 67 | size_flags_horizontal = 3 68 | size_flags_vertical = 3 69 | enabled_focus_mode = 0 70 | text = "Show Leaderboard (LId)" 71 | expand_icon = true 72 | 73 | [node name="ButtonShowLBForTS" type="Button" parent="VBoxContainer"] 74 | margin_top = 377.0 75 | margin_right = 720.0 76 | margin_bottom = 449.0 77 | focus_mode = 0 78 | size_flags_horizontal = 3 79 | size_flags_vertical = 3 80 | enabled_focus_mode = 0 81 | text = "Show LB For TS (LId, TSpan)" 82 | expand_icon = true 83 | 84 | [node name="ButtonShowLBForTSAndCollection" type="Button" parent="VBoxContainer"] 85 | margin_top = 453.0 86 | margin_right = 720.0 87 | margin_bottom = 524.0 88 | focus_mode = 0 89 | size_flags_horizontal = 3 90 | size_flags_vertical = 3 91 | enabled_focus_mode = 0 92 | text = "Show LB For TS And Coll (LId, TSpan, Coll)" 93 | expand_icon = true 94 | 95 | [node name="ButtonSubmitScore" type="Button" parent="VBoxContainer"] 96 | margin_top = 528.0 97 | margin_right = 720.0 98 | margin_bottom = 600.0 99 | focus_mode = 0 100 | size_flags_horizontal = 3 101 | size_flags_vertical = 3 102 | enabled_focus_mode = 0 103 | text = "Submit Score (LId, Score)" 104 | expand_icon = true 105 | 106 | [node name="ButtonLoadPlayerScore" type="Button" parent="VBoxContainer"] 107 | margin_top = 604.0 108 | margin_right = 720.0 109 | margin_bottom = 675.0 110 | focus_mode = 0 111 | size_flags_horizontal = 3 112 | size_flags_vertical = 3 113 | enabled_focus_mode = 0 114 | text = "Load Player Score (LId, TSpan, Coll)" 115 | expand_icon = true 116 | 117 | [node name="ButtonLoadAllLeaderboards" type="Button" parent="VBoxContainer"] 118 | margin_top = 679.0 119 | margin_right = 720.0 120 | margin_bottom = 751.0 121 | focus_mode = 0 122 | size_flags_horizontal = 3 123 | size_flags_vertical = 3 124 | enabled_focus_mode = 0 125 | text = "Load All Leaderboards (ForceReload)" 126 | expand_icon = true 127 | 128 | [node name="ButtonLoadLeaderboard" type="Button" parent="VBoxContainer"] 129 | margin_top = 755.0 130 | margin_right = 720.0 131 | margin_bottom = 826.0 132 | focus_mode = 0 133 | size_flags_horizontal = 3 134 | size_flags_vertical = 3 135 | enabled_focus_mode = 0 136 | text = "Load Leaderboard (LId, ForceReload)" 137 | expand_icon = true 138 | 139 | [node name="LabelParameters" type="Label" parent="VBoxContainer"] 140 | margin_top = 830.0 141 | margin_right = 720.0 142 | margin_bottom = 902.0 143 | size_flags_horizontal = 3 144 | size_flags_vertical = 7 145 | text = "Parameters" 146 | align = 1 147 | valign = 2 148 | 149 | [node name="LineEditLeaderboardId" type="LineEdit" parent="VBoxContainer"] 150 | margin_top = 906.0 151 | margin_right = 720.0 152 | margin_bottom = 977.0 153 | size_flags_horizontal = 3 154 | size_flags_vertical = 3 155 | text = "CgkIy_Lnrp4ZEAIQDg" 156 | align = 1 157 | placeholder_text = "Leaderboard Id (LId)" 158 | caret_blink = true 159 | caret_blink_speed = 0.5 160 | 161 | [node name="SpinBoxScore" type="SpinBox" parent="VBoxContainer"] 162 | margin_top = 981.0 163 | margin_right = 720.0 164 | margin_bottom = 1053.0 165 | size_flags_horizontal = 3 166 | size_flags_vertical = 3 167 | max_value = 1e+10 168 | value = 10.0 169 | rounded = true 170 | align = 1 171 | suffix = "Score" 172 | 173 | [node name="CheckButtonLeaderboardsForceReload" type="CheckButton" parent="VBoxContainer"] 174 | margin_top = 1057.0 175 | margin_right = 720.0 176 | margin_bottom = 1128.0 177 | size_flags_horizontal = 3 178 | size_flags_vertical = 3 179 | pressed = true 180 | text = "Force Reload" 181 | align = 1 182 | 183 | [node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] 184 | margin_top = 1132.0 185 | margin_right = 720.0 186 | margin_bottom = 1204.0 187 | size_flags_horizontal = 3 188 | size_flags_vertical = 3 189 | 190 | [node name="Label" type="Label" parent="VBoxContainer/HBoxContainer"] 191 | margin_right = 356.0 192 | margin_bottom = 72.0 193 | size_flags_horizontal = 3 194 | size_flags_vertical = 7 195 | size_flags_stretch_ratio = 2.0 196 | text = "Timespan (TSpan):" 197 | valign = 1 198 | 199 | [node name="HSliderTimespan" type="HSlider" parent="VBoxContainer/HBoxContainer"] 200 | margin_left = 360.0 201 | margin_right = 538.0 202 | margin_bottom = 72.0 203 | size_flags_horizontal = 3 204 | size_flags_vertical = 3 205 | max_value = 2.0 206 | value = 2.0 207 | rounded = true 208 | 209 | [node name="Label2" type="Label" parent="VBoxContainer/HBoxContainer"] 210 | margin_left = 542.0 211 | margin_right = 720.0 212 | margin_bottom = 72.0 213 | size_flags_horizontal = 3 214 | size_flags_vertical = 5 215 | text = " Daily/Weekly/All" 216 | valign = 1 217 | 218 | [node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer"] 219 | margin_top = 1208.0 220 | margin_right = 720.0 221 | margin_bottom = 1280.0 222 | size_flags_horizontal = 3 223 | size_flags_vertical = 3 224 | 225 | [node name="Label" type="Label" parent="VBoxContainer/HBoxContainer2"] 226 | margin_right = 356.0 227 | margin_bottom = 72.0 228 | size_flags_horizontal = 3 229 | size_flags_vertical = 7 230 | size_flags_stretch_ratio = 2.0 231 | text = "Collection (Coll):" 232 | valign = 1 233 | 234 | [node name="HSliderLeaderboardsCollection" type="HSlider" parent="VBoxContainer/HBoxContainer2"] 235 | margin_left = 360.0 236 | margin_right = 538.0 237 | margin_bottom = 72.0 238 | size_flags_horizontal = 3 239 | size_flags_vertical = 3 240 | max_value = 3.0 241 | step = 3.0 242 | rounded = true 243 | 244 | [node name="Label3" type="Label" parent="VBoxContainer/HBoxContainer2"] 245 | margin_left = 542.0 246 | margin_right = 720.0 247 | margin_bottom = 72.0 248 | size_flags_horizontal = 3 249 | size_flags_vertical = 5 250 | text = " Public/Friends " 251 | valign = 1 252 | 253 | [connection signal="pressed" from="VBoxContainer/ButtonShowAllLeaderboards" to="." method="_on_ButtonShowAllLeaderboards_pressed"] 254 | [connection signal="pressed" from="VBoxContainer/ButtonShowLeaderboard" to="." method="_on_ButtonShowLeaderboard_pressed"] 255 | [connection signal="pressed" from="VBoxContainer/ButtonShowLBForTS" to="." method="_on_ButtonShowLBForTS_pressed"] 256 | [connection signal="pressed" from="VBoxContainer/ButtonShowLBForTSAndCollection" to="." method="_on_ButtonShowLBForTSAndCollection_pressed"] 257 | [connection signal="pressed" from="VBoxContainer/ButtonSubmitScore" to="." method="_on_ButtonSubmitScore_pressed"] 258 | [connection signal="pressed" from="VBoxContainer/ButtonLoadPlayerScore" to="." method="_on_ButtonLoadPlayerScore_pressed"] 259 | [connection signal="pressed" from="VBoxContainer/ButtonLoadAllLeaderboards" to="." method="_on_ButtonLoadAllLeaderboards_pressed"] 260 | [connection signal="pressed" from="VBoxContainer/ButtonLoadLeaderboard" to="." method="_on_ButtonLoadLeaderboard_pressed"] 261 | -------------------------------------------------------------------------------- /example/main.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | 4 | # Variables 5 | onready var _container_screens: Container = find_node("ContainerScreens") 6 | onready var _container_footer: Container = find_node("ContainerFooter") 7 | 8 | 9 | # Built-in overrides 10 | func _ready() -> void: 11 | show_screen("Menu") 12 | 13 | 14 | # Public methods 15 | func show_screen(screen: String) -> void: 16 | _container_footer.visible = screen != "Menu" 17 | 18 | for c in _container_screens.get_children(): 19 | var child: Control = c 20 | child.visible = child.name == screen 21 | 22 | 23 | # Event handlers 24 | # Buttons 25 | func _on_ButtonBack_pressed() -> void: 26 | show_screen("Menu") 27 | -------------------------------------------------------------------------------- /example/main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=10 format=2] 2 | 3 | [ext_resource path="res://example/main.gd" type="Script" id=1] 4 | [ext_resource path="res://example/events.tscn" type="PackedScene" id=2] 5 | [ext_resource path="res://example/leaderboards.tscn" type="PackedScene" id=3] 6 | [ext_resource path="res://example/achievements.tscn" type="PackedScene" id=4] 7 | [ext_resource path="res://example/snapshots.tscn" type="PackedScene" id=5] 8 | [ext_resource path="res://example/players.tscn" type="PackedScene" id=6] 9 | [ext_resource path="res://example/sign_in.tscn" type="PackedScene" id=7] 10 | [ext_resource path="res://example/menu.tscn" type="PackedScene" id=8] 11 | [ext_resource path="res://example/resources/theme.tres" type="Theme" id=9] 12 | 13 | [node name="Main" type="Control" groups=["main"]] 14 | anchor_right = 1.0 15 | anchor_bottom = 1.0 16 | script = ExtResource( 1 ) 17 | 18 | [node name="MarginContainer" type="MarginContainer" parent="."] 19 | anchor_right = 1.0 20 | anchor_bottom = 1.0 21 | theme = ExtResource( 9 ) 22 | custom_constants/margin_right = 16 23 | custom_constants/margin_top = 32 24 | custom_constants/margin_left = 16 25 | custom_constants/margin_bottom = 32 26 | 27 | [node name="MainContainer" type="VBoxContainer" parent="MarginContainer"] 28 | margin_left = 16.0 29 | margin_top = 32.0 30 | margin_right = 704.0 31 | margin_bottom = 1248.0 32 | 33 | [node name="ContainerScreens" type="VBoxContainer" parent="MarginContainer/MainContainer"] 34 | margin_right = 688.0 35 | margin_bottom = 1096.0 36 | size_flags_horizontal = 3 37 | size_flags_vertical = 3 38 | 39 | [node name="Menu" parent="MarginContainer/MainContainer/ContainerScreens" instance=ExtResource( 8 )] 40 | anchor_right = 0.0 41 | anchor_bottom = 0.0 42 | margin_right = 688.0 43 | margin_bottom = 1096.0 44 | 45 | [node name="Achievements" parent="MarginContainer/MainContainer/ContainerScreens" instance=ExtResource( 4 )] 46 | visible = false 47 | anchor_right = 0.0 48 | anchor_bottom = 0.0 49 | margin_top = 366.0 50 | margin_right = 688.0 51 | margin_bottom = 729.0 52 | 53 | [node name="Events" parent="MarginContainer/MainContainer/ContainerScreens" instance=ExtResource( 2 )] 54 | visible = false 55 | anchor_right = 0.0 56 | anchor_bottom = 0.0 57 | margin_top = 550.0 58 | margin_right = 688.0 59 | margin_bottom = 1096.0 60 | 61 | [node name="Leaderboards" parent="MarginContainer/MainContainer/ContainerScreens" instance=ExtResource( 3 )] 62 | visible = false 63 | anchor_right = 0.0 64 | anchor_bottom = 0.0 65 | margin_top = 550.0 66 | margin_right = 688.0 67 | margin_bottom = 1096.0 68 | 69 | [node name="Players" parent="MarginContainer/MainContainer/ContainerScreens" instance=ExtResource( 6 )] 70 | visible = false 71 | anchor_right = 0.0 72 | anchor_bottom = 0.0 73 | margin_top = 550.0 74 | margin_right = 688.0 75 | margin_bottom = 1096.0 76 | 77 | [node name="SignIn" parent="MarginContainer/MainContainer/ContainerScreens" instance=ExtResource( 7 )] 78 | visible = false 79 | anchor_right = 0.0 80 | anchor_bottom = 0.0 81 | margin_top = 550.0 82 | margin_right = 688.0 83 | margin_bottom = 1096.0 84 | 85 | [node name="Snapshots" parent="MarginContainer/MainContainer/ContainerScreens" instance=ExtResource( 5 )] 86 | visible = false 87 | anchor_right = 0.0 88 | anchor_bottom = 0.0 89 | margin_top = 550.0 90 | margin_right = 688.0 91 | margin_bottom = 1096.0 92 | 93 | [node name="ContainerFooter" type="MarginContainer" parent="MarginContainer/MainContainer"] 94 | margin_top = 1100.0 95 | margin_right = 688.0 96 | margin_bottom = 1216.0 97 | custom_constants/margin_top = 16 98 | 99 | [node name="ButtonBack" type="Button" parent="MarginContainer/MainContainer/ContainerFooter"] 100 | margin_left = 219.0 101 | margin_top = 16.0 102 | margin_right = 469.0 103 | margin_bottom = 116.0 104 | rect_min_size = Vector2( 250, 100 ) 105 | focus_mode = 0 106 | size_flags_horizontal = 4 107 | size_flags_vertical = 8 108 | enabled_focus_mode = 0 109 | text = "Back" 110 | expand_icon = true 111 | 112 | [connection signal="pressed" from="MarginContainer/MainContainer/ContainerFooter/ButtonBack" to="." method="_on_ButtonBack_pressed"] 113 | -------------------------------------------------------------------------------- /example/menu.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | 4 | # Variables 5 | onready var _menu_container: Container = find_node("MenuContainer") 6 | 7 | 8 | # Built-in overrides 9 | func _ready() -> void: 10 | _connect_menu_buttons() 11 | 12 | 13 | # Private methods 14 | func _connect_menu_buttons() -> void: 15 | for c in _menu_container.get_children(): 16 | var child: Control = c 17 | 18 | if not child.has_signal("pressed"): 19 | continue 20 | 21 | var screen_name := child.name.replace("Button", "") 22 | child.connect("pressed", self, "_on_button_pressed", [screen_name]) 23 | 24 | 25 | # Event handlers 26 | func _on_button_pressed(screen_name: String) -> void: 27 | get_tree().call_group("main", "show_screen", screen_name) 28 | -------------------------------------------------------------------------------- /example/menu.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://example/menu.gd" type="Script" id=1] 4 | [ext_resource path="res://example/resources/theme.tres" type="Theme" id=2] 5 | [ext_resource path="res://icon.png" type="Texture" id=3] 6 | 7 | [node name="Menu" type="Control"] 8 | anchor_right = 1.0 9 | anchor_bottom = 1.0 10 | size_flags_horizontal = 3 11 | size_flags_vertical = 3 12 | theme = ExtResource( 2 ) 13 | script = ExtResource( 1 ) 14 | 15 | [node name="MenuContainer" type="VBoxContainer" parent="."] 16 | anchor_right = 1.0 17 | anchor_bottom = 1.0 18 | 19 | [node name="HBoxContainer" type="HBoxContainer" parent="MenuContainer"] 20 | margin_right = 720.0 21 | margin_bottom = 179.0 22 | size_flags_horizontal = 3 23 | size_flags_vertical = 3 24 | 25 | [node name="Control" type="Control" parent="MenuContainer/HBoxContainer"] 26 | margin_right = 83.0 27 | margin_bottom = 179.0 28 | size_flags_horizontal = 3 29 | size_flags_vertical = 3 30 | size_flags_stretch_ratio = 0.2 31 | 32 | [node name="TextureRect" type="TextureRect" parent="MenuContainer/HBoxContainer"] 33 | margin_left = 87.0 34 | margin_right = 297.0 35 | margin_bottom = 179.0 36 | size_flags_horizontal = 3 37 | size_flags_vertical = 3 38 | size_flags_stretch_ratio = 0.5 39 | texture = ExtResource( 3 ) 40 | expand = true 41 | stretch_mode = 6 42 | 43 | [node name="LabelHeader" type="Label" parent="MenuContainer/HBoxContainer"] 44 | margin_left = 301.0 45 | margin_right = 720.0 46 | margin_bottom = 179.0 47 | size_flags_horizontal = 3 48 | size_flags_vertical = 7 49 | text = "Google Play Games Services 50 | for Godot (Example Project)" 51 | valign = 1 52 | 53 | [node name="ButtonAchievements" type="Button" parent="MenuContainer"] 54 | margin_top = 183.0 55 | margin_right = 720.0 56 | margin_bottom = 362.0 57 | size_flags_horizontal = 3 58 | size_flags_vertical = 3 59 | text = "Achievements" 60 | 61 | [node name="ButtonEvents" type="Button" parent="MenuContainer"] 62 | margin_top = 366.0 63 | margin_right = 720.0 64 | margin_bottom = 546.0 65 | size_flags_horizontal = 3 66 | size_flags_vertical = 3 67 | text = "Events" 68 | 69 | [node name="ButtonLeaderboards" type="Button" parent="MenuContainer"] 70 | margin_top = 550.0 71 | margin_right = 720.0 72 | margin_bottom = 729.0 73 | size_flags_horizontal = 3 74 | size_flags_vertical = 3 75 | text = "Leaderboards" 76 | 77 | [node name="ButtonPlayers" type="Button" parent="MenuContainer"] 78 | margin_top = 733.0 79 | margin_right = 720.0 80 | margin_bottom = 913.0 81 | size_flags_horizontal = 3 82 | size_flags_vertical = 3 83 | text = "Players" 84 | 85 | [node name="ButtonSignIn" type="Button" parent="MenuContainer"] 86 | margin_top = 917.0 87 | margin_right = 720.0 88 | margin_bottom = 1096.0 89 | size_flags_horizontal = 3 90 | size_flags_vertical = 3 91 | text = "Sign In" 92 | 93 | [node name="ButtonSnapshots" type="Button" parent="MenuContainer"] 94 | margin_top = 1100.0 95 | margin_right = 720.0 96 | margin_bottom = 1280.0 97 | size_flags_horizontal = 3 98 | size_flags_vertical = 3 99 | text = "Snapshots" 100 | -------------------------------------------------------------------------------- /example/players.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | 4 | # Variables 5 | onready var _line_edit_players_output: LineEdit = find_node("LineEditPlayersOutput") 6 | onready var _line_edit_player_id: LineEdit = find_node("LineEditPlayerId") 7 | onready var _line_edit_player_name: LineEdit = find_node("LineEditPlayerName") 8 | onready var _line_edit_current_player_name: LineEdit = find_node("LineEditCurrentPlayerName") 9 | onready var _spin_box_page_size: SpinBox = find_node("SpinBoxPageSize") 10 | onready var _check_button_players_force_reload: CheckButton = find_node("CheckButtonPlayersForceReload") 11 | onready var _check_button_ask_permission: CheckButton = find_node("CheckButtonAskPermission") 12 | 13 | 14 | # Built-in overrides 15 | func _ready() -> void: 16 | GooglePlayGamesServices.connect("players_current_loaded", self, "_on_players_current_loaded") 17 | GooglePlayGamesServices.connect("players_friends_loaded", self, "_on_players_friends_loaded") 18 | GooglePlayGamesServices.connect("players_searched", self, "_on_players_searched") 19 | 20 | 21 | # Event handlers 22 | # Buttons 23 | func _on_ButtonCompareProfile_pressed() -> void: 24 | GooglePlayGamesServices.players_compare_profile(_line_edit_player_id.text) 25 | 26 | 27 | func _on_ButtonCompareProfileWithAltNameHints_pressed() -> void: 28 | GooglePlayGamesServices.players_compare_profile_with_alternative_name_hints( 29 | _line_edit_player_id.text, 30 | _line_edit_player_name.text, 31 | _line_edit_current_player_name.text) 32 | 33 | 34 | func _on_ButtonLoadCurrentPlayer_pressed() -> void: 35 | GooglePlayGamesServices.players_load_current(_check_button_players_force_reload.pressed) 36 | 37 | 38 | func _on_ButtonLoadFriends_pressed() -> void: 39 | GooglePlayGamesServices.players_load_friends( 40 | int(_spin_box_page_size.value), 41 | _check_button_players_force_reload.pressed, 42 | _check_button_ask_permission.pressed) 43 | 44 | 45 | func _on_ButtonSearchPlayer_pressed() -> void: 46 | GooglePlayGamesServices.players_search() 47 | 48 | 49 | # Return values 50 | func _on_players_current_loaded(player: Dictionary) -> void: 51 | var value := "player: " + str(player) 52 | _line_edit_players_output.text = value 53 | prints(value) 54 | 55 | 56 | func _on_players_friends_loaded(friends: Array) -> void: 57 | var value := "friends: " + str(friends) 58 | _line_edit_players_output.text = value 59 | prints(value) 60 | 61 | 62 | func _on_players_searched(player: Dictionary) -> void: 63 | var value := "player: " + str(player) 64 | _line_edit_players_output.text = value 65 | prints(value) 66 | -------------------------------------------------------------------------------- /example/players.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://example/players.gd" type="Script" id=1] 4 | [ext_resource path="res://example/resources/theme.tres" type="Theme" id=2] 5 | 6 | [node name="Players" type="Control"] 7 | anchor_right = 1.0 8 | anchor_bottom = 1.0 9 | size_flags_horizontal = 3 10 | size_flags_vertical = 3 11 | theme = ExtResource( 2 ) 12 | script = ExtResource( 1 ) 13 | 14 | [node name="VBoxContainer" type="VBoxContainer" parent="."] 15 | anchor_right = 1.0 16 | anchor_bottom = 1.0 17 | size_flags_horizontal = 3 18 | size_flags_vertical = 3 19 | 20 | [node name="LabelTitle" type="Label" parent="VBoxContainer"] 21 | margin_right = 720.0 22 | margin_bottom = 81.0 23 | size_flags_horizontal = 3 24 | size_flags_vertical = 7 25 | text = "Players" 26 | align = 1 27 | valign = 1 28 | 29 | [node name="LineEditPlayersOutput" type="LineEdit" parent="VBoxContainer"] 30 | margin_top = 85.0 31 | margin_right = 720.0 32 | margin_bottom = 167.0 33 | size_flags_horizontal = 3 34 | size_flags_vertical = 3 35 | align = 1 36 | virtual_keyboard_enabled = false 37 | placeholder_text = "Output" 38 | caret_blink = true 39 | caret_blink_speed = 0.5 40 | 41 | [node name="LabelEndpoints" type="Label" parent="VBoxContainer"] 42 | margin_top = 171.0 43 | margin_right = 720.0 44 | margin_bottom = 252.0 45 | size_flags_horizontal = 3 46 | size_flags_vertical = 7 47 | text = "Endpoints" 48 | align = 1 49 | valign = 2 50 | 51 | [node name="ButtonCompareProfile" type="Button" parent="VBoxContainer"] 52 | margin_top = 256.0 53 | margin_right = 720.0 54 | margin_bottom = 338.0 55 | focus_mode = 0 56 | size_flags_horizontal = 3 57 | size_flags_vertical = 3 58 | enabled_focus_mode = 0 59 | text = "Compare Profile (PId)" 60 | expand_icon = true 61 | 62 | [node name="ButtonCompareProfileWithAltNameHints" type="Button" parent="VBoxContainer"] 63 | margin_top = 342.0 64 | margin_right = 720.0 65 | margin_bottom = 423.0 66 | focus_mode = 0 67 | size_flags_horizontal = 3 68 | size_flags_vertical = 3 69 | enabled_focus_mode = 0 70 | text = "Comp Profile W/ Alt Name (PId, OName, CName)" 71 | expand_icon = true 72 | 73 | [node name="ButtonLoadCurrentPlayer" type="Button" parent="VBoxContainer"] 74 | margin_top = 427.0 75 | margin_right = 720.0 76 | margin_bottom = 509.0 77 | focus_mode = 0 78 | size_flags_horizontal = 3 79 | size_flags_vertical = 3 80 | enabled_focus_mode = 0 81 | text = "Load Current Player (ForceReload)" 82 | expand_icon = true 83 | 84 | [node name="ButtonLoadFriends" type="Button" parent="VBoxContainer"] 85 | margin_top = 513.0 86 | margin_right = 720.0 87 | margin_bottom = 595.0 88 | focus_mode = 0 89 | size_flags_horizontal = 3 90 | size_flags_vertical = 3 91 | enabled_focus_mode = 0 92 | text = "Load Friends (PageSize, ForceReload, AskPerm)" 93 | expand_icon = true 94 | 95 | [node name="ButtonSearchPlayer" type="Button" parent="VBoxContainer"] 96 | margin_top = 599.0 97 | margin_right = 720.0 98 | margin_bottom = 680.0 99 | focus_mode = 0 100 | size_flags_horizontal = 3 101 | size_flags_vertical = 3 102 | enabled_focus_mode = 0 103 | text = "Search Player" 104 | expand_icon = true 105 | 106 | [node name="LabelParameters" type="Label" parent="VBoxContainer"] 107 | margin_top = 684.0 108 | margin_right = 720.0 109 | margin_bottom = 766.0 110 | size_flags_horizontal = 3 111 | size_flags_vertical = 7 112 | text = "Parameters" 113 | align = 1 114 | valign = 2 115 | 116 | [node name="LineEditPlayerId" type="LineEdit" parent="VBoxContainer"] 117 | margin_top = 770.0 118 | margin_right = 720.0 119 | margin_bottom = 851.0 120 | size_flags_horizontal = 3 121 | size_flags_vertical = 3 122 | align = 1 123 | placeholder_text = "Other Player Id (PId)" 124 | caret_blink = true 125 | caret_blink_speed = 0.5 126 | 127 | [node name="LineEditPlayerName" type="LineEdit" parent="VBoxContainer"] 128 | margin_top = 855.0 129 | margin_right = 720.0 130 | margin_bottom = 937.0 131 | size_flags_horizontal = 3 132 | size_flags_vertical = 3 133 | align = 1 134 | placeholder_text = "Other Player Name (OName)" 135 | caret_blink = true 136 | caret_blink_speed = 0.5 137 | 138 | [node name="LineEditCurrentPlayerName" type="LineEdit" parent="VBoxContainer"] 139 | margin_top = 941.0 140 | margin_right = 720.0 141 | margin_bottom = 1023.0 142 | size_flags_horizontal = 3 143 | size_flags_vertical = 3 144 | align = 1 145 | placeholder_text = "Current Player Name (CName)" 146 | caret_blink = true 147 | caret_blink_speed = 0.5 148 | 149 | [node name="SpinBoxPageSize" type="SpinBox" parent="VBoxContainer"] 150 | margin_top = 1027.0 151 | margin_right = 720.0 152 | margin_bottom = 1108.0 153 | size_flags_horizontal = 3 154 | size_flags_vertical = 3 155 | min_value = 1.0 156 | max_value = 50.0 157 | value = 1.0 158 | rounded = true 159 | align = 1 160 | prefix = "Page Size" 161 | 162 | [node name="CheckButtonPlayersForceReload" type="CheckButton" parent="VBoxContainer"] 163 | margin_top = 1112.0 164 | margin_right = 720.0 165 | margin_bottom = 1194.0 166 | size_flags_horizontal = 3 167 | size_flags_vertical = 3 168 | pressed = true 169 | text = "Force Reload" 170 | align = 1 171 | 172 | [node name="CheckButtonAskPermission" type="CheckButton" parent="VBoxContainer"] 173 | margin_top = 1198.0 174 | margin_right = 720.0 175 | margin_bottom = 1280.0 176 | size_flags_horizontal = 3 177 | size_flags_vertical = 3 178 | text = "Ask Permission" 179 | align = 1 180 | 181 | [connection signal="pressed" from="VBoxContainer/ButtonCompareProfile" to="." method="_on_ButtonCompareProfile_pressed"] 182 | [connection signal="pressed" from="VBoxContainer/ButtonCompareProfileWithAltNameHints" to="." method="_on_ButtonCompareProfileWithAltNameHints_pressed"] 183 | [connection signal="pressed" from="VBoxContainer/ButtonLoadCurrentPlayer" to="." method="_on_ButtonLoadCurrentPlayer_pressed"] 184 | [connection signal="pressed" from="VBoxContainer/ButtonLoadFriends" to="." method="_on_ButtonLoadFriends_pressed"] 185 | [connection signal="pressed" from="VBoxContainer/ButtonSearchPlayer" to="." method="_on_ButtonSearchPlayer_pressed"] 186 | -------------------------------------------------------------------------------- /example/resources/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Iakobs/godot-google-play-game-services-plugin/6265a74c370e63d7194fc0035e3770a1bf0d1e43/example/resources/Roboto-Regular.ttf -------------------------------------------------------------------------------- /example/resources/theme.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Theme" load_steps=3 format=2] 2 | 3 | [ext_resource path="res://example/resources/Roboto-Regular.ttf" type="DynamicFontData" id=1] 4 | 5 | [sub_resource type="DynamicFont" id=1] 6 | size = 22 7 | outline_color = Color( 0, 0, 0, 1 ) 8 | use_filter = true 9 | font_data = ExtResource( 1 ) 10 | 11 | [resource] 12 | default_font = SubResource( 1 ) 13 | -------------------------------------------------------------------------------- /example/sign_in.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | 4 | # Variables 5 | onready var _line_edit_sign_in_output: LineEdit = find_node("LineEditSignInOutput") 6 | 7 | 8 | # Built-in overrides 9 | func _ready() -> void: 10 | GooglePlayGamesServices.connect("sign_in_user_authenticated", self, "_on_sign_in_user_authenticated") 11 | 12 | 13 | # Event handlers 14 | # Buttons 15 | func _on_ButtonIsAuthenticated_pressed() -> void: 16 | GooglePlayGamesServices.sign_in_is_authenticated() 17 | 18 | 19 | func _on_ButtonSignIn_pressed() -> void: 20 | GooglePlayGamesServices.sign_in_show_popup() 21 | 22 | 23 | # Return values 24 | func _on_sign_in_user_authenticated(is_authenticated: bool) -> void: 25 | var value := "is_authenticated: " + str(is_authenticated) 26 | _line_edit_sign_in_output.text = value 27 | prints(value) 28 | -------------------------------------------------------------------------------- /example/sign_in.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://example/sign_in.gd" type="Script" id=1] 4 | [ext_resource path="res://example/resources/theme.tres" type="Theme" id=2] 5 | 6 | [node name="SignIn" type="Control"] 7 | anchor_right = 1.0 8 | anchor_bottom = 1.0 9 | size_flags_horizontal = 3 10 | size_flags_vertical = 3 11 | theme = ExtResource( 2 ) 12 | script = ExtResource( 1 ) 13 | 14 | [node name="VBoxContainer" type="VBoxContainer" parent="."] 15 | anchor_right = 1.0 16 | anchor_bottom = 1.0 17 | size_flags_horizontal = 3 18 | size_flags_vertical = 3 19 | 20 | [node name="LabelTitle" type="Label" parent="VBoxContainer"] 21 | margin_right = 720.0 22 | margin_bottom = 140.0 23 | size_flags_horizontal = 3 24 | size_flags_vertical = 7 25 | text = "Sign In" 26 | align = 1 27 | valign = 1 28 | 29 | [node name="LineEditSignInOutput" type="LineEdit" parent="VBoxContainer"] 30 | margin_top = 144.0 31 | margin_right = 720.0 32 | margin_bottom = 284.0 33 | size_flags_horizontal = 3 34 | size_flags_vertical = 3 35 | align = 1 36 | placeholder_text = "Output" 37 | caret_blink = true 38 | caret_blink_speed = 0.5 39 | 40 | [node name="LabelEndpoints" type="Label" parent="VBoxContainer"] 41 | margin_top = 288.0 42 | margin_right = 720.0 43 | margin_bottom = 428.0 44 | size_flags_horizontal = 3 45 | size_flags_vertical = 7 46 | text = "Endpoints" 47 | align = 1 48 | valign = 2 49 | 50 | [node name="ButtonIsAuthenticated" type="Button" parent="VBoxContainer"] 51 | margin_top = 432.0 52 | margin_right = 720.0 53 | margin_bottom = 572.0 54 | focus_mode = 0 55 | size_flags_horizontal = 3 56 | size_flags_vertical = 3 57 | enabled_focus_mode = 0 58 | text = "Is Authenticated" 59 | expand_icon = true 60 | 61 | [node name="ButtonSignIn" type="Button" parent="VBoxContainer"] 62 | margin_top = 576.0 63 | margin_right = 720.0 64 | margin_bottom = 716.0 65 | focus_mode = 0 66 | size_flags_horizontal = 3 67 | size_flags_vertical = 3 68 | enabled_focus_mode = 0 69 | text = "SignIn" 70 | expand_icon = true 71 | 72 | [node name="Control2" type="Control" parent="VBoxContainer"] 73 | margin_top = 720.0 74 | margin_right = 720.0 75 | margin_bottom = 1280.0 76 | size_flags_horizontal = 3 77 | size_flags_vertical = 3 78 | size_flags_stretch_ratio = 4.0 79 | 80 | [connection signal="pressed" from="VBoxContainer/ButtonIsAuthenticated" to="." method="_on_ButtonIsAuthenticated_pressed"] 81 | [connection signal="pressed" from="VBoxContainer/ButtonSignIn" to="." method="_on_ButtonSignIn_pressed"] 82 | -------------------------------------------------------------------------------- /example/snapshots.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | 4 | # Variables 5 | onready var _line_edit_snapshots_output: LineEdit = find_node("LineEditSnapshotsOutput") 6 | onready var _line_edit_file_name: LineEdit = find_node("LineEditFileName") 7 | onready var _line_edit_description: LineEdit = find_node("LineEditDescription") 8 | onready var _line_edit_save_data: LineEdit = find_node("LineEditSaveData") 9 | onready var _spin_box_played_time_ms: SpinBox = find_node("SpinBoxPlayedTimeMs") 10 | onready var _spin_box_progress_value: SpinBox = find_node("SpinBoxProgressValue") 11 | onready var _line_edit_title: LineEdit = find_node("LineEditTitle") 12 | onready var _check_button_allow_add_button: CheckButton = find_node("CheckButtonAllowAddButton") 13 | onready var _check_button_allow_delete: CheckButton = find_node("CheckButtonAllowDelete") 14 | onready var _spin_box_max_snapshots: SpinBox = find_node("SpinBoxMaxSnapshots") 15 | 16 | 17 | # Built-in overrides 18 | func _ready() -> void: 19 | GooglePlayGamesServices.connect("snapshots_game_saved", self, "_on_snapshots_game_saved") 20 | GooglePlayGamesServices.connect("snapshots_game_loaded", self, "_on_snapshots_game_loaded") 21 | GooglePlayGamesServices.connect("snapshots_conflict_emitted", self, "_on_snapshots_conflict_emitted") 22 | 23 | 24 | # Event handlers 25 | # Buttons 26 | func _on_ButtonLoadGame_pressed() -> void: 27 | GooglePlayGamesServices.snapshots_load_game(_line_edit_file_name.text) 28 | 29 | 30 | func _on_ButtonSaveGame_pressed() -> void: 31 | GooglePlayGamesServices.snapshots_save_game( 32 | _line_edit_file_name.text, 33 | _line_edit_description.text, 34 | _line_edit_save_data.text.to_utf8(), 35 | int(_spin_box_played_time_ms.value), 36 | int(_spin_box_progress_value.value)) 37 | 38 | 39 | func _on_ButtonShowSavedGames_pressed() -> void: 40 | GooglePlayGamesServices.snapshots_show_saved_games( 41 | _line_edit_title.text, 42 | _check_button_allow_add_button.pressed, 43 | _check_button_allow_delete.pressed, 44 | int(_spin_box_max_snapshots.value)) 45 | 46 | 47 | # Return values 48 | func _on_snapshots_game_saved(saved: bool, file_name: String, description: String) -> void: 49 | var value := "saved: " + str(saved) + ", file_name: " + file_name + ", description: " + description 50 | _line_edit_snapshots_output.text = value 51 | prints(value) 52 | 53 | 54 | func _on_snapshots_game_loaded(snapshot: Dictionary) -> void: 55 | var value := "snapshot: " + str(snapshot) 56 | _line_edit_snapshots_output.text = value 57 | prints(value) 58 | 59 | 60 | func _on_snapshots_conflict_emitted(conflict: Dictionary) -> void: 61 | var value := "conflict: " + str(conflict) 62 | _line_edit_snapshots_output.text = value 63 | prints(value) 64 | -------------------------------------------------------------------------------- /example/snapshots.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://example/snapshots.gd" type="Script" id=1] 4 | [ext_resource path="res://example/resources/theme.tres" type="Theme" id=2] 5 | 6 | [node name="Snapshots" type="Control"] 7 | anchor_right = 1.0 8 | anchor_bottom = 1.0 9 | size_flags_horizontal = 3 10 | size_flags_vertical = 3 11 | theme = ExtResource( 2 ) 12 | script = ExtResource( 1 ) 13 | 14 | [node name="VBoxContainer" type="VBoxContainer" parent="."] 15 | anchor_right = 1.0 16 | anchor_bottom = 1.0 17 | size_flags_horizontal = 3 18 | size_flags_vertical = 3 19 | 20 | [node name="LabelTitle" type="Label" parent="VBoxContainer"] 21 | margin_right = 720.0 22 | margin_bottom = 76.0 23 | size_flags_horizontal = 3 24 | size_flags_vertical = 7 25 | text = "Events" 26 | align = 1 27 | valign = 1 28 | 29 | [node name="LineEditSnapshotsOutput" type="LineEdit" parent="VBoxContainer"] 30 | margin_top = 80.0 31 | margin_right = 720.0 32 | margin_bottom = 156.0 33 | size_flags_horizontal = 3 34 | size_flags_vertical = 3 35 | align = 1 36 | virtual_keyboard_enabled = false 37 | placeholder_text = "Output" 38 | caret_blink = true 39 | caret_blink_speed = 0.5 40 | 41 | [node name="LabelEndpoints" type="Label" parent="VBoxContainer"] 42 | margin_top = 160.0 43 | margin_right = 720.0 44 | margin_bottom = 236.0 45 | size_flags_horizontal = 3 46 | size_flags_vertical = 7 47 | text = "Endpoints" 48 | align = 1 49 | valign = 2 50 | 51 | [node name="ButtonLoadGame" type="Button" parent="VBoxContainer"] 52 | margin_top = 240.0 53 | margin_right = 720.0 54 | margin_bottom = 317.0 55 | focus_mode = 0 56 | size_flags_horizontal = 3 57 | size_flags_vertical = 3 58 | enabled_focus_mode = 0 59 | text = "Load Game (File)" 60 | expand_icon = true 61 | 62 | [node name="ButtonSaveGame" type="Button" parent="VBoxContainer"] 63 | margin_top = 321.0 64 | margin_right = 720.0 65 | margin_bottom = 397.0 66 | focus_mode = 0 67 | size_flags_horizontal = 3 68 | size_flags_vertical = 3 69 | enabled_focus_mode = 0 70 | text = "Save Game (File, Desc, Data, Time, Progress)" 71 | expand_icon = true 72 | 73 | [node name="ButtonShowSavedGames" type="Button" parent="VBoxContainer"] 74 | margin_top = 401.0 75 | margin_right = 720.0 76 | margin_bottom = 477.0 77 | focus_mode = 0 78 | size_flags_horizontal = 3 79 | size_flags_vertical = 3 80 | enabled_focus_mode = 0 81 | text = "Show Saved Games (Title, AddBut, Del, Max)" 82 | expand_icon = true 83 | 84 | [node name="LabelParameters" type="Label" parent="VBoxContainer"] 85 | margin_top = 481.0 86 | margin_right = 720.0 87 | margin_bottom = 557.0 88 | size_flags_horizontal = 3 89 | size_flags_vertical = 7 90 | text = "Parameters" 91 | align = 1 92 | valign = 2 93 | 94 | [node name="LineEditFileName" type="LineEdit" parent="VBoxContainer"] 95 | margin_top = 561.0 96 | margin_right = 720.0 97 | margin_bottom = 638.0 98 | size_flags_horizontal = 3 99 | size_flags_vertical = 3 100 | text = "savefile" 101 | align = 1 102 | placeholder_text = "File Name" 103 | caret_blink = true 104 | caret_blink_speed = 0.5 105 | 106 | [node name="LineEditDescription" type="LineEdit" parent="VBoxContainer"] 107 | margin_top = 642.0 108 | margin_right = 720.0 109 | margin_bottom = 718.0 110 | size_flags_horizontal = 3 111 | size_flags_vertical = 3 112 | text = "This is a savegame description." 113 | align = 1 114 | placeholder_text = "Description" 115 | caret_blink = true 116 | caret_blink_speed = 0.5 117 | 118 | [node name="LineEditSaveData" type="LineEdit" parent="VBoxContainer"] 119 | margin_top = 722.0 120 | margin_right = 720.0 121 | margin_bottom = 798.0 122 | size_flags_horizontal = 3 123 | size_flags_vertical = 3 124 | text = "{\"test\": 1}" 125 | align = 1 126 | placeholder_text = "Save Data" 127 | caret_blink = true 128 | caret_blink_speed = 0.5 129 | 130 | [node name="SpinBoxPlayedTimeMs" type="SpinBox" parent="VBoxContainer"] 131 | margin_top = 802.0 132 | margin_right = 720.0 133 | margin_bottom = 878.0 134 | size_flags_horizontal = 3 135 | size_flags_vertical = 3 136 | max_value = 1e+17 137 | value = 2000.0 138 | rounded = true 139 | align = 1 140 | prefix = "Played Time:" 141 | suffix = "ms" 142 | 143 | [node name="SpinBoxProgressValue" type="SpinBox" parent="VBoxContainer"] 144 | margin_top = 882.0 145 | margin_right = 720.0 146 | margin_bottom = 959.0 147 | size_flags_horizontal = 3 148 | size_flags_vertical = 3 149 | min_value = 1.0 150 | max_value = 50.0 151 | value = 1.0 152 | rounded = true 153 | align = 1 154 | prefix = "Progress value:" 155 | 156 | [node name="LineEditTitle" type="LineEdit" parent="VBoxContainer"] 157 | margin_top = 963.0 158 | margin_right = 720.0 159 | margin_bottom = 1039.0 160 | size_flags_horizontal = 3 161 | size_flags_vertical = 3 162 | text = "Test Title" 163 | align = 1 164 | placeholder_text = "Title" 165 | caret_blink = true 166 | caret_blink_speed = 0.5 167 | 168 | [node name="CheckButtonAllowAddButton" type="CheckButton" parent="VBoxContainer"] 169 | margin_top = 1043.0 170 | margin_right = 720.0 171 | margin_bottom = 1119.0 172 | size_flags_horizontal = 3 173 | size_flags_vertical = 3 174 | pressed = true 175 | text = "Allow Add Button" 176 | align = 1 177 | 178 | [node name="CheckButtonAllowDelete" type="CheckButton" parent="VBoxContainer"] 179 | margin_top = 1123.0 180 | margin_right = 720.0 181 | margin_bottom = 1199.0 182 | size_flags_horizontal = 3 183 | size_flags_vertical = 3 184 | pressed = true 185 | text = "Allow Delete" 186 | align = 1 187 | 188 | [node name="SpinBoxMaxSnapshots" type="SpinBox" parent="VBoxContainer"] 189 | margin_top = 1203.0 190 | margin_right = 720.0 191 | margin_bottom = 1280.0 192 | size_flags_horizontal = 3 193 | size_flags_vertical = 3 194 | min_value = 1.0 195 | max_value = 50.0 196 | value = 10.0 197 | rounded = true 198 | align = 1 199 | prefix = "Max snapshots:" 200 | 201 | [connection signal="pressed" from="VBoxContainer/ButtonLoadGame" to="." method="_on_ButtonLoadGame_pressed"] 202 | [connection signal="pressed" from="VBoxContainer/ButtonSaveGame" to="." method="_on_ButtonSaveGame_pressed"] 203 | [connection signal="pressed" from="VBoxContainer/ButtonShowSavedGames" to="." method="_on_ButtonShowSavedGames_pressed"] 204 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Iakobs/godot-google-play-game-services-plugin/6265a74c370e63d7194fc0035e3770a1bf0d1e43/icon.png -------------------------------------------------------------------------------- /icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://icon.png" 13 | dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | process/normal_map_invert_y=false 32 | stream=false 33 | size_limit=0 34 | detect_3d=true 35 | svg/scale=1.0 36 | -------------------------------------------------------------------------------- /project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=4 10 | 11 | [application] 12 | 13 | config/name="Google Play Game Services Godot Plugin" 14 | config/description="A godot plugin to connect to the android godot plugin counterpart of the same name. 15 | The project includes a demo of the main features, showing one of the multiple ways 16 | of how to use the plugin." 17 | run/main_scene="res://example/main.tscn" 18 | boot_splash/image="res://icon.png" 19 | boot_splash/fullsize=false 20 | boot_splash/bg_color=Color( 0, 0, 0, 1 ) 21 | config/icon="res://icon.png" 22 | 23 | [autoload] 24 | 25 | GooglePlayGamesServices="*res://addons/google_play_game_services_manager/singleton.gd" 26 | 27 | [debug] 28 | 29 | gdscript/warnings/return_value_discarded=false 30 | 31 | [display] 32 | 33 | window/size/width=720 34 | window/size/height=1280 35 | window/size/test_width=540 36 | window/size/test_height=960 37 | window/handheld/orientation="portrait" 38 | window/stretch/mode="2d" 39 | window/stretch/aspect="keep_width" 40 | 41 | [editor] 42 | 43 | scene_naming=2 44 | 45 | [editor_plugins] 46 | 47 | enabled=PoolStringArray( "res://addons/google_play_game_services_manager/plugin.cfg" ) 48 | 49 | [gui] 50 | 51 | common/drop_mouse_on_gui_input_disabled=true 52 | 53 | [physics] 54 | 55 | common/enable_pause_aware_picking=true 56 | 57 | [rendering] 58 | 59 | quality/driver/driver_name="GLES2" 60 | vram_compression/import_etc=true 61 | vram_compression/import_etc2=false 62 | --------------------------------------------------------------------------------