├── .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 | 
2 |
3 | [](https://developer.android.com)
4 | [](https://github.com/godotengine/godot/)
5 | [](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 |
--------------------------------------------------------------------------------