mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-01-18 00:59:47 +00:00
Experiment with Steam achievements, using a new SteamManager class
This has no effect on non-Steam builds. Steam achievements are mostly for fun, but can also be educational because they can let users know of certain features and functionalities. It's using the GodotSteam GDExtension, but because I do not want to bloat the GitHub repository with things that are not needed for most builds, I decided not to include the GDExtension files, and instead check if the `Steam` class exists in `ClassDB`. The new SteamManager class pretty much does nothing on non-Steam builds, so do not worry about bloat. In the future we could even take advantage of more of Steam's features, such as Cloud storage for pxo files.
This commit is contained in:
parent
d58da13493
commit
f84f15b8ae
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -24,3 +24,5 @@ mono_crash.*.json
|
||||||
|
|
||||||
# Android ignores
|
# Android ignores
|
||||||
android/
|
android/
|
||||||
|
|
||||||
|
addons/godotsteam
|
||||||
|
|
|
@ -354,14 +354,14 @@ func open_v0_pxo_file(path: String, empty_project: bool) -> Project:
|
||||||
func save_pxo_file(
|
func save_pxo_file(
|
||||||
path: String, autosave: bool, include_blended := false, project := Global.current_project
|
path: String, autosave: bool, include_blended := false, project := Global.current_project
|
||||||
) -> bool:
|
) -> bool:
|
||||||
if !autosave:
|
if not autosave:
|
||||||
project.name = path.get_file().trim_suffix(".pxo")
|
project.name = path.get_file().trim_suffix(".pxo")
|
||||||
var serialized_data := project.serialize()
|
var serialized_data := project.serialize()
|
||||||
if !serialized_data:
|
if not serialized_data:
|
||||||
Global.popup_error(tr("File failed to save. Converting project data to dictionary failed."))
|
Global.popup_error(tr("File failed to save. Converting project data to dictionary failed."))
|
||||||
return false
|
return false
|
||||||
var to_save := JSON.stringify(serialized_data)
|
var to_save := JSON.stringify(serialized_data)
|
||||||
if !to_save:
|
if not to_save:
|
||||||
Global.popup_error(tr("File failed to save. Converting dictionary to JSON failed."))
|
Global.popup_error(tr("File failed to save. Converting dictionary to JSON failed."))
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
@ -450,6 +450,7 @@ func save_pxo_file(
|
||||||
Global.FileMenu.SAVE, tr("Save") + " %s" % path.get_file()
|
Global.FileMenu.SAVE, tr("Save") + " %s" % path.get_file()
|
||||||
)
|
)
|
||||||
project_saved.emit()
|
project_saved.emit()
|
||||||
|
SteamManager.set_achievement("ACH_SAVE")
|
||||||
|
|
||||||
save_project_to_recent_list(path)
|
save_project_to_recent_list(path)
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -77,3 +77,4 @@ func set_pixel(image: Image, position: Vector2i, color: Color, ignore_mirroring
|
||||||
var mirror_pos := mirrored_positions[i]
|
var mirror_pos := mirrored_positions[i]
|
||||||
if project.can_pixel_get_drawn(mirror_pos) && not Tools.check_alpha_lock(image, mirror_pos):
|
if project.can_pixel_get_drawn(mirror_pos) && not Tools.check_alpha_lock(image, mirror_pos):
|
||||||
drawers[i + 1].set_pixel(image, mirror_pos, color, color_op)
|
drawers[i + 1].set_pixel(image, mirror_pos, color, color_op)
|
||||||
|
SteamManager.set_achievement("ACH_FIRST_PIXEL")
|
||||||
|
|
45
src/Classes/SteamManager.gd
Normal file
45
src/Classes/SteamManager.gd
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
class_name SteamManager
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
## A class that manages Steam-specific functionalities. Currently only unlocks achievements.
|
||||||
|
## On non-Steam builds, this node gets automatically freed.
|
||||||
|
|
||||||
|
## The Steam app id of Pixelorama.
|
||||||
|
const APP_ID := 2779170
|
||||||
|
## We are using a variable instead of the `Steam` singleton directly,
|
||||||
|
## because it is not available in non-Steam builds.
|
||||||
|
static var steam_class
|
||||||
|
|
||||||
|
|
||||||
|
func _init() -> void:
|
||||||
|
if not ClassDB.class_exists(&"Steam"):
|
||||||
|
queue_free()
|
||||||
|
return
|
||||||
|
steam_class = ClassDB.instantiate(&"Steam")
|
||||||
|
OS.set_environment("SteamAppID", str(APP_ID))
|
||||||
|
OS.set_environment("SteamGameID", str(APP_ID))
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
if not is_instance_valid(steam_class):
|
||||||
|
return
|
||||||
|
var response: Dictionary = steam_class.steamInitEx(true, APP_ID)
|
||||||
|
print(response)
|
||||||
|
if not steam_class.isSteamRunning():
|
||||||
|
print("Steam is not running!")
|
||||||
|
return
|
||||||
|
#var id: int = steam_class.getSteamID()
|
||||||
|
#var username: String = steam_class.getFriendPersonaName(id)
|
||||||
|
|
||||||
|
|
||||||
|
## Unlocks an achievement on Steam based on its [param achievement_name].
|
||||||
|
static func set_achievement(achievement_name: String) -> void:
|
||||||
|
if not is_instance_valid(steam_class):
|
||||||
|
return
|
||||||
|
if not steam_class.isSteamRunning():
|
||||||
|
return
|
||||||
|
var status: Dictionary = steam_class.getAchievement(achievement_name)
|
||||||
|
if status["achieved"]:
|
||||||
|
return
|
||||||
|
steam_class.setAchievement(achievement_name)
|
||||||
|
steam_class.storeStats()
|
|
@ -1,4 +1,4 @@
|
||||||
[gd_scene load_steps=17 format=3 uid="uid://dbylw5k04ulp8"]
|
[gd_scene load_steps=18 format=3 uid="uid://dbylw5k04ulp8"]
|
||||||
|
|
||||||
[ext_resource type="Theme" uid="uid://bkb4syj8110el" path="res://assets/themes/dark/theme.tres" id="1"]
|
[ext_resource type="Theme" uid="uid://bkb4syj8110el" path="res://assets/themes/dark/theme.tres" id="1"]
|
||||||
[ext_resource type="Script" path="res://src/Main.gd" id="2"]
|
[ext_resource type="Script" path="res://src/Main.gd" id="2"]
|
||||||
|
@ -14,6 +14,7 @@
|
||||||
[ext_resource type="PackedScene" uid="uid://c0nuukjakmai2" path="res://src/UI/Dialogs/TileModeOffsetsDialog.tscn" id="14"]
|
[ext_resource type="PackedScene" uid="uid://c0nuukjakmai2" path="res://src/UI/Dialogs/TileModeOffsetsDialog.tscn" id="14"]
|
||||||
[ext_resource type="PackedScene" uid="uid://c6fyrnyt3663o" path="res://src/UI/Timeline/TagProperties.tscn" id="14_fw6cf"]
|
[ext_resource type="PackedScene" uid="uid://c6fyrnyt3663o" path="res://src/UI/Timeline/TagProperties.tscn" id="14_fw6cf"]
|
||||||
[ext_resource type="Script" path="res://src/HandleExtensions.gd" id="15_v0k2h"]
|
[ext_resource type="Script" path="res://src/HandleExtensions.gd" id="15_v0k2h"]
|
||||||
|
[ext_resource type="Script" path="res://src/Classes/SteamManager.gd" id="17_k1xhp"]
|
||||||
[ext_resource type="PackedScene" uid="uid://clbjfkdupw52l" path="res://src/UI/Timeline/CelProperties.tscn" id="17_ucs64"]
|
[ext_resource type="PackedScene" uid="uid://clbjfkdupw52l" path="res://src/UI/Timeline/CelProperties.tscn" id="17_ucs64"]
|
||||||
[ext_resource type="PackedScene" uid="uid://clgu8wb5o6oup" path="res://src/UI/Dialogs/ExportDialog.tscn" id="39"]
|
[ext_resource type="PackedScene" uid="uid://clgu8wb5o6oup" path="res://src/UI/Dialogs/ExportDialog.tscn" id="39"]
|
||||||
|
|
||||||
|
@ -110,11 +111,14 @@ visible = false
|
||||||
|
|
||||||
[node name="ImageRequest" type="HTTPRequest" parent="."]
|
[node name="ImageRequest" type="HTTPRequest" parent="."]
|
||||||
|
|
||||||
|
[node name="SteamManager" type="Node" parent="."]
|
||||||
|
script = ExtResource("17_k1xhp")
|
||||||
|
|
||||||
[connection signal="files_selected" from="Dialogs/OpenSprite" to="." method="_on_OpenSprite_files_selected"]
|
[connection signal="files_selected" from="Dialogs/OpenSprite" to="." method="_on_OpenSprite_files_selected"]
|
||||||
[connection signal="visibility_changed" from="Dialogs/OpenSprite" to="." method="_on_open_sprite_visibility_changed"]
|
[connection signal="visibility_changed" from="Dialogs/OpenSprite" to="." method="_on_open_sprite_visibility_changed"]
|
||||||
[connection signal="file_selected" from="Dialogs/SaveSprite" to="." method="_on_SaveSprite_file_selected"]
|
[connection signal="file_selected" from="Dialogs/SaveSprite" to="." method="_on_SaveSprite_file_selected"]
|
||||||
[connection signal="visibility_changed" from="Dialogs/SaveSprite" to="." method="_on_save_sprite_visibility_changed"]
|
|
||||||
[connection signal="visibility_changed" from="Dialogs/SaveSprite" to="." method="_can_draw_true"]
|
[connection signal="visibility_changed" from="Dialogs/SaveSprite" to="." method="_can_draw_true"]
|
||||||
|
[connection signal="visibility_changed" from="Dialogs/SaveSprite" to="." method="_on_save_sprite_visibility_changed"]
|
||||||
[connection signal="confirmed" from="Dialogs/SaveSpriteHTML5" to="." method="save_project" binds= [""]]
|
[connection signal="confirmed" from="Dialogs/SaveSpriteHTML5" to="." method="save_project" binds= [""]]
|
||||||
[connection signal="visibility_changed" from="Dialogs/SaveSpriteHTML5" to="." method="_can_draw_true"]
|
[connection signal="visibility_changed" from="Dialogs/SaveSpriteHTML5" to="." method="_can_draw_true"]
|
||||||
[connection signal="visibility_changed" from="Dialogs/ExportDialog" to="." method="_can_draw_true"]
|
[connection signal="visibility_changed" from="Dialogs/ExportDialog" to="." method="_can_draw_true"]
|
||||||
|
|
|
@ -328,6 +328,7 @@ func _ready() -> void:
|
||||||
if typeof(value) == TYPE_VECTOR2 or typeof(value) == TYPE_COLOR:
|
if typeof(value) == TYPE_VECTOR2 or typeof(value) == TYPE_COLOR:
|
||||||
is_default = value.is_equal_approx(pref.default_value)
|
is_default = value.is_equal_approx(pref.default_value)
|
||||||
disable_restore_default_button(restore_default_button, is_default)
|
disable_restore_default_button(restore_default_button, is_default)
|
||||||
|
SteamManager.set_achievement("ACH_PREFERENCES")
|
||||||
|
|
||||||
|
|
||||||
func _on_Preference_value_changed(value, pref: Preference, button: RestoreDefaultButton) -> void:
|
func _on_Preference_value_changed(value, pref: Preference, button: RestoreDefaultButton) -> void:
|
||||||
|
|
|
@ -106,6 +106,7 @@ func draw_end(pos: Vector2i) -> void:
|
||||||
_draw_line = false
|
_draw_line = false
|
||||||
|
|
||||||
commit_undo()
|
commit_undo()
|
||||||
|
SteamManager.set_achievement("ACH_ERASE_PIXEL")
|
||||||
cursor_text = ""
|
cursor_text = ""
|
||||||
update_random_image()
|
update_random_image()
|
||||||
|
|
||||||
|
|
|
@ -834,6 +834,7 @@ func help_menu_id_pressed(id: int) -> void:
|
||||||
_popup_dialog(Global.control.splash_dialog)
|
_popup_dialog(Global.control.splash_dialog)
|
||||||
Global.HelpMenu.ONLINE_DOCS:
|
Global.HelpMenu.ONLINE_DOCS:
|
||||||
OS.shell_open(DOCS_URL)
|
OS.shell_open(DOCS_URL)
|
||||||
|
SteamManager.set_achievement("ACH_ONLINE_DOCS")
|
||||||
Global.HelpMenu.ISSUE_TRACKER:
|
Global.HelpMenu.ISSUE_TRACKER:
|
||||||
OS.shell_open(ISSUES_URL)
|
OS.shell_open(ISSUES_URL)
|
||||||
Global.HelpMenu.OPEN_EDITOR_DATA_FOLDER:
|
Global.HelpMenu.OPEN_EDITOR_DATA_FOLDER:
|
||||||
|
@ -844,5 +845,6 @@ func help_menu_id_pressed(id: int) -> void:
|
||||||
about_dialog.popup()
|
about_dialog.popup()
|
||||||
Global.HelpMenu.SUPPORT_PIXELORAMA:
|
Global.HelpMenu.SUPPORT_PIXELORAMA:
|
||||||
OS.shell_open(SUPPORT_URL)
|
OS.shell_open(SUPPORT_URL)
|
||||||
|
SteamManager.set_achievement("ACH_SUPPORT_DEVELOPMENT")
|
||||||
_:
|
_:
|
||||||
_handle_metadata(id, help_menu)
|
_handle_metadata(id, help_menu)
|
||||||
|
|
Loading…
Reference in a new issue