remove addons & multiplayer calls

This commit is contained in:
Harmony Honey Monroe 2025-01-16 13:39:08 -05:00
parent a627dd11f1
commit 15af541390
79 changed files with 14 additions and 7033 deletions

View file

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2020 Hector Margittay
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,187 +0,0 @@
tool
extends Node
class_name AsepriteImportData
enum Error{
OK = 0,
# Error codes start from 49 to not conflict with GlobalScope's error constants
ERR_JSON_PARSE_ERROR = 49,
ERR_INVALID_JSON_DATA,
ERR_MISSING_FRAME_TAGS,
ERR_EMPTY_FRAME_TAGS
}
const FRAME_TEMPLATE = {
frame = {
x = TYPE_INT,
y = TYPE_INT,
w = TYPE_INT,
h = TYPE_INT,
},
spriteSourceSize = {
x = TYPE_INT,
y = TYPE_INT,
w = TYPE_INT,
h = TYPE_INT,
},
sourceSize = {
w = TYPE_INT,
h = TYPE_INT,
},
duration = TYPE_INT,
}
const META_TEMPLATE = {
frameTags = [
{
name = TYPE_STRING,
from = TYPE_INT,
to = TYPE_INT,
direction = TYPE_STRING
},
],
size = {
w = TYPE_INT,
h = TYPE_INT,
},
}
var json_filepath : String
var json_data : Dictionary
func load(filepath : String) -> int:
var file := File.new()
var error := file.open(filepath, File.READ)
if error != OK:
return error
var file_text = file.get_as_text()
file.close()
var json := JSON.parse(file_text)
if json.error != OK:
return Error.ERR_JSON_PARSE_ERROR
error = _validate_json(json)
if error != OK:
return error
json_filepath = filepath
json_data = json.result
return OK
func get_frame_array() -> Array:
if not json_data:
return []
var frame_data = json_data.frames
if frame_data is Dictionary:
return frame_data.values()
return frame_data
func get_image_filename() -> String:
if not (json_data and json_data.meta.has("image")):
return ""
return json_data.meta.image
func get_image_size() -> Vector2:
if not json_data:
return Vector2.ZERO
var image_size : Dictionary = json_data.meta.size
return Vector2(
image_size.w,
image_size.h
)
func get_tag(tag_idx : int) -> Dictionary:
var tags := get_tags()
if tag_idx >= 0 and tag_idx < tags.size():
return tags[tag_idx]
return {}
func get_tags() -> Array:
if not json_data:
return []
return json_data.meta.frameTags
static func _validate_json(json : JSONParseResult) -> int:
var data : Dictionary = json.result
if not (data is Dictionary and data.has_all(["frames", "meta"])):
return Error.ERR_INVALID_JSON_DATA
# "frames" validation
var frames = data.frames
var is_hash := frames is Dictionary
for frame in frames:
if is_hash:
frame = frames[frame]
if not _match_template(frame, FRAME_TEMPLATE):
return Error.ERR_INVALID_JSON_DATA
# "meta" validation
if not _match_template(data.meta, META_TEMPLATE):
var meta := data.meta as Dictionary
if not meta.has("frameTags"):
return Error.ERR_MISSING_FRAME_TAGS
elif meta.frameTags == []:
return Error.ERR_EMPTY_FRAME_TAGS
return Error.ERR_INVALID_JSON_DATA
return OK
"""
This helper function recursively walks an Array or a Dictionary checking if each
children's type matches the template
"""
static func _match_template(data, template) -> bool:
match typeof(template):
TYPE_INT:
# When parsed, the JSON interprets integer values as floats
if template == TYPE_INT and typeof(data) == TYPE_REAL:
return true
return typeof(data) == template
TYPE_DICTIONARY:
if typeof(data) != TYPE_DICTIONARY:
return false
if not data.has_all(template.keys()):
return false
for key in template:
if not _match_template(data[key], template[key]):
return false
TYPE_ARRAY:
if typeof(data) != TYPE_ARRAY:
return false
if data.empty():
return false
for element in data:
if not _match_template(element, template[0]):
return false
return true

View file

@ -1,153 +0,0 @@
tool
extends Node
class_name AsepriteImporter
enum Error{
OK,
INVALID_JSON_DATA,
MISSING_JSON_DATA,
MISSING_ANIMATION_PLAYER,
MISSING_SPRITE,
NO_TAGS_SELECTED,
DUPLICATE_TAG_NAME,
MISSING_TEXTURE,
}
static func generate_animations(import_data : AsepriteImportData, selected_tags : Array,
animation_player : AnimationPlayer, sprite : Node, texture : Texture) -> int:
if not(import_data and import_data.json_data):
return Error.MISSING_JSON_DATA
var frame_tags : Array = import_data.get_tags()
if not selected_tags:
return Error.NO_TAGS_SELECTED
else:
var tag_names := []
for tag_idx in selected_tags:
var tag_name : String = frame_tags[tag_idx].name
if tag_names.has(tag_name):
return Error.DUPLICATE_TAG_NAME
else:
tag_names.append(tag_name)
if not animation_player:
return Error.MISSING_ANIMATION_PLAYER
if not(sprite is Sprite or sprite is Sprite3D):
return Error.MISSING_SPRITE
if texture == null:
return Error.MISSING_TEXTURE
var animation_root_path := animation_player.root_node
var animation_root_node := animation_player.get_node(animation_root_path)
var sprite_relative_path := str(animation_root_node.get_path_to(sprite))
# These are tracks that will be used
var tracks := {
"region" : {
path = (sprite_relative_path + ":region_rect"),
},
"offset" : {
path = (sprite_relative_path + ":offset")
}
}
var frames := import_data.get_frame_array()
var is_sprite3d := sprite is Sprite3D
# Iterate over each tag (animation)
for tag_idx in selected_tags:
var tag : Dictionary = frame_tags[tag_idx]
var animation : Animation
# Check if the animation already exists
if animation_player.has_animation(tag.name):
animation = animation_player.get_animation(tag.name)
else:
# If it doesn't, adds a new one
animation = Animation.new()
# warning-ignore:return_value_discarded
animation_player.add_animation(tag.name, animation)
# Setup the animation tracks
for track_name in tracks:
var track : Dictionary = tracks[track_name]
track.idx = animation.find_track(track.path)
# Checks if the track doesn't exist
if track.idx == -1:
# Create a new_track
track.idx = animation.add_track(Animation.TYPE_VALUE)
animation.track_set_path(track.idx, track.path)
else:
# Remove all existing keys from the track
for key_idx in range(animation.track_get_key_count(track.idx)):
animation.track_remove_key(track.idx, 0)
# Set the track Interpolation Mode to Nearest
animation.track_set_interpolation_type(track.idx, Animation.INTERPOLATION_NEAREST)
#Enable the track
animation.track_set_enabled(track.idx, true)
var time := 0.0
var frame_idxs := range(tag.from, tag.to + 1)
# Modify the frame order based on the tag's direction
match tag.direction:
"reverse":
frame_idxs.invert()
"pingpong":
var pong_frame_idxs := range(tag.from + 1, tag.to)
pong_frame_idxs.invert()
frame_idxs += pong_frame_idxs
# Insert the new keys
for i in frame_idxs:
var frame : Dictionary = frames[i]
# Get the region of the spritesheet that has the frame
var rect = frame.frame
var region = Rect2(rect.x, rect.y, rect.w, rect.h)
# Insert the new key for the region track
animation.track_insert_key(tracks.region.idx, time, region)
# Get the center of the frame in the original size
var source_size : Dictionary = frame.sourceSize
var source_center_x : float = source_size.w / 2
var source_center_y : float = source_size.h / 2
# Get the center of the trimmed frame in the spritesheet
var trim_rect : Dictionary = frame.spriteSourceSize
var trim_rect_center_x : float = trim_rect.x + (trim_rect.w / 2)
var trim_rect_center_y : float = trim_rect.y + (trim_rect.h / 2)
# Calculate the offset between the trimmed frame center and original frame center
var offset_x := trim_rect_center_x - source_center_x
var offset_y := trim_rect_center_y - source_center_y
# Invert the vertical offset when the selected sprite is a Sprite3D
if is_sprite3d:
offset_y *= -1
# Insert the new key for the offset track
animation.track_insert_key(tracks.offset.idx, time, Vector2(offset_x, offset_y))
# Add up the current frame's duration for the next key position
time += frame.duration / 1000
# Set the animation length equal to the sum of all frame's durations
animation.length = time
sprite.texture = texture
sprite.region_enabled = true
sprite.centered = true
return OK

View file

@ -1,26 +0,0 @@
tool
extends Node
class_name EditorTheme
var _theme : Theme
func _init(theme : Theme) -> void:
_theme = theme
func get_color(color_name : String, color_list := "Editor") -> Color:
return _theme.get_color(color_name, color_list)
func get_font(font_name : String, font_list := "EditorFonts") -> Font:
return _theme.get_font(font_name, font_list)
func get_icon(icon_name : String, icon_list := "EditorIcons") -> Texture:
return _theme.get_icon(icon_name, icon_list)
func get_stylebox(stylebox_name : String, stylebox_list := "EditorStyles") -> StyleBox:
return _theme.get_stylebox(stylebox_name, stylebox_list)

View file

@ -1,156 +0,0 @@
tool
extends PanelContainer
onready var import_menu : Container = $Body/ImportMenu
onready var steps : Container = import_menu.get_node("Steps")
onready var json_import_menu : Container = steps.get_node("JSONImportMenu")
onready var tags_menu : Container = steps.get_node("TagsMenu")
onready var select_animation_player_menu = steps.get_node("SelectAnimationPlayerMenu")
onready var select_sprite_menu = steps.get_node("SelectSpriteMenu")
onready var generate_button : Button = steps.get_node("GenerateButton")
onready var spritesheet_inspector : Container = $Body/SpritesheetInspector
onready var alert_dialog : AcceptDialog = $AlertDialog
const ERROR_MSG := {
AsepriteImporter.Error.MISSING_JSON_DATA : "Missing JSON Data!",
AsepriteImporter.Error.MISSING_ANIMATION_PLAYER : "Select an AnimationPlayer node!",
AsepriteImporter.Error.MISSING_SPRITE : "Select a Sprite node!",
AsepriteImporter.Error.NO_TAGS_SELECTED : "No tags selected to import!",
AsepriteImporter.Error.DUPLICATE_TAG_NAME : "Two or more of the selected tags share the same name\nSelect only tags with distinct names",
AsepriteImporter.Error.MISSING_TEXTURE: "No texture selected!",
}
const IMPORT_MENU_INITIAL_WIDTH := 300
var import_data : AsepriteImportData
var _is_ready := false
signal animations_generated(animation_player)
func _ready() -> void:
import_menu.rect_size.x = IMPORT_MENU_INITIAL_WIDTH
alert_dialog.set_as_toplevel(true)
json_import_menu.connect("data_imported", self, "_on_JSONImportMenu_data_imported")
json_import_menu.connect("data_cleared", self, "_on_JSONImportMenu_data_cleared")
tags_menu.connect("frame_selected", self, "_on_TagSelectMenu_frame_selected")
tags_menu.connect("tag_selected", self, "_on_TagSelectMenu_tag_selected")
generate_button.connect("pressed", self, "_on_GenerateButton_pressed")
func get_state() -> Dictionary:
var state := {
"import_data" : import_data,
"tags_menu" : tags_menu.get_state(),
"select_sprite_menu" : select_sprite_menu.get_state(),
"select_animation_player_menu" : select_animation_player_menu.get_state(),
"spritesheet_inspector" : spritesheet_inspector.get_state(),
}
return state
func set_state(new_state : Dictionary) -> void:
var json_filepath := ""
var tags := []
var selected_tags := []
if new_state.get("import_data", false):
import_data = new_state.import_data
json_filepath = import_data.json_filepath
tags = import_data.get_tags()
spritesheet_inspector.frames = import_data.get_frame_array()
# var selected_tag := import_data.get_tag(tag_name)
# if selected_tag:
# spritesheet_inspector.select_frames(range(selected_tag.from, selected_tag.to + 1))
else:
import_data = null
new_state.erase("tags_menu")
# new_state.erase("spritesheet_inspector")
json_import_menu.set_json_filepath(json_filepath)
select_sprite_menu.set_state(new_state.get("select_sprite_menu", {}))
select_animation_player_menu.set_state(new_state.get("select_animation_player_menu", {}))
spritesheet_inspector.set_state(new_state.get("spritesheet_inspector", {}))
tags_menu.load_tags(tags)
tags_menu.set_state(new_state.get("tags_menu", {}))
func _show_alert(message : String) -> void:
alert_dialog.dialog_text = message
alert_dialog.popup_centered()
func _update_theme(editor_theme : EditorTheme) -> void:
generate_button.icon = editor_theme.get_icon("ImportCheck")
# Signal Callbacks
func _on_GenerateButton_pressed() -> void:
var selected_tags : Array = tags_menu.get_selected_tags()
var animation_player : AnimationPlayer = select_animation_player_menu.animation_player
var sprite : Node = select_sprite_menu.sprite
var texture : Texture = spritesheet_inspector.get_texture()
var error := AsepriteImporter.generate_animations(import_data, selected_tags, animation_player, sprite, texture)
if error != OK:
var error_msg : String
if ERROR_MSG.has(error):
error_msg = ERROR_MSG[error]
else:
error_msg = "An error ocurred!"
_show_alert(error_msg)
else:
emit_signal("animations_generated", animation_player)
func _on_JSONImportMenu_data_imported(new_import_data : AsepriteImportData) -> void:
import_data = new_import_data
var tags : Array = import_data.get_tags()
tags_menu.load_tags(tags)
var json_filepath := import_data.json_filepath
var json_dir_path := json_filepath.rsplit("/", true, 1)[0]
var image_filepath := ""
var image_filename := import_data.get_image_filename()
image_filepath = str(json_dir_path, "/", image_filename)
spritesheet_inspector.texture_size = import_data.get_image_size()
spritesheet_inspector.frames = import_data.get_frame_array()
spritesheet_inspector.load_texture(image_filepath)
func _on_JSONImportMenu_data_cleared() -> void:
import_data = null
spritesheet_inspector.clear_texture()
tags_menu.clear_options()
func _on_TagSelectMenu_frame_selected(idx : int) -> void:
spritesheet_inspector.select_frames([idx])
func _on_TagSelectMenu_tag_selected(tag_idx : int) -> void:
var selected_tag := import_data.get_tag(tag_idx)
spritesheet_inspector.select_frames(range(selected_tag.from, selected_tag.to + 1))

View file

@ -1,100 +0,0 @@
[gd_scene load_steps=9 format=2]
[ext_resource path="res://addons/aseprite_importer/interface/Main.gd" type="Script" id=1]
[ext_resource path="res://addons/aseprite_importer/interface/import_menu/SelectAnimationPlayerMenu.tscn" type="PackedScene" id=2]
[ext_resource path="res://addons/aseprite_importer/interface/import_menu/JSONImportMenu.tscn" type="PackedScene" id=3]
[ext_resource path="res://addons/aseprite_importer/interface/import_menu/TagsMenu.tscn" type="PackedScene" id=4]
[ext_resource path="res://addons/aseprite_importer/interface/import_menu/SelectSpriteMenu.tscn" type="PackedScene" id=5]
[ext_resource path="res://addons/aseprite_importer/interface/spritesheet_inspector/SpritesheetInspector.tscn" type="PackedScene" id=6]
[sub_resource type="Image" id=3]
data = {
"data": PoolByteArray( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 229, 127, 0, 113, 241, 127, 0, 113, 240, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 229, 127, 0, 114, 229, 127, 20, 113, 241, 127, 184, 113, 240, 127, 144, 113, 240, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 229, 127, 0, 114, 229, 127, 20, 114, 241, 127, 210, 115, 242, 128, 255, 114, 241, 127, 170, 114, 241, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 229, 127, 0, 114, 229, 127, 20, 114, 241, 126, 209, 115, 242, 128, 255, 114, 241, 127, 210, 109, 230, 121, 21, 109, 230, 121, 0, 0, 0, 0, 0, 113, 240, 127, 0, 113, 241, 127, 0, 114, 229, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 235, 123, 0, 114, 229, 127, 20, 114, 241, 127, 208, 115, 242, 128, 255, 114, 241, 127, 210, 104, 231, 127, 22, 106, 230, 124, 0, 0, 0, 0, 0, 113, 240, 127, 0, 113, 240, 127, 144, 113, 241, 127, 184, 114, 229, 127, 20, 114, 229, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 240, 123, 0, 107, 241, 120, 19, 114, 241, 126, 207, 115, 242, 128, 255, 114, 241, 126, 211, 104, 231, 127, 22, 104, 231, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 241, 127, 0, 114, 241, 127, 170, 115, 242, 128, 255, 114, 241, 127, 210, 114, 229, 127, 20, 114, 229, 127, 0, 113, 240, 127, 0, 113, 240, 127, 18, 114, 241, 126, 207, 115, 242, 128, 255, 114, 241, 127, 212, 104, 231, 127, 22, 104, 231, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 230, 121, 0, 109, 230, 121, 21, 114, 241, 127, 210, 115, 242, 128, 255, 114, 241, 126, 209, 114, 229, 127, 20, 113, 240, 127, 18, 114, 241, 126, 207, 115, 242, 128, 255, 114, 241, 126, 213, 104, 231, 127, 22, 104, 231, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 230, 124, 0, 104, 231, 127, 22, 114, 241, 127, 210, 115, 242, 128, 255, 114, 241, 126, 207, 113, 241, 127, 206, 115, 242, 128, 255, 114, 241, 126, 213, 110, 232, 121, 23, 107, 231, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 231, 127, 0, 104, 231, 127, 22, 114, 241, 127, 212, 115, 242, 128, 255, 115, 242, 128, 255, 114, 241, 126, 213, 106, 233, 127, 24, 108, 232, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 231, 127, 0, 104, 231, 127, 22, 113, 241, 127, 186, 114, 241, 126, 187, 106, 233, 127, 24, 106, 233, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 231, 127, 0, 113, 241, 127, 0, 114, 241, 126, 0, 106, 233, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ),
"format": "RGBA8",
"height": 16,
"mipmaps": false,
"width": 16
}
[sub_resource type="ImageTexture" id=2]
flags = 0
flags = 0
image = SubResource( 3 )
size = Vector2( 16, 16 )
[node name="Main" type="PanelContainer"]
anchor_right = 1.0
anchor_bottom = 1.0
size_flags_horizontal = 3
size_flags_vertical = 3
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Body" type="HSplitContainer" parent="."]
margin_left = 7.0
margin_top = 7.0
margin_right = 1017.0
margin_bottom = 593.0
size_flags_vertical = 3
[node name="ImportMenu" type="ScrollContainer" parent="Body"]
margin_right = 300.0
margin_bottom = 586.0
rect_min_size = Vector2( 300, 0 )
size_flags_vertical = 3
follow_focus = true
scroll_horizontal_enabled = false
scroll_horizontal = 100
[node name="Steps" type="VBoxContainer" parent="Body/ImportMenu"]
margin_right = 300.0
margin_bottom = 586.0
size_flags_horizontal = 3
size_flags_vertical = 3
custom_constants/separation = 12
[node name="JSONImportMenu" parent="Body/ImportMenu/Steps" instance=ExtResource( 3 )]
margin_right = 300.0
[node name="TagsMenu" parent="Body/ImportMenu/Steps" instance=ExtResource( 4 )]
margin_top = 50.0
margin_right = 300.0
margin_bottom = 432.0
[node name="SelectAnimationPlayerMenu" parent="Body/ImportMenu/Steps" instance=ExtResource( 2 )]
margin_top = 444.0
margin_right = 300.0
margin_bottom = 484.0
[node name="SelectSpriteMenu" parent="Body/ImportMenu/Steps" instance=ExtResource( 5 )]
margin_top = 496.0
margin_right = 300.0
margin_bottom = 536.0
[node name="HSeparator" type="HSeparator" parent="Body/ImportMenu/Steps"]
margin_top = 548.0
margin_right = 300.0
margin_bottom = 552.0
[node name="GenerateButton" type="Button" parent="Body/ImportMenu/Steps"]
margin_top = 564.0
margin_right = 300.0
margin_bottom = 586.0
hint_tooltip = "Generate the animations in the selected AnimationPlayer node"
size_flags_horizontal = 3
text = "Generate Animations"
icon = SubResource( 2 )
[node name="SpritesheetInspector" parent="Body" instance=ExtResource( 6 )]
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 312.0
margin_right = 1010.0
margin_bottom = 586.0
[node name="AlertDialog" type="AcceptDialog" parent="."]
margin_right = 83.0
margin_bottom = 58.0
popup_exclusive = true

Binary file not shown.

Before

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 225 B

View file

@ -1,92 +0,0 @@
tool
extends Container
onready var import_button : Button = $InputContainer/ImportButton
onready var clear_button : Button = $InputContainer/ClearButton
onready var file_dialog : FileDialog = $FileDialog
onready var alert_dialog : AcceptDialog = $AlertDialog
const IMPORT_BUTTON_DEFAULT_TEXT = "Import JSON"
const MSG_JSON_OPEN_FILE_ERROR = \
"An error occurred while opening the file \"%s\"\n\n" + \
"(error code: %d)"
const MSG_JSON_PARSE_ERROR = "Error parsing the file"
const MSG_INVALID_JSON_DATA = "Invalid Aseprite JSON file"
const MSG_MISSING_FRAME_TAGS = \
"Missing animation tags data from the JSON file\n\n" + \
"Make sure to enable the option Output->Meta->Tags when exporting the spritesheet from Aseprite"
const MSG_EMPTY_FRAME_TAGS = \
"Animation tags not defined in the JSON file\n\n" + \
"Add tags in the Aseprite timeline to define the frames inside each animation"
signal data_imported(import_data)
signal data_cleared
func _ready():
clear_button.hide()
alert_dialog.set_as_toplevel(true)
import_button.connect("pressed", self, "_on_ImportButton_pressed")
clear_button.connect("pressed", self, "_on_ClearButton_pressed")
file_dialog.connect("file_selected", self, "_on_FileDialog_file_selected")
func set_json_filepath(new_filepath : String) -> void:
if new_filepath:
import_button.text = new_filepath
clear_button.show()
else:
import_button.text = IMPORT_BUTTON_DEFAULT_TEXT
clear_button.hide()
func _update_theme(editor_theme : EditorTheme) -> void:
import_button.icon = editor_theme.get_icon("Load")
clear_button.icon = editor_theme.get_icon("Clear")
#Signal Callbacks
func _on_ImportButton_pressed() -> void:
file_dialog.invalidate()
file_dialog.popup_centered_ratio(0.5)
func _on_ClearButton_pressed() -> void:
set_json_filepath("")
emit_signal("data_cleared")
func _on_FileDialog_file_selected(path : String) -> void:
var import_data := AsepriteImportData.new()
var error := import_data.load(path)
if error != OK:
var error_msg : String
match error:
AsepriteImportData.Error.ERR_JSON_PARSE_ERROR:
error_msg = MSG_JSON_PARSE_ERROR
AsepriteImportData.Error.ERR_INVALID_JSON_DATA:
error_msg = MSG_INVALID_JSON_DATA
AsepriteImportData.Error.ERR_MISSING_FRAME_TAGS:
error_msg = MSG_MISSING_FRAME_TAGS
AsepriteImportData.Error.ERR_EMPTY_FRAME_TAGS:
error_msg = MSG_EMPTY_FRAME_TAGS
_:
error_msg = MSG_JSON_OPEN_FILE_ERROR % [path, error]
set_json_filepath("")
yield(get_tree(), "idle_frame")
alert_dialog.dialog_text = error_msg
alert_dialog.popup_centered()
else:
set_json_filepath(path)
emit_signal("data_imported", import_data)

View file

@ -1,78 +0,0 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://addons/aseprite_importer/interface/import_menu/JSONImportMenu.gd" type="Script" id=1]
[sub_resource type="Image" id=3]
data = {
"data": PoolByteArray( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 179, 223, 223, 223, 179, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220, 0, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 0, 220, 220, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220, 0, 220, 220, 220, 59, 223, 223, 223, 201, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 200, 220, 220, 220, 59, 220, 220, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 222, 222, 0, 222, 222, 222, 199, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 222, 222, 222, 198, 222, 222, 222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 254, 223, 223, 223, 203, 223, 223, 223, 203, 223, 223, 223, 152, 223, 223, 223, 152, 222, 222, 222, 101, 222, 222, 222, 101, 219, 219, 219, 50, 219, 219, 219, 50, 221, 221, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 0, 222, 222, 222, 0, 222, 222, 222, 0, 219, 219, 219, 0, 219, 219, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ),
"format": "RGBA8",
"height": 16,
"mipmaps": false,
"width": 16
}
[sub_resource type="ImageTexture" id=2]
flags = 0
flags = 0
image = SubResource( 3 )
size = Vector2( 16, 16 )
[node name="JSONImport" type="VBoxContainer"]
margin_right = 91.0
margin_bottom = 38.0
size_flags_horizontal = 3
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label" type="Label" parent="."]
margin_right = 91.0
margin_bottom = 14.0
text = "JSON Data"
valign = 1
[node name="InputContainer" type="HBoxContainer" parent="."]
margin_top = 18.0
margin_right = 91.0
margin_bottom = 38.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="ImportButton" type="Button" parent="InputContainer"]
margin_right = 91.0
margin_bottom = 20.0
hint_tooltip = "Import a Aseprite JSON file"
size_flags_horizontal = 3
text = "Import JSON"
[node name="ClearButton" type="Button" parent="InputContainer"]
visible = false
margin_left = 143.0
margin_top = -18.0
margin_right = 187.0
margin_bottom = 2.0
text = "Clear"
icon = SubResource( 2 )
[node name="FileDialog" type="FileDialog" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
margin_bottom = 110.0
window_title = "Select the JSON file"
resizable = true
mode_overrides_title = false
mode = 0
filters = PoolStringArray( "*.json ; JSON Files" )
show_hidden_files = true
[node name="AlertDialog" type="AcceptDialog" parent="."]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_top = 42.0
margin_right = 400.0
margin_bottom = 100.0
popup_exclusive = true

View file

@ -1,64 +0,0 @@
tool
extends Container
onready var select_button : Button = $Button
onready var select_node_dialog : WindowDialog = $SelectNodeDialog
const SELECT_BUTTON_DEFAULT_TEXT := "Select a Node"
var animation_player : AnimationPlayer setget set_animation_player
signal node_selected(animation_player)
func _ready():
select_node_dialog.class_filters = ["AnimationPlayer"]
select_button.connect("pressed", self, "_on_SelectButton_pressed")
select_node_dialog.connect("node_selected", self, "_on_SelectNodeDialog_node_selected")
func get_state() -> Dictionary:
var state := {}
if animation_player:
state.animation_player = animation_player
return state
func set_state(new_state : Dictionary) -> void:
var new_animation_player : Node = new_state.get("animation_player")
if new_animation_player != null :
self.animation_player = new_animation_player
else:
animation_player = null
select_button.text = SELECT_BUTTON_DEFAULT_TEXT
func _update_theme(editor_theme : EditorTheme) -> void:
select_button.icon = editor_theme.get_icon("AnimationPlayer")
# Setters and Getters
func set_animation_player(node : AnimationPlayer) -> void:
animation_player = node
var node_path := node.owner.get_parent().get_path_to(node)
select_button.text = node_path
# Signal Callbacks
func _on_SelectButton_pressed() -> void:
if select_node_dialog.initialize():
select_node_dialog.popup_centered_ratio(.5)
func _on_SelectNodeDialog_node_selected(selected_node : Node) -> void:
self.animation_player = selected_node
emit_signal("node_selected", selected_node)

View file

@ -1,53 +0,0 @@
[gd_scene load_steps=5 format=2]
[ext_resource path="res://addons/aseprite_importer/interface/import_menu/SelectNodeDialog.tscn" type="PackedScene" id=1]
[ext_resource path="res://addons/aseprite_importer/interface/import_menu/SelectAnimationPlayerMenu.gd" type="Script" id=2]
[sub_resource type="Image" id=1]
data = {
"data": PoolByteArray( 0, 0, 0, 0, 206, 164, 241, 0, 204, 159, 235, 0, 0, 0, 0, 0, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 164, 241, 0, 0, 0, 0, 0, 206, 164, 241, 0, 206, 164, 241, 255, 204, 159, 235, 40, 205, 161, 238, 0, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 255, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 255, 204, 159, 235, 40, 205, 162, 239, 0, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 255, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 255, 204, 159, 235, 40, 205, 162, 239, 0, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 255, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 255, 204, 159, 235, 40, 205, 162, 239, 0, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 255, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 255, 204, 159, 235, 40, 205, 162, 239, 0, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 255, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 255, 204, 159, 235, 40, 205, 162, 239, 0, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 255, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 255, 204, 159, 235, 40, 205, 162, 239, 0, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 255, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 255, 204, 159, 235, 40, 205, 161, 238, 0, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 255, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 255, 206, 164, 241, 0, 0, 0, 0, 0, 206, 164, 241, 0, 204, 159, 235, 0, 0, 0, 0, 0, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 0, 206, 164, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 164, 241, 0, 0, 0, 0, 0 ),
"format": "RGBA8",
"height": 16,
"mipmaps": false,
"width": 16
}
[sub_resource type="ImageTexture" id=2]
flags = 0
flags = 0
image = SubResource( 1 )
size = Vector2( 16, 16 )
[node name="SelectAnimationPlayer" type="VBoxContainer"]
margin_right = 148.0
margin_bottom = 38.0
script = ExtResource( 2 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label" type="Label" parent="."]
margin_right = 148.0
margin_bottom = 14.0
text = "Select AnimationPlayer"
[node name="Button" type="Button" parent="."]
margin_top = 18.0
margin_right = 148.0
margin_bottom = 40.0
hint_tooltip = "Select a AnimationPlayer node from the current scene"
text = "Select Node"
icon = SubResource( 2 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="SelectNodeDialog" parent="." instance=ExtResource( 1 )]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_top = 42.0
margin_right = 245.0
margin_bottom = 43.0
window_title = "Select the AnimationPlayer Node"

View file

@ -1,144 +0,0 @@
tool
extends WindowDialog
onready var body : VBoxContainer = $MarginContainer/Body
onready var edited_scene_view : Container = body.get_node('EditedSceneView')
onready var scene_tree : Tree = edited_scene_view.get_node('SceneTree')
onready var footer : HBoxContainer = body.get_node('Footer')
onready var confirm_button : Button = footer.get_node('ConfirmButton')
onready var cancel_button : Button = footer.get_node('CancelButton')
onready var alert_dialog : AcceptDialog = $AlertDialog
enum Columns {
NAME,
PATH,
}
const MSG_EMPTY_SCENE = 'The current scene is empty!'
const MSG_UNSAVED_SCENE = 'The current scene is still not saved!'
const MSG_NO_FILTERED_NODES_IN_SCENE = "There aren't any %s nodes in the current scene"
const WINDOW_TITLE_DEFAULT = 'Select a Node'
const WINDOW_TITLE_WITH_FILTER = "Select the %s Node"
const DISABLED_ICON_MODULATE := Color(1, 1, 1, .5)
var class_filters : Array setget set_class_filters
var edited_scene_root : Node
var _editor_theme : EditorTheme
signal node_selected(selected_node)
func _ready():
self.class_filters = class_filters
scene_tree.columns = Columns.size()
scene_tree.set_column_expand(Columns.PATH, false)
alert_dialog.set_as_toplevel(true)
scene_tree.connect('item_activated', self, '_on_node_selected')
confirm_button.connect('pressed', self, '_on_node_selected')
cancel_button.connect('pressed', self, 'hide')
func initialize() -> bool:
edited_scene_root = get_tree().get_edited_scene_root()
if edited_scene_root == null:
_show_alert(MSG_EMPTY_SCENE)
return false
var scene_filename := edited_scene_root.filename
if not scene_filename:
_show_alert(MSG_UNSAVED_SCENE)
return false
scene_tree.clear()
var filtered_node_count := _add_node_to_scene_tree(edited_scene_root)
if class_filters and filtered_node_count == 0:
var filters_str := PoolStringArray(class_filters).join(" / ")
_show_alert(MSG_NO_FILTERED_NODES_IN_SCENE % filters_str)
return false
return true
func _add_node_to_scene_tree(node : Node, parent : TreeItem = null) -> int:
var tree_item := scene_tree.create_item(parent)
var node_class := node.get_class()
tree_item.set_icon(Columns.NAME, _editor_theme.get_icon(node_class))
tree_item.set_text(Columns.NAME, node.name)
tree_item.set_text(Columns.PATH, edited_scene_root.get_path_to(node))
var disabled_font_color := _editor_theme.get_color("disabled_font_color")
var filtered_node_count := 0
if class_filters:
var is_valid := false
for filter in class_filters:
if node.is_class(filter):
is_valid = true
filtered_node_count += 1
break
if not is_valid:
tree_item.set_selectable(Columns.NAME, false)
tree_item.set_icon_modulate(Columns.NAME, DISABLED_ICON_MODULATE)
tree_item.set_custom_color(Columns.NAME, disabled_font_color)
for child in node.get_children():
if child.owner == edited_scene_root:
filtered_node_count += _add_node_to_scene_tree(child, tree_item)
return filtered_node_count
func _show_alert(message : String) -> void:
alert_dialog.dialog_text = message
alert_dialog.popup_centered()
func _update_theme(editor_theme : EditorTheme) -> void:
_editor_theme = editor_theme
# Setters and Getters
func set_class_filters(filters : Array) -> void:
class_filters = filters
if class_filters != []:
var filters_str := PoolStringArray(class_filters).join(" / ")
window_title = WINDOW_TITLE_WITH_FILTER % filters_str
else:
window_title = WINDOW_TITLE_DEFAULT
# Signal Callbacks
func _on_node_selected() -> void:
var selected_item := scene_tree.get_selected()
if selected_item:
var node_path := selected_item.get_text(Columns.PATH)
var selected_node := edited_scene_root.get_node(node_path)
emit_signal('node_selected', selected_node)
hide()

View file

@ -1,98 +0,0 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/aseprite_importer/interface/import_menu/SelectNodeDialog.gd" type="Script" id=1]
[node name="SelectNodeDialog" type="WindowDialog"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -150.0
margin_top = -100.0
margin_right = 150.0
margin_bottom = 100.0
rect_min_size = Vector2( 300, 200 )
size_flags_horizontal = 3
size_flags_vertical = 3
window_title = "Select a Node"
resizable = true
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="MarginContainer" type="MarginContainer" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
custom_constants/margin_right = 8
custom_constants/margin_top = 8
custom_constants/margin_left = 8
custom_constants/margin_bottom = 8
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Body" type="VBoxContainer" parent="MarginContainer"]
margin_left = 8.0
margin_top = 8.0
margin_right = 292.0
margin_bottom = 192.0
size_flags_horizontal = 3
size_flags_vertical = 3
__meta__ = {
"_edit_use_anchors_": false
}
[node name="EditedSceneView" type="VBoxContainer" parent="MarginContainer/Body"]
margin_right = 284.0
margin_bottom = 160.0
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="Label" type="Label" parent="MarginContainer/Body/EditedSceneView"]
margin_right = 284.0
margin_bottom = 14.0
size_flags_horizontal = 3
text = "Current Edited Scene:"
[node name="SceneTree" type="Tree" parent="MarginContainer/Body/EditedSceneView"]
margin_top = 18.0
margin_right = 284.0
margin_bottom = 160.0
size_flags_horizontal = 3
size_flags_vertical = 3
columns = 2
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Footer" type="HBoxContainer" parent="MarginContainer/Body"]
margin_top = 164.0
margin_right = 284.0
margin_bottom = 184.0
size_flags_horizontal = 3
[node name="ConfirmButton" type="Button" parent="MarginContainer/Body/Footer"]
margin_left = 25.0
margin_right = 114.0
margin_bottom = 20.0
size_flags_horizontal = 6
text = "Select Node"
[node name="CancelButton" type="Button" parent="MarginContainer/Body/Footer"]
margin_left = 187.0
margin_right = 241.0
margin_bottom = 20.0
size_flags_horizontal = 6
text = "Cancel"
[node name="AlertDialog" type="AcceptDialog" parent="."]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -41.5
margin_top = -29.0
margin_right = 41.5
margin_bottom = 29.0
popup_exclusive = true

View file

@ -1,81 +0,0 @@
tool
extends Container
onready var select_button : Button = $Button
onready var select_node_dialog : WindowDialog = $SelectNodeDialog
const SELECT_BUTTON_DEFAULT_TEXT := "Select a Node"
var sprite : Node setget set_sprite
var _sprite_icon : Texture
var _sprite3d_icon : Texture
signal node_selected(sprite)
func _ready():
select_node_dialog.class_filters = ["Sprite", "Sprite3D"]
select_button.connect("pressed", self, "_on_SelectButton_pressed")
select_node_dialog.connect("node_selected", self, "_on_SelectNodeDialog_node_selected")
func get_state() -> Dictionary:
var state := {}
if sprite:
state.sprite = sprite
return state
func set_state(new_state : Dictionary) -> void:
var new_sprite : Node = new_state.get("sprite")
if new_sprite != null:
self.sprite = new_sprite
else:
sprite = null
select_button.text = SELECT_BUTTON_DEFAULT_TEXT
select_button.icon = _sprite_icon
func _update_theme(editor_theme : EditorTheme) -> void:
var is_sprite3d := select_button.icon == _sprite3d_icon
_sprite_icon = editor_theme.get_icon("Sprite")
_sprite3d_icon = editor_theme.get_icon("Sprite3D")
if is_sprite3d:
select_button.icon = _sprite3d_icon
else:
select_button.icon = _sprite_icon
# Setters and Getters
func set_sprite(node : Node) -> void:
sprite = node
var node_path := node.owner.get_parent().get_path_to(node)
select_button.text = node_path
if node.is_class("Sprite"):
select_button.icon = _sprite_icon
elif node.is_class("Sprite3D"):
select_button.icon = _sprite3d_icon
# Signal Callbacks
func _on_SelectButton_pressed() -> void:
if select_node_dialog.initialize():
select_node_dialog.popup_centered_ratio(.5)
func _on_SelectNodeDialog_node_selected(selected_node : Node) -> void:
self.sprite = selected_node
emit_signal("node_selected", selected_node)

View file

@ -1,43 +0,0 @@
[gd_scene load_steps=5 format=2]
[ext_resource path="res://addons/aseprite_importer/interface/import_menu/SelectNodeDialog.tscn" type="PackedScene" id=1]
[ext_resource path="res://addons/aseprite_importer/interface/import_menu/SelectSpriteMenu.gd" type="Script" id=2]
[sub_resource type="Image" id=3]
data = {
"data": PoolByteArray( 0, 0, 0, 0, 0, 0, 0, 0, 163, 182, 236, 0, 164, 182, 242, 0, 164, 182, 242, 0, 165, 183, 243, 0, 165, 183, 243, 0, 165, 183, 243, 0, 165, 183, 243, 0, 165, 183, 243, 0, 165, 183, 243, 0, 164, 182, 242, 0, 164, 182, 242, 0, 160, 179, 236, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 180, 236, 0, 163, 182, 236, 28, 164, 182, 242, 169, 164, 182, 242, 229, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 164, 182, 242, 229, 164, 182, 242, 169, 160, 179, 236, 27, 160, 179, 236, 0, 0, 0, 0, 0, 160, 179, 236, 0, 160, 179, 236, 27, 164, 182, 242, 236, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 164, 182, 242, 236, 160, 179, 236, 27, 160, 179, 236, 0, 164, 181, 242, 0, 164, 181, 242, 164, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 164, 181, 242, 163, 164, 181, 242, 0, 164, 182, 242, 0, 164, 182, 242, 225, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 164, 182, 242, 225, 164, 182, 242, 0, 165, 183, 243, 0, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 0, 165, 183, 243, 0, 165, 183, 243, 255, 165, 183, 243, 255, 163, 182, 240, 70, 163, 182, 240, 70, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 163, 182, 240, 70, 163, 182, 240, 70, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 0, 165, 183, 243, 0, 165, 183, 243, 255, 165, 183, 243, 255, 164, 182, 241, 0, 164, 182, 241, 0, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 164, 182, 241, 0, 164, 182, 241, 0, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 0, 165, 183, 243, 0, 165, 183, 243, 255, 165, 183, 243, 255, 164, 182, 241, 0, 164, 182, 241, 0, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 164, 182, 241, 0, 164, 182, 241, 0, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 0, 165, 183, 243, 0, 165, 183, 243, 255, 165, 183, 243, 255, 163, 182, 240, 70, 163, 182, 240, 70, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 163, 182, 240, 70, 163, 182, 240, 70, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 0, 165, 183, 243, 0, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 0, 164, 182, 242, 0, 164, 182, 242, 226, 165, 183, 243, 255, 165, 183, 243, 255, 164, 182, 242, 252, 163, 182, 241, 95, 163, 182, 241, 95, 164, 182, 242, 201, 164, 182, 242, 201, 163, 182, 241, 95, 163, 182, 241, 95, 164, 182, 242, 251, 165, 183, 243, 255, 165, 183, 243, 255, 164, 182, 242, 225, 164, 182, 242, 0, 164, 181, 242, 0, 164, 181, 242, 164, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 163, 182, 236, 28, 163, 182, 239, 0, 163, 177, 238, 0, 163, 177, 238, 0, 163, 181, 240, 0, 161, 178, 238, 30, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 164, 181, 242, 164, 164, 181, 242, 0, 160, 179, 236, 0, 160, 179, 236, 27, 164, 182, 242, 237, 165, 183, 243, 255, 165, 183, 243, 255, 164, 182, 242, 226, 163, 182, 242, 84, 163, 173, 234, 25, 163, 173, 234, 25, 165, 183, 243, 85, 164, 182, 242, 226, 165, 183, 243, 255, 165, 183, 243, 255, 164, 182, 242, 237, 160, 179, 236, 27, 160, 179, 236, 0, 0, 0, 0, 0, 161, 180, 236, 0, 163, 182, 236, 28, 164, 182, 242, 169, 164, 182, 242, 229, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 165, 183, 243, 255, 164, 182, 242, 229, 164, 182, 242, 169, 160, 179, 236, 27, 160, 179, 236, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 182, 236, 0, 164, 182, 242, 0, 164, 182, 242, 0, 165, 183, 243, 0, 165, 183, 243, 0, 165, 183, 243, 0, 165, 183, 243, 0, 165, 183, 243, 0, 165, 183, 243, 0, 164, 182, 242, 0, 164, 182, 242, 0, 160, 179, 236, 0, 0, 0, 0, 0, 0, 0, 0, 0 ),
"format": "RGBA8",
"height": 16,
"mipmaps": false,
"width": 16
}
[sub_resource type="ImageTexture" id=2]
flags = 0
flags = 0
image = SubResource( 3 )
size = Vector2( 16, 16 )
[node name="SelectSprite" type="VBoxContainer"]
margin_right = 89.0
margin_bottom = 38.0
size_flags_horizontal = 3
script = ExtResource( 2 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label" type="Label" parent="."]
margin_right = 107.0
margin_bottom = 14.0
text = "Select Sprite"
[node name="Button" type="Button" parent="."]
margin_top = 18.0
margin_right = 107.0
margin_bottom = 40.0
hint_tooltip = "Select a Sprite node from the current scene"
text = "Select Node"
icon = SubResource( 2 )
[node name="SelectNodeDialog" parent="." instance=ExtResource( 1 )]

View file

@ -1,202 +0,0 @@
tool
extends Container
onready var select_all_button : CheckBox = find_node("SelectAllButton")
onready var options_list : VBoxContainer = find_node("OptionsList")
onready var tree : Tree = $Tree
enum Columns {
SELECTED,
NAME,
START,
END,
DIRECTION,
}
var _tree_root : TreeItem
var _options := []
var _toggling_option := false
signal frame_selected(idx)
signal selected_tags_changed(selected_tags)
signal tag_selected(tag_name)
func _ready():
clear_options()
tree.columns = Columns.size()
tree.set_column_expand(Columns.SELECTED, false)
tree.set_column_min_width(Columns.SELECTED, 32)
tree.set_column_title(Columns.NAME, "Name")
tree.set_column_expand(Columns.NAME, true)
tree.set_column_min_width(Columns.START, 48)
tree.set_column_title(Columns.START, "Start")
tree.set_column_expand(Columns.START, false)
tree.set_column_min_width(Columns.START, 48)
tree.set_column_title(Columns.END, "End")
tree.set_column_expand(Columns.END, false)
tree.set_column_min_width(Columns.END, 48)
tree.set_column_title(Columns.DIRECTION, "Direction")
tree.set_column_expand(Columns.DIRECTION, false)
tree.set_column_min_width(Columns.DIRECTION, 84)
tree.set_column_titles_visible(true)
select_all_button.connect("toggled", self, "_on_SelectAllButton_toggled")
tree.connect("cell_selected", self, "_on_Tree_cell_selected")
tree.connect("item_edited", self, "_on_Tree_item_edited")
func clear_options() -> void:
select_all_button.hide()
for option in _options:
option.free()
_options.clear()
tree.clear()
_tree_root = tree.create_item()
func load_tags(tags : Array) -> void:
clear_options()
if tags == []:
return
for tag in tags:
var new_tree_item := tree.create_item(_tree_root)
new_tree_item.set_cell_mode(Columns.SELECTED, TreeItem.CELL_MODE_CHECK)
new_tree_item.set_editable(Columns.SELECTED, true)
new_tree_item.set_checked(Columns.SELECTED, true)
new_tree_item.set_selectable(Columns.SELECTED, false)
new_tree_item.set_text(Columns.NAME, tag.name)
new_tree_item.set_text(Columns.START, str(floor(tag.from)))
new_tree_item.set_text_align(Columns.START, TreeItem.ALIGN_CENTER)
new_tree_item.set_text(Columns.END, str(floor(tag.to)))
new_tree_item.set_text_align(Columns.END, TreeItem.ALIGN_CENTER)
new_tree_item.set_text(Columns.DIRECTION, " %s" % tag.direction)
new_tree_item.set_selectable(Columns.DIRECTION, false)
_options.append(new_tree_item)
select_all_button.pressed = true
select_all_button.show()
func get_selected_tags() -> Array:
var selected_tags := []
for i in range(_options.size()):
var item : TreeItem = _options[i]
if item.is_checked(Columns.SELECTED):
selected_tags.append(i)
return selected_tags
func get_state() -> Dictionary:
var state := {
selected_tags = get_selected_tags()
}
var selected_item := tree.get_selected()
if selected_item != null:
var selected_column := tree.get_selected_column()
var item_idx := _options.find(selected_item)
state.selected_cell = Vector2(selected_column, item_idx)
return state
func set_state(new_state : Dictionary) -> void:
if new_state.has("selected_tags") and _options != []:
select_all_button.pressed = false
for tag in new_state.selected_tags:
_options[tag].set_checked(Columns.SELECTED, true)
if new_state.has("selected_cell"):
var selected_cell : Vector2 = new_state.selected_cell
var tree_item : TreeItem = _options[selected_cell.y]
var column : int = selected_cell.x
tree_item.select(column)
match column:
Columns.NAME:
emit_signal("tag_selected", selected_cell.y)
Columns.START, Columns.END:
emit_signal("frame_selected", int(tree_item.get_text(column)))
for option in _options:
if not option.is_checked(Columns.SELECTED):
return
_toggling_option = true
select_all_button.pressed = true
_toggling_option = false
# Signal Callbacks
func _on_SelectAllButton_toggled(button_pressed : bool) -> void:
if _toggling_option:
return
for option in _options:
option.set_checked(Columns.SELECTED, button_pressed)
emit_signal("selected_tags_changed", get_selected_tags())
func _on_Tree_cell_selected() -> void:
var selected_column := tree.get_selected_column()
var selected_item := tree.get_selected()
match selected_column:
Columns.NAME:
emit_signal("tag_selected", _options.find(selected_item))
Columns.START, Columns.END:
emit_signal("frame_selected", int(selected_item.get_text(selected_column)))
func _on_Tree_item_edited() -> void:
_toggling_option = true
if select_all_button.pressed:
for option in _options:
if option.is_checked(Columns.SELECTED):
select_all_button.pressed = false
break
else:
var is_all_selected := true
for option in _options:
if not option.is_checked(Columns.SELECTED):
is_all_selected = false
break
if is_all_selected:
select_all_button.pressed = true
_toggling_option = false
emit_signal("selected_tags_changed", get_selected_tags())

View file

@ -1,41 +0,0 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/aseprite_importer/interface/import_menu/TagsMenu.gd" type="Script" id=1]
[node name="TagSelectMenu" type="VBoxContainer"]
rect_min_size = Vector2( 0, 120 )
size_flags_vertical = 3
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Header" type="HBoxContainer" parent="."]
margin_right = 28.0
margin_bottom = 14.0
[node name="Label" type="Label" parent="Header"]
margin_right = 28.0
margin_bottom = 14.0
size_flags_horizontal = 3
text = "Tags"
valign = 1
[node name="SelectAllButton" type="CheckBox" parent="Header"]
visible = false
margin_left = 32.0
margin_right = 120.0
margin_bottom = 24.0
size_flags_horizontal = 8
text = "Select All"
[node name="Tree" type="Tree" parent="."]
margin_top = 18.0
margin_right = 28.0
margin_bottom = 120.0
size_flags_vertical = 3
columns = 5
hide_folding = true
hide_root = true

View file

@ -1,95 +0,0 @@
tool
extends Container
onready var label : Label = $Header/Label
onready var visibility_button: Button = $Header/VisibilityButton
onready var color_picker : ColorPickerButton = $ColorPicker
export var label_text := '' setget set_label_text
export var visibility := true setget set_visibility
export var show_visibility_button := true setget set_show_visibility_button
export var color_value := Color.black setget set_color_value
export var color_edit_alpha := true setget set_color_edit_alpha
export(String, MULTILINE) var color_picker_tooltip := "" setget set_color_picker_tooltip
var _visible_icon : Texture
var _hidden_icon : Texture
signal property_changed(color_menu_item)
func _ready():
self.label_text = label_text
self.visibility = visibility
self.show_visibility_button = show_visibility_button
self.color_value = color_value
self.color_edit_alpha = color_edit_alpha
self.color_picker_tooltip = color_picker_tooltip
visibility_button.connect('pressed', self, '_on_ViewButton_pressed')
color_picker.connect('color_changed', self, '_on_ColorPicker_color_changed')
func _update_theme(editor_theme : EditorTheme) -> void:
_visible_icon = editor_theme.get_icon('GuiVisibilityVisible')
_hidden_icon = editor_theme.get_icon('GuiVisibilityHidden')
self.visibility = visibility
# Setters and Getters
func set_color_picker_tooltip(text : String) -> void:
color_picker_tooltip = text
if color_picker:
color_picker.hint_tooltip = text
func set_color_value(color: Color) -> void:
color_value = color
if color_picker:
color_picker.color = color_value
func set_color_edit_alpha(value : bool) -> void:
color_edit_alpha = value
if color_picker:
color_picker.edit_alpha = color_edit_alpha
func set_label_text(text : String) -> void:
label_text = text
if label:
label.text = label_text
func set_show_visibility_button(show_button : bool) -> void:
show_visibility_button = show_button
if visibility_button:
visibility_button.visible = show_visibility_button
func set_visibility(value : bool) -> void:
visibility = value
if visibility_button:
if visibility:
visibility_button.icon = _visible_icon
visibility_button.modulate.a = 1
else:
visibility_button.icon = _hidden_icon
visibility_button.modulate.a = .5
# Signal Callbacks
func _on_ColorPicker_color_changed(color : Color) -> void:
color_value = color
emit_signal('property_changed', self)
func _on_ViewButton_pressed() -> void:
self.visibility = !visibility
emit_signal('property_changed', self)

View file

@ -1,37 +0,0 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/aseprite_importer/interface/spritesheet_inspector/ColorMenuItem.gd" type="Script" id=1]
[node name="ColorMenuItem" type="VBoxContainer"]
margin_right = 103.0
margin_bottom = 46.0
size_flags_horizontal = 3
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Header" type="HBoxContainer" parent="."]
margin_right = 116.0
margin_bottom = 22.0
rect_min_size = Vector2( 0, 22 )
[node name="Label" type="Label" parent="Header"]
margin_top = 4.0
margin_right = 100.0
margin_bottom = 18.0
size_flags_horizontal = 3
text = "ColorMenuItem"
[node name="VisibilityButton" type="ToolButton" parent="Header"]
margin_left = 104.0
margin_right = 116.0
margin_bottom = 22.0
hint_tooltip = "Toggle Visibility"
size_flags_horizontal = 8
shortcut_in_tooltip = false
[node name="ColorPicker" type="ColorPickerButton" parent="."]
margin_top = 26.0
margin_right = 116.0
margin_bottom = 46.0

View file

@ -1,74 +0,0 @@
tool
extends Container
onready var options : Container = $Options
const PROP_TO_COLOR_MENU := {
frame_border = "FrameBorder",
selection_border = "SelectionBorder",
texture_background = "TextureBackground",
inspector_background = "InspectorBackground",
}
const DEFAULT_SETTINGS :={
frame_border = {
color = Color("#808080"),
visibility = true,
},
selection_border = {
color = Color.yellow,
visibility = true,
},
texture_background = {
color = Color("#404040"),
visibility = true,
},
inspector_background = {
color = Color.black,
},
}
var settings := DEFAULT_SETTINGS.duplicate(true) setget set_settings
signal settings_changed(settings)
func _ready():
for property in PROP_TO_COLOR_MENU:
var node_name : String = PROP_TO_COLOR_MENU[property]
var color_menu = options.get_node(node_name)
color_menu.set_meta("property", property)
color_menu.connect("property_changed", self, "_on_ColorMenuItem_property_changed")
# Setters and Getters
func set_settings(new_settings : Dictionary) -> void:
if new_settings:
settings = new_settings
else:
settings = DEFAULT_SETTINGS.duplicate(true)
for property in PROP_TO_COLOR_MENU:
var node_name : String = PROP_TO_COLOR_MENU[property]
var color_menu = options.get_node(node_name)
color_menu.color_value = settings[property].color
color_menu.visibility = settings[property].get("visibility", false)
emit_signal("settings_changed", settings)
# Signal Callbacks
func _on_ColorMenuItem_property_changed(color_menu_item : Node) -> void:
var property : String = color_menu_item.get_meta("property")
settings[property]["color"] = color_menu_item.color_value
settings[property]["visibility"] = color_menu_item.visibility
emit_signal("settings_changed", settings)

View file

@ -1,247 +0,0 @@
tool
extends Container
onready var header : HBoxContainer= $Header
onready var filename_label : Label = header.find_node("Filename")
onready var settings_button : Button = header.find_node("SettingsButton")
onready var body : Container = $Body
onready var warning_message : Label = body.find_node("WarningMessage")
onready var search_file_button : Button = body.find_node("SearchFileButton")
onready var spritesheet_view : Container = body.find_node("SpritesheetView")
onready var settings_menu : Container = body.get_node("SettingsMenu")
onready var footer : HBoxContainer = $Footer
onready var frame_count : Label = footer.get_node("FrameCount")
onready var zoom_button : Button = footer.get_node("ZoomButton")
onready var zoom_slider : HSlider = footer.get_node("ZoomSlider")
onready var file_dialog : FileDialog = $FileDialog
const MSG_MISSING_IMAGE_PARAMETER = "The imported JSON doesn't contain the spritesheet file name"
const MSG_IMPORT_JSON = "Import a Aseprite JSON file to \npreview the spritesheet"
const MSG_INVALID_TEXTURE_SIZE = "The selected texture size %s doesn't match the JSON %s"
const MSG_LOAD_ERROR = "Error on loading the file!"
const MSG_SPRITESHEET_NOT_FOUND = "Spritesheet \"%s\" not found!"
var texture_size : Vector2 setget set_texture_size
var frames := []
var _zoom_update := false
func _ready() -> void:
clear_texture()
settings_button.pressed = false
warning_message.text = MSG_IMPORT_JSON
search_file_button.hide()
spritesheet_view.hide()
settings_menu.hide()
var settings = settings_menu.settings
spritesheet_view.load_settings(settings)
settings_button.connect("toggled", self, "_on_SettingsButton_toggled")
search_file_button.connect("pressed", self, "_on_SearchFileButton_pressed")
spritesheet_view.connect("zoom_changed", self, "_on_SpritesheetInspector_zoom_changed")
settings_menu.connect("settings_changed", self, "_on_SettingsMenu_settings_changed")
zoom_button.connect("pressed", self, "_on_ZoomButton_pressed")
zoom_slider.connect("value_changed", self, "_on_ZoomSlider_value_changed")
file_dialog.connect("file_selected", self, "_on_FileDialog_file_selected")
func clear_texture() -> void:
filename_label.text = ""
spritesheet_view.hide()
spritesheet_view.texture = null
warning_message.text = MSG_IMPORT_JSON
search_file_button.hide()
footer.hide()
func get_state() -> Dictionary:
var state := {}
if spritesheet_view.texture:
state.texture = spritesheet_view.texture
state.zoom = spritesheet_view.zoom
state.offset = spritesheet_view.offset
state.warning_msg = warning_message.text
state.search_file_button_visible =search_file_button.visible
state.settings = settings_menu.settings
return state
func get_texture() -> Texture:
return spritesheet_view.texture
func load_texture(path : String) -> int:
if not path:
_show_find_file_prompt(MSG_MISSING_IMAGE_PARAMETER)
return ERR_INVALID_DATA
clear_texture()
var split_path := path.rsplit("/", true, 1)
var dir_path := split_path[0]
var file_name := split_path[1]
if file_name == "":
_show_find_file_prompt(MSG_MISSING_IMAGE_PARAMETER)
file_dialog.current_dir = dir_path
return ERR_INVALID_DATA
var file := File.new()
if !file.file_exists(path):
_show_find_file_prompt(MSG_SPRITESHEET_NOT_FOUND % file_name)
file_dialog.current_dir = dir_path
return ERR_FILE_NOT_FOUND
var new_texture : Texture = load(path)
if new_texture == null:
_show_find_file_prompt(MSG_LOAD_ERROR)
return ERR_INVALID_DATA
var new_texture_size := new_texture.get_size()
if new_texture_size != texture_size:
var message := MSG_INVALID_TEXTURE_SIZE % [new_texture.get_size(), texture_size]
_show_find_file_prompt(message)
return ERR_INVALID_DATA
spritesheet_view.texture = new_texture
spritesheet_view.frames = frames
spritesheet_view.selected_frames = []
filename_label.text = file_name
_update_frames_count()
spritesheet_view.show()
footer.show()
return OK
func select_frames(selected_frames : Array) -> void:
spritesheet_view.selected_frames = selected_frames
func set_state(new_state : Dictionary) -> void:
if new_state.get("texture", false):
spritesheet_view.texture = new_state.texture
spritesheet_view.zoom = new_state.zoom
spritesheet_view.offset = new_state.offset
spritesheet_view.frames = frames
spritesheet_view.selected_frames = new_state.get("selected_frames", [])
filename_label.text = new_state.texture.resource_path
_update_frames_count()
spritesheet_view.show()
footer.show()
else:
clear_texture()
warning_message.text = new_state.get("warning_msg", MSG_IMPORT_JSON)
search_file_button.visible = new_state.get("search_file_button_visible", (warning_message.text != MSG_IMPORT_JSON))
settings_menu.settings = new_state.get("settings", {})
func _show_find_file_prompt(message : String) -> void:
clear_texture()
warning_message.text = message
search_file_button.show()
func _update_frames_count() -> void:
var frames_size := frames.size()
if frames_size <= 0:
frame_count.text = ""
return
frame_count.text = "%d frames" % frames_size
var distinct_regions := []
for frame in frames:
var region : Dictionary = frame.frame
var rect := Rect2(region.x, region.y, region.w, region.h)
if distinct_regions.find(rect) == -1:
distinct_regions.append(rect)
var distinct_frames_size := distinct_regions.size()
if frames_size > distinct_frames_size:
var merged_frames_count := frames_size - distinct_frames_size
frame_count.text += " (%d merged)" % merged_frames_count
func _update_theme(editor_theme : EditorTheme) -> void:
settings_button.icon = editor_theme.get_icon("Tools")
search_file_button.icon = editor_theme.get_icon("Load")
zoom_button.icon = editor_theme.get_icon("Zoom")
# Setters and Getters
func set_texture_size(value : Vector2) -> void:
texture_size = value
# Signal Callbacks
func _on_FileDialog_file_selected(path) -> void:
load_texture(path)
func _on_SearchFileButton_pressed() -> void:
file_dialog.invalidate()
file_dialog.popup_centered_ratio(.5)
func _on_SettingsButton_toggled(button_pressed : bool) -> void:
settings_menu.visible = button_pressed
func _on_SettingsMenu_settings_changed(settings : Dictionary) -> void:
spritesheet_view.load_settings(settings)
func _on_SpritesheetInspector_zoom_changed(new_zoom : int) -> void:
_zoom_update = true
zoom_button.text = "%d X" % new_zoom
zoom_slider.value = new_zoom
_zoom_update = false
func _on_ZoomButton_pressed() -> void:
zoom_slider.value = 1
func _on_ZoomSlider_value_changed(value : float) -> void:
if not _zoom_update:
spritesheet_view.zoom = round(value)

View file

@ -1,255 +0,0 @@
[gd_scene load_steps=14 format=2]
[ext_resource path="res://addons/aseprite_importer/interface/spritesheet_inspector/ColorMenuItem.tscn" type="PackedScene" id=1]
[ext_resource path="res://addons/aseprite_importer/interface/spritesheet_inspector/SpritesheetView.tscn" type="PackedScene" id=2]
[ext_resource path="res://addons/aseprite_importer/interface/spritesheet_inspector/SettingsMenu.gd" type="Script" id=3]
[ext_resource path="res://addons/aseprite_importer/interface/spritesheet_inspector/SpritesheetInspector.gd" type="Script" id=4]
[ext_resource path="res://addons/aseprite_importer/interface/spritesheet_inspector/godot_button/godot_hover.png" type="Texture" id=5]
[ext_resource path="res://addons/aseprite_importer/interface/spritesheet_inspector/godot_button/godot_normal.png" type="Texture" id=6]
[ext_resource path="res://addons/aseprite_importer/interface/spritesheet_inspector/godot_button/godot_pressed.png" type="Texture" id=7]
[sub_resource type="Image" id=7]
data = {
"data": PoolByteArray( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 221, 221, 0, 224, 224, 224, 0, 221, 221, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 221, 221, 0, 221, 221, 221, 60, 224, 224, 224, 255, 221, 221, 221, 60, 221, 221, 221, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 112, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 112, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 189, 224, 224, 224, 255, 223, 223, 223, 189, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 122, 224, 224, 224, 255, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 255, 223, 223, 223, 122, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 222, 222, 0, 222, 222, 222, 190, 224, 224, 224, 255, 222, 222, 222, 190, 222, 222, 222, 0, 223, 223, 223, 0, 223, 223, 223, 212, 224, 224, 224, 255, 223, 223, 223, 0, 223, 223, 223, 0, 224, 224, 224, 255, 223, 223, 223, 211, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 221, 221, 0, 221, 221, 221, 61, 224, 224, 224, 255, 221, 221, 221, 61, 221, 221, 221, 0, 223, 223, 223, 0, 223, 223, 223, 212, 224, 224, 224, 255, 222, 222, 222, 70, 222, 222, 222, 70, 224, 224, 224, 255, 223, 223, 223, 212, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 222, 222, 0, 224, 224, 224, 255, 222, 222, 222, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 122, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 223, 223, 223, 122, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 114, 224, 224, 224, 255, 224, 224, 224, 255, 223, 223, 223, 113, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 224, 224, 224, 255, 224, 224, 224, 255, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 0, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 222, 222, 0, 222, 222, 222, 247, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 222, 222, 222, 247, 222, 222, 222, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 185, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 223, 223, 223, 185, 223, 223, 223, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 221, 221, 0, 221, 221, 221, 30, 222, 222, 222, 181, 223, 223, 223, 254, 222, 222, 222, 181, 221, 221, 221, 30, 221, 221, 221, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 180, 223, 223, 223, 180, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 221, 221, 0, 222, 222, 222, 0, 223, 223, 223, 0, 222, 222, 222, 0, 221, 221, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ),
"format": "RGBA8",
"height": 16,
"mipmaps": false,
"width": 16
}
[sub_resource type="ImageTexture" id=2]
flags = 0
flags = 0
image = SubResource( 7 )
size = Vector2( 16, 16 )
[sub_resource type="Image" id=8]
data = {
"data": PoolByteArray( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 221, 221, 0, 223, 223, 223, 0, 224, 224, 224, 0, 224, 224, 224, 0, 223, 223, 223, 0, 221, 221, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 221, 221, 0, 221, 221, 221, 60, 223, 223, 223, 201, 224, 224, 224, 255, 224, 224, 224, 255, 223, 223, 223, 201, 221, 221, 221, 60, 221, 221, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 222, 222, 0, 222, 222, 222, 199, 222, 222, 222, 70, 223, 223, 223, 0, 223, 223, 223, 0, 222, 222, 222, 70, 222, 222, 222, 199, 223, 223, 223, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 222, 222, 0, 223, 223, 223, 180, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 223, 223, 223, 180, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 222, 222, 0, 223, 223, 223, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 223, 223, 223, 0, 224, 224, 224, 0, 224, 224, 224, 0, 222, 222, 222, 0, 0, 0, 0, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 0, 0, 0, 0, 0, 217, 217, 217, 0, 222, 222, 222, 173, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 222, 222, 222, 173, 222, 222, 222, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 0, 212, 212, 212, 0, 212, 212, 212, 18, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 223, 223, 223, 232, 223, 223, 223, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 0, 221, 221, 221, 0, 221, 221, 221, 60, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 223, 223, 223, 188, 223, 223, 223, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 0, 222, 222, 222, 0, 222, 222, 222, 103, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 223, 223, 223, 147, 223, 223, 223, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 0, 223, 223, 223, 0, 223, 223, 223, 145, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 223, 223, 223, 104, 223, 223, 223, 0, 224, 224, 224, 0, 224, 224, 224, 255, 224, 224, 224, 0, 223, 223, 223, 0, 223, 223, 223, 187, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 222, 222, 222, 62, 222, 222, 222, 0, 224, 224, 224, 0, 224, 224, 224, 255, 223, 223, 223, 0, 222, 222, 222, 0, 223, 223, 223, 230, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 214, 214, 214, 19, 214, 214, 214, 0, 223, 223, 223, 0, 223, 223, 223, 200, 222, 222, 222, 70, 221, 221, 221, 75, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 223, 223, 223, 193, 218, 218, 218, 0, 0, 0, 0, 0, 221, 221, 221, 0, 221, 221, 221, 60, 223, 223, 223, 202, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 222, 222, 222, 198, 220, 220, 220, 51, 220, 220, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 221, 221, 0, 223, 223, 223, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 224, 224, 224, 0, 222, 222, 222, 0, 220, 220, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0 ),
"format": "RGBA8",
"height": 16,
"mipmaps": false,
"width": 16
}
[sub_resource type="ImageTexture" id=4]
flags = 0
flags = 0
image = SubResource( 8 )
size = Vector2( 16, 16 )
[sub_resource type="Image" id=9]
data = {
"data": PoolByteArray( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 0, 221, 221, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 222, 222, 0, 223, 223, 223, 57, 223, 223, 223, 177, 223, 223, 223, 228, 223, 223, 223, 234, 223, 223, 223, 185, 221, 221, 221, 61, 221, 221, 221, 0, 223, 223, 223, 0, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 222, 222, 0, 222, 222, 222, 118, 223, 223, 223, 253, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 222, 222, 222, 0, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 0, 223, 223, 223, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 56, 223, 223, 223, 251, 222, 222, 222, 247, 222, 222, 222, 116, 223, 223, 223, 24, 220, 220, 220, 22, 223, 223, 223, 115, 223, 223, 223, 0, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 0, 222, 222, 222, 0, 222, 222, 222, 174, 223, 223, 223, 254, 222, 222, 222, 116, 222, 222, 222, 0, 223, 223, 223, 0, 220, 220, 220, 0, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 224, 223, 223, 223, 254, 223, 223, 223, 24, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 0, 223, 223, 223, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 229, 223, 223, 223, 254, 214, 214, 214, 19, 214, 214, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 24, 223, 223, 223, 254, 223, 223, 223, 0, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 179, 223, 223, 223, 254, 223, 223, 223, 115, 222, 222, 222, 0, 223, 223, 223, 0, 223, 223, 223, 0, 222, 222, 222, 0, 222, 222, 222, 116, 223, 223, 223, 254, 222, 222, 222, 0, 223, 223, 223, 0, 223, 223, 223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223, 223, 0, 223, 223, 223, 57, 223, 223, 223, 252, 223, 223, 223, 246, 222, 222, 222, 116, 223, 223, 223, 24, 223, 223, 223, 24, 222, 222, 222, 116, 223, 223, 223, 246, 223, 223, 223, 254, 222, 222, 222, 86, 218, 218, 218, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 222, 222, 0, 222, 222, 222, 118, 223, 223, 223, 253, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 254, 223, 223, 223, 209, 214, 214, 214, 19, 214, 214, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220, 0, 219, 219, 219, 58, 223, 223, 223, 177, 223, 223, 223, 228, 223, 223, 223, 237, 222, 222, 222, 183, 223, 223, 223, 80, 223, 223, 223, 209, 223, 223, 223, 254, 223, 223, 223, 208, 214, 214, 214, 19, 214, 214, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 219, 219, 0, 223, 223, 223, 0, 223, 223, 223, 0, 223, 223, 223, 0, 222, 222, 222, 0, 220, 220, 220, 0, 218, 218, 218, 21, 223, 223, 223, 209, 223, 223, 223, 254, 222, 222, 222, 207, 214, 214, 214, 19, 214, 214, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 218, 218, 0, 218, 218, 218, 21, 223, 223, 223, 210, 223, 223, 223, 254, 222, 222, 222, 206, 214, 214, 214, 19, 214, 214, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 218, 218, 0, 218, 218, 218, 21, 223, 223, 223, 211, 223, 223, 223, 228, 219, 219, 219, 36, 219, 219, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 218, 218, 0, 218, 218, 218, 21, 218, 218, 218, 35, 218, 218, 218, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 218, 218, 0, 218, 218, 218, 0, 0, 0, 0, 0, 0, 0, 0, 0 ),
"format": "RGBA8",
"height": 16,
"mipmaps": false,
"width": 16
}
[sub_resource type="ImageTexture" id=6]
flags = 0
flags = 0
image = SubResource( 9 )
size = Vector2( 16, 16 )
[node name="SpritesheetInspector" type="VBoxContainer"]
anchor_right = 1.0
anchor_bottom = 1.0
size_flags_horizontal = 3
script = ExtResource( 4 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Header" type="HBoxContainer" parent="."]
margin_right = 1024.0
margin_bottom = 24.0
[node name="Filename" type="Label" parent="Header"]
margin_top = 5.0
margin_bottom = 19.0
[node name="Buttons" type="HBoxContainer" parent="Header"]
margin_left = 942.0
margin_right = 1024.0
margin_bottom = 24.0
size_flags_horizontal = 10
[node name="SettingsButton" type="ToolButton" parent="Header/Buttons"]
margin_right = 82.0
margin_bottom = 24.0
hint_tooltip = "Spritesheet Inspector's settings"
toggle_mode = true
text = "Settings"
icon = SubResource( 2 )
[node name="Body" type="HBoxContainer" parent="."]
margin_top = 28.0
margin_right = 1024.0
margin_bottom = 600.0
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="MainView" type="MarginContainer" parent="Body"]
margin_right = 1024.0
margin_bottom = 572.0
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="WarningView" type="VBoxContainer" parent="Body/MainView"]
margin_left = 415.0
margin_top = 230.0
margin_right = 608.0
margin_bottom = 341.0
size_flags_horizontal = 6
size_flags_vertical = 6
custom_constants/separation = 16
[node name="GodotButton" type="TextureButton" parent="Body/MainView/WarningView"]
margin_left = 64.0
margin_right = 128.0
margin_bottom = 64.0
rect_min_size = Vector2( 64, 64 )
hint_tooltip = "Hello!"
focus_mode = 0
mouse_default_cursor_shape = 2
size_flags_horizontal = 4
size_flags_vertical = 4
shortcut_in_tooltip = false
enabled_focus_mode = 0
texture_normal = ExtResource( 6 )
texture_pressed = ExtResource( 7 )
texture_hover = ExtResource( 5 )
expand = true
[node name="WarningMessage" type="Label" parent="Body/MainView/WarningView"]
margin_top = 80.0
margin_right = 193.0
margin_bottom = 111.0
size_flags_horizontal = 4
size_flags_vertical = 0
text = "Import a Aseprite JSON file to
preview the spritesheet"
align = 1
valign = 1
[node name="SearchFileButton" type="Button" parent="Body/MainView/WarningView"]
visible = false
margin_left = 47.0
margin_top = 127.0
margin_right = 146.0
margin_bottom = 149.0
hint_tooltip = "Search for the spritesheet file"
size_flags_horizontal = 4
size_flags_vertical = 0
text = "Search File"
icon = SubResource( 4 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="SpritesheetView" parent="Body/MainView" instance=ExtResource( 2 )]
visible = false
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 1024.0
margin_bottom = 572.0
[node name="SettingsMenu" type="ScrollContainer" parent="Body"]
visible = false
margin_left = 882.0
margin_right = 1024.0
margin_bottom = 572.0
size_flags_horizontal = 8
size_flags_vertical = 3
follow_focus = true
scroll_horizontal_enabled = false
script = ExtResource( 3 )
[node name="Options" type="VBoxContainer" parent="Body/SettingsMenu"]
margin_right = 142.0
margin_bottom = 196.0
[node name="FrameBorder" parent="Body/SettingsMenu/Options" instance=ExtResource( 1 )]
margin_right = 142.0
label_text = "Frame Border"
visibility = true
show_visibility_button = true
color_value = Color( 0.501961, 0.501961, 0.501961, 1 )
color_edit_alpha = false
color_picker_tooltip = "Change the border color of unselected frames"
[node name="SelectionBorder" parent="Body/SettingsMenu/Options" instance=ExtResource( 1 )]
margin_top = 50.0
margin_right = 142.0
margin_bottom = 96.0
label_text = "Selection Border"
visibility = true
show_visibility_button = true
color_value = Color( 1, 1, 0, 1 )
color_edit_alpha = false
color_picker_tooltip = "Change the border color of selected frames"
[node name="TextureBackground" parent="Body/SettingsMenu/Options" instance=ExtResource( 1 )]
margin_top = 100.0
margin_right = 142.0
margin_bottom = 146.0
label_text = "Texture Background"
visibility = true
show_visibility_button = true
color_value = Color( 0.25098, 0.25098, 0.25098, 1 )
color_edit_alpha = false
color_picker_tooltip = "Change the background color of the spritesheet's transparent area "
[node name="InspectorBackground" parent="Body/SettingsMenu/Options" instance=ExtResource( 1 )]
margin_top = 150.0
margin_right = 142.0
margin_bottom = 196.0
label_text = "Inspector Background"
visibility = false
show_visibility_button = false
color_value = Color( 0, 0, 0, 1 )
color_edit_alpha = false
color_picker_tooltip = "Change the background color of the inspector"
[node name="Footer" type="HBoxContainer" parent="."]
visible = false
margin_top = 218.0
margin_right = 400.0
margin_bottom = 240.0
[node name="FrameCount" type="Label" parent="Footer"]
margin_top = 4.0
margin_bottom = 18.0
[node name="ZoomButton" type="ToolButton" parent="Footer"]
margin_left = 273.0
margin_right = 300.0
margin_bottom = 22.0
size_flags_horizontal = 10
text = "1 X"
icon = SubResource( 6 )
[node name="ZoomSlider" type="HSlider" parent="Footer"]
margin_left = 304.0
margin_top = 3.0
margin_right = 400.0
margin_bottom = 19.0
rect_min_size = Vector2( 96, 0 )
size_flags_horizontal = 8
size_flags_vertical = 6
min_value = 1.0
max_value = 8.0
value = 1.0
[node name="FileDialog" type="FileDialog" parent="."]
margin_left = 186.0
margin_right = 402.0
margin_bottom = 240.0
window_title = "Select the Spritesheet"
resizable = true
mode_overrides_title = false
mode = 0
filters = PoolStringArray( "*.png ; PNG Files" )
show_hidden_files = true

View file

@ -1,315 +0,0 @@
tool
extends Container
onready var h_scroll_bar : HScrollBar = $HScrollBar
onready var v_scroll_bar : VScrollBar = $VScrollBar
export(Texture) var texture : Texture setget set_texture
export(int, 1, 8) var zoom := 1 setget set_zoom
export(Vector2) var offset := Vector2.ZERO setget set_offset
export(bool)var zoom_to_fit := true
var frames = []
var selected_frames := [] setget set_selected_frames
var frame_border_color := Color.red
var frame_border_visibility := true
var selection_border_color := Color.yellow
var selection_border_visibility := true
var border_width := 2
var texture_background_color := Color.green
var texture_background_visibility := true
var background_color := Color.blue
var _full_rect := Rect2(Vector2.ZERO, rect_size)
var _render_rect : Rect2
var _texture_size : Vector2
var _min_offset : Vector2
var _max_offset : Vector2
var _zoom_pivot : Vector2
var _updating_scroll_bars := false
var _panning := false
signal zoom_changed(new_zoom)
func _ready() -> void:
h_scroll_bar.value = .5
v_scroll_bar.value = .5
connect("resized", self, "_on_resized")
h_scroll_bar.connect("value_changed", self, "_on_HScrollBar_value_changed")
v_scroll_bar.connect("value_changed", self, "_on_VScrollBar_value_changed")
update()
func _draw() -> void:
draw_rect(_full_rect, background_color)
if not texture:
return
if texture_background_visibility:
draw_rect(_render_rect, texture_background_color)
draw_texture_rect(texture, _render_rect, false)
if frame_border_visibility:
for frame_idx in range(frames.size()):
if (not selection_border_visibility) or (not frame_idx in selected_frames):
_draw_frame_border(frame_idx)
if selection_border_visibility:
for frame_idx in selected_frames:
_draw_frame_border(frame_idx, true)
func _draw_frame_border(frame_idx : int, selected := false) -> void:
var sprite_region = frames[frame_idx].frame
var frame_rect := _render_rect
frame_rect.position += Vector2(sprite_region.x, sprite_region.y) * zoom
frame_rect.size = Vector2(sprite_region.w, sprite_region.h) * zoom
var border_color
if frame_idx in selected_frames:
border_color = selection_border_color
else:
border_color = frame_border_color
draw_rect(frame_rect, border_color, false, border_width)
func _gui_input(event: InputEvent) -> void:
if event is InputEventMouseButton:
match event.button_index:
BUTTON_MIDDLE:
_panning = event.pressed
if _panning:
mouse_default_cursor_shape = CURSOR_DRAG
else:
mouse_default_cursor_shape = CURSOR_ARROW
BUTTON_WHEEL_UP, BUTTON_WHEEL_DOWN:
if event.pressed:
_zoom_pivot = get_local_mouse_position()
if event.button_index == BUTTON_WHEEL_UP:
self.zoom += 1
else:
self.zoom -= 1
_zoom_pivot = _full_rect.size / 2
elif event is InputEventMouseMotion:
if _panning:
self.offset += event.relative
func load_settings(settings : Dictionary) -> void:
frame_border_color = settings.frame_border.color
frame_border_visibility = settings.frame_border.visibility
selection_border_color = settings.selection_border.color
selection_border_visibility = settings.selection_border.visibility
texture_background_color = settings.texture_background.color
texture_background_visibility = settings.texture_background.visibility
background_color = settings.inspector_background.color
update()
func _update_offset_limits() -> void:
var full_rect_width := _full_rect.size.x
var render_rect_width := _render_rect.size.x
if render_rect_width <= full_rect_width:
_min_offset.x = 0
_max_offset.x = full_rect_width - render_rect_width
else:
_min_offset.x = -(render_rect_width - full_rect_width)
_max_offset.x = 0
var full_rect_height := _full_rect.size.y
var render_rect_height := _render_rect.size.y
if render_rect_height <= full_rect_height:
_min_offset.y = 0
_max_offset.y = full_rect_height - render_rect_height
else:
_min_offset.y = -(render_rect_height - full_rect_height)
_max_offset.y = 0
func _update_scrollbars() ->void:
_updating_scroll_bars = true
if h_scroll_bar:
var full_width:= _full_rect.size.x
var render_width:= _render_rect.size.x
if render_width > full_width:
var h_page := full_width / render_width
h_scroll_bar.page = h_page
h_scroll_bar.max_value = 1 + h_page
var value := inverse_lerp(_max_offset.x, _min_offset.x, offset.x)
h_scroll_bar.value = value
h_scroll_bar.show()
else:
h_scroll_bar.hide()
if v_scroll_bar:
var full_height:= _full_rect.size.y
var render_height:= _render_rect.size.y
if render_height > full_height:
var v_page := full_height / render_height
v_scroll_bar.page = v_page
v_scroll_bar.max_value = 1 + v_page
var value := inverse_lerp(_max_offset.y, _min_offset.y, offset.y)
v_scroll_bar.value = value
v_scroll_bar.show()
else:
v_scroll_bar.hide()
_updating_scroll_bars = false
# Setters and Getters
func set_offset(new_offset : Vector2) -> void:
new_offset.x = clamp(new_offset.x, _min_offset.x, _max_offset.x)
new_offset.y = clamp(new_offset.y, _min_offset.y, _max_offset.y)
if new_offset == offset:
return
offset = new_offset
_render_rect.position = offset
if not _updating_scroll_bars:
_update_scrollbars()
update()
func set_selected_frames(selection : Array) -> void:
selected_frames = selection
update()
func set_texture(new_texture) -> void:
texture = new_texture
if texture == null:
return
_texture_size = texture.get_size()
var full_rect_size := _full_rect.size
if zoom_to_fit:
var ratio : Vector2
ratio.x = floor(full_rect_size.x / _texture_size.x)
ratio.y = floor(full_rect_size.y / _texture_size.y)
self.zoom = min(ratio.x, ratio.y)
else:
self.zoom = 1
_update_offset_limits()
self.offset = (_max_offset - _min_offset) / 2
func set_zoom(new_zoom : int) -> void:
zoom = clamp(new_zoom, 1, 8)
var new_render_rect_size := _texture_size * zoom
var relative_pivot := _zoom_pivot - offset
var pivot_weight : Vector2
if _render_rect.size.x and _render_rect.size.y:
pivot_weight.x = relative_pivot.x / _render_rect.size.x
pivot_weight.y = relative_pivot.y / _render_rect.size.y
var render_rect_size_diff := new_render_rect_size - _render_rect.size
var offset_diff := render_rect_size_diff * pivot_weight
_render_rect.size = new_render_rect_size
_update_offset_limits()
_update_scrollbars()
self.offset = offset - offset_diff
emit_signal("zoom_changed", zoom)
# Signal Callbacks
func _on_resized() -> void:
_full_rect.size = rect_size
_zoom_pivot = _full_rect.size / 2
_update_offset_limits()
_update_scrollbars()
self.offset = offset
var rect := Rect2()
rect.position.x = 0
rect.position.y = (rect_size.y - h_scroll_bar.rect_size.y)
rect.size.x = (rect_size.x - v_scroll_bar.rect_size.x)
rect.size.y = h_scroll_bar.rect_size.y
fit_child_in_rect(h_scroll_bar, rect)
rect.position.x = (rect_size.x - v_scroll_bar.rect_size.x)
rect.position.y = 0
rect.size.x = v_scroll_bar.rect_size.x
rect.size.y = (rect_size.y - h_scroll_bar.rect_size.y)
fit_child_in_rect(v_scroll_bar, rect)
func _on_HScrollBar_value_changed(value : float) -> void:
if _updating_scroll_bars:
return
_updating_scroll_bars = true
self.offset.x = lerp(_max_offset.x, _min_offset.x, value)
_updating_scroll_bars = false
func _on_VScrollBar_value_changed(value : float) -> void:
if _updating_scroll_bars:
return
_updating_scroll_bars = true
self.offset.y = lerp(_max_offset.y, _min_offset.y, value)
_updating_scroll_bars = false

View file

@ -1,48 +0,0 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://addons/aseprite_importer/interface/spritesheet_inspector/SpritesheetView.gd" type="Script" id=2]
[sub_resource type="StyleBoxFlat" id=1]
content_margin_left = 4.0
content_margin_right = 4.0
content_margin_top = 4.0
content_margin_bottom = 4.0
bg_color = Color( 0.135, 0.165, 0.1875, 1 )
border_width_left = 1
border_width_top = 1
border_width_right = 1
border_width_bottom = 1
border_color = Color( 0.09, 0.11, 0.125, 1 )
[sub_resource type="Theme" id=2]
PanelContainer/styles/panel = SubResource( 1 )
[node name="SpritesheetView" type="Container"]
anchor_right = 1.0
anchor_bottom = 1.0
rect_clip_content = true
theme = SubResource( 2 )
script = ExtResource( 2 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="VScrollBar" type="VScrollBar" parent="."]
visible = false
margin_left = 1012.0
margin_right = 1024.0
margin_bottom = 588.0
grow_horizontal = 0
size_flags_horizontal = 8
max_value = 1.0
value = 0.5
[node name="HScrollBar" type="HScrollBar" parent="."]
visible = false
margin_top = 588.0
margin_right = 1012.0
margin_bottom = 600.0
grow_vertical = 0
size_flags_vertical = 8
max_value = 1.0
value = 0.5

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 B

View file

@ -1,7 +0,0 @@
[plugin]
name="Aseprite Importer"
description="Use the JSON data generated by Aseprite to import animations"
author="hectorid"
version="1.0.1"
script="plugin.gd"

View file

@ -1,101 +0,0 @@
tool
extends EditorPlugin
const INTERFACE_SCN = preload("interface/Main.tscn")
const DARK_ICON = preload("interface/icons/dark_icon.png")
const LIGHT_ICON = preload("interface/icons/light_icon.png")
var interface : Control
var editor_interface := get_editor_interface()
var editor_base_control := editor_interface.get_base_control()
var editor_settings := editor_interface.get_editor_settings()
var editor_viewport := editor_interface.get_editor_viewport()
var _state_set := false
func _enter_tree() -> void:
interface = INTERFACE_SCN.instance()
interface.connect("ready", self, "_on_interface_ready", [], CONNECT_ONESHOT)
editor_viewport.add_child(interface)
make_visible(false)
connect("scene_changed", self, "_on_scene_changed")
editor_settings.connect("settings_changed", self, "_on_settings_changed")
interface.connect("animations_generated", self, "_on_animations_generated")
func _exit_tree() -> void:
if interface:
interface.queue_free()
func has_main_screen():
return true
func make_visible(visible: bool) -> void:
if interface:
if visible:
interface.show()
else:
interface.hide()
func get_plugin_name():
return "Aseprite Importer"
func get_plugin_icon():
var editor_theme := editor_base_control.theme
if editor_theme.get_constant("dark_theme", "Editor"):
return LIGHT_ICON;
return DARK_ICON;
func get_state() -> Dictionary:
return interface.get_state()
func set_state(state: Dictionary) -> void:
interface.set_state(state)
_state_set = true
func _update_theme() -> void:
var editor_theme := EditorTheme.new(editor_base_control.theme)
interface.propagate_call("_update_theme", [editor_theme])
# Signal Callbacks
func _on_animations_generated(animation_player : AnimationPlayer) -> void:
var editor_selection := get_editor_interface().get_selection()
editor_selection.clear()
# Reselect the AnimationPlayer node to show the new animations
editor_selection.add_node(animation_player)
func _on_interface_ready() -> void:
_update_theme()
func _on_scene_changed(scene_root : Node) -> void:
if _state_set == false:
interface.set_state({})
_state_set = false
func _on_settings_changed() -> void:
yield(editor_base_control, "draw")
_update_theme()

Binary file not shown.

View file

@ -1,652 +0,0 @@
extends Node
const CommonErrors = preload("res://addons/silent_wolf/common/CommonErrors.gd")
const SWLocalFileStorage = preload("res://addons/silent_wolf/utils/SWLocalFileStorage.gd")
const SWLogger = preload("res://addons/silent_wolf/utils/SWLogger.gd")
const UUID = preload("res://addons/silent_wolf/utils/UUID.gd")
signal sw_login_succeeded
signal sw_login_failed
signal sw_logout_succeeded
signal sw_registration_succeeded
signal sw_registration_user_pwd_succeeded
signal sw_registration_failed
signal sw_email_verif_succeeded
signal sw_email_verif_failed
signal sw_resend_conf_code_succeeded
signal sw_resend_conf_code_failed
signal sw_session_check_complete
signal sw_request_password_reset_succeeded
signal sw_request_password_reset_failed
signal sw_reset_password_succeeded
signal sw_reset_password_failed
signal sw_get_player_details_succeeded
signal sw_get_player_details_failed
var tmp_username = null
var logged_in_player = null
var logged_in_player_email = null
var logged_in_anon = false
var token = null
var id_token = null
var RegisterPlayer = null
var VerifyEmail = null
var ResendConfCode = null
var LoginPlayer = null
var ValidateSession = null
var RequestPasswordReset = null
var ResetPassword = null
var GetPlayerDetails = null
# wekrefs
var wrRegisterPlayer = null
var wrVerifyEmail = null
var wrResendConfCode = null
var wrLoginPlayer = null
var wrValidateSession = null
var wrRequestPasswordReset = null
var wrResetPassword = null
var wrGetPlayerDetails = null
var login_timeout = 0
var login_timer = null
var complete_session_check_wait_timer
func _ready():
pass
func set_player_logged_in(player_name):
logged_in_player = player_name
SWLogger.info("SilentWolf - player logged in as " + str(player_name))
if SilentWolf.auth_config.has("session_duration_seconds") and typeof(SilentWolf.auth_config.session_duration_seconds) == 2:
login_timeout = SilentWolf.auth_config.session_duration_seconds
else:
login_timeout = 0
SWLogger.info("SilentWolf login timeout: " + str(login_timeout))
if login_timeout != 0:
setup_login_timer()
func get_anon_user_id() -> String:
var anon_user_id = OS.get_unique_id()
if anon_user_id == '':
anon_user_id = UUID.generate_uuid_v4()
print("anon_user_id: " + str(anon_user_id))
return anon_user_id
func logout_player():
logged_in_player = null
# remove any player data if present
SilentWolf.Players.clear_player_data()
# remove stored session if any
remove_stored_session()
emit_signal("sw_logout_succeeded")
func register_player_anon(player_name=null) -> Node:
var user_local_id: String = get_anon_user_id()
RegisterPlayer = HTTPRequest.new()
wrRegisterPlayer = weakref(RegisterPlayer)
if OS.get_name() != "HTML5":
RegisterPlayer.set_use_threads(true)
get_tree().get_root().add_child(RegisterPlayer)
RegisterPlayer.connect("request_completed", self, "_on_RegisterPlayer_request_completed")
SWLogger.info("Calling SilentWolf to register an anonymous player")
var game_id = SilentWolf.config.game_id
var game_version = SilentWolf.config.game_version
var api_key = SilentWolf.config.api_key
var payload = { "game_id": game_id, "anon": true, "player_name": player_name, "user_local_id": user_local_id }
var query = JSON.print(payload)
var headers = [
"Content-Type: application/json",
"x-api-key: " + api_key,
"x-sw-plugin-version: " + SilentWolf.version,
"x-sw-game-id: " + SilentWolf.config.game_id,
"x-sw-godot-version: " + SilentWolf.godot_version
]
#print("register_player headers: " + str(headers))
RegisterPlayer.request("https://api.silentwolf.com/create_new_player", headers, true, HTTPClient.METHOD_POST, query)
return self
func register_player(player_name, email, password, confirm_password):
tmp_username = player_name
RegisterPlayer = HTTPRequest.new()
wrRegisterPlayer = weakref(RegisterPlayer)
if OS.get_name() != "HTML5":
RegisterPlayer.set_use_threads(true)
get_tree().get_root().add_child(RegisterPlayer)
RegisterPlayer.connect("request_completed", self, "_on_RegisterPlayer_request_completed")
SWLogger.info("Calling SilentWolf to register a player")
var game_id = SilentWolf.config.game_id
var game_version = SilentWolf.config.game_version
var api_key = SilentWolf.config.api_key
var payload = { "game_id": game_id, "anon": false, "player_name": player_name, "email": email, "password": password, "confirm_password": confirm_password }
var query = JSON.print(payload)
var headers = [
"Content-Type: application/json",
"x-api-key: " + api_key,
"x-sw-plugin-version: " + SilentWolf.version,
"x-sw-game-id: " + SilentWolf.config.game_id,
"x-sw-godot-version: " + SilentWolf.godot_version
]
#print("register_player headers: " + str(headers))
RegisterPlayer.request("https://api.silentwolf.com/create_new_player", headers, true, HTTPClient.METHOD_POST, query)
return self
func register_player_user_password(player_name, password, confirm_password):
tmp_username = player_name
RegisterPlayer = HTTPRequest.new()
wrRegisterPlayer = weakref(RegisterPlayer)
if OS.get_name() != "HTML5":
RegisterPlayer.set_use_threads(true)
get_tree().get_root().add_child(RegisterPlayer)
RegisterPlayer.connect("request_completed", self, "_on_RegisterPlayerUserPassword_request_completed")
SWLogger.info("Calling SilentWolf to register a player")
var game_id = SilentWolf.config.game_id
var game_version = SilentWolf.config.game_version
var api_key = SilentWolf.config.api_key
var payload = { "game_id": game_id, "player_name": player_name, "password": password, "confirm_password": confirm_password }
var query = JSON.print(payload)
var headers = [
"Content-Type: application/json",
"x-api-key: " + api_key,
"x-sw-plugin-version: " + SilentWolf.version,
"x-sw-game-id: " + SilentWolf.config.game_id,
"x-sw-godot-version: " + SilentWolf.godot_version
]
#print("register_player headers: " + str(headers))
RegisterPlayer.request("https://api.silentwolf.com/create_new_player", headers, true, HTTPClient.METHOD_POST, query)
return self
func verify_email(player_name, code):
tmp_username = player_name
VerifyEmail = HTTPRequest.new()
wrVerifyEmail = weakref(VerifyEmail)
if OS.get_name() != "HTML5":
VerifyEmail.set_use_threads(true)
get_tree().get_root().add_child(VerifyEmail)
VerifyEmail.connect("request_completed", self, "_on_VerifyEmail_request_completed")
SWLogger.info("Calling SilentWolf to verify email address for: " + str(player_name))
var game_id = SilentWolf.config.game_id
var game_version = SilentWolf.config.game_version
var api_key = SilentWolf.config.api_key
var payload = { "game_id": game_id, "username": player_name, "code": code }
var query = JSON.print(payload)
var headers = [
"Content-Type: application/json",
"x-api-key: " + api_key,
"x-sw-plugin-version: " + SilentWolf.version,
"x-sw-game-id: " + SilentWolf.config.game_id,
"x-sw-godot-version: " + SilentWolf.godot_version
]
#print("register_player headers: " + str(headers))
VerifyEmail.request("https://api.silentwolf.com/confirm_verif_code", headers, true, HTTPClient.METHOD_POST, query)
return self
func resend_conf_code(player_name):
ResendConfCode = HTTPRequest.new()
wrResendConfCode = weakref(ResendConfCode)
if OS.get_name() != "HTML5":
ResendConfCode.set_use_threads(true)
get_tree().get_root().add_child(ResendConfCode)
ResendConfCode.connect("request_completed", self, "_on_ResendConfCode_request_completed")
SWLogger.info("Calling SilentWolf to resend confirmation code for: " + str(player_name))
var game_id = SilentWolf.config.game_id
var game_version = SilentWolf.config.game_version
var api_key = SilentWolf.config.api_key
var payload = { "game_id": game_id, "username": player_name }
var query = JSON.print(payload)
var headers = [
"Content-Type: application/json",
"x-api-key: " + api_key,
"x-sw-plugin-version: " + SilentWolf.version,
"x-sw-game-id: " + SilentWolf.config.game_id,
"x-sw-godot-version: " + SilentWolf.godot_version
]
#print("register_player headers: " + str(headers))
ResendConfCode.request("https://api.silentwolf.com/resend_conf_code", headers, true, HTTPClient.METHOD_POST, query)
return self
func login_player(username, password, remember_me=false):
tmp_username = username
LoginPlayer = HTTPRequest.new()
wrLoginPlayer = weakref(LoginPlayer)
print("OS name: " + str(OS.get_name()))
if OS.get_name() != "HTML5":
LoginPlayer.set_use_threads(true)
print("get_tree().get_root(): " + str(get_tree().get_root()))
get_tree().get_root().add_child(LoginPlayer)
LoginPlayer.connect("request_completed", self, "_on_LoginPlayer_request_completed")
SWLogger.info("Calling SilentWolf to log in a player")
var game_id = SilentWolf.config.game_id
var api_key = SilentWolf.config.api_key
var payload = { "game_id": game_id, "username": username, "password": password, "remember_me": str(remember_me) }
if SilentWolf.auth_config.has("saved_session_expiration_days") and typeof(SilentWolf.auth_config.saved_session_expiration_days) == 2:
payload["remember_me_expires_in"] = str(SilentWolf.auth_config.saved_session_expiration_days)
SWLogger.debug("SilentWolf login player payload: " + str(payload))
var query = JSON.print(payload)
var headers = [
"Content-Type: application/json",
"x-api-key: " + api_key,
"x-sw-plugin-version: " + SilentWolf.version,
"x-sw-game-id: " + SilentWolf.config.game_id,
"x-sw-godot-version: " + SilentWolf.godot_version
]#print("login_player headers: " + str(headers))
LoginPlayer.request("https://api.silentwolf.com/login_player", headers, true, HTTPClient.METHOD_POST, query)
return self
func request_player_password_reset(player_name):
RequestPasswordReset = HTTPRequest.new()
wrRequestPasswordReset = weakref(RequestPasswordReset)
print("OS name: " + str(OS.get_name()))
if OS.get_name() != "HTML5":
RequestPasswordReset.set_use_threads(true)
get_tree().get_root().add_child(RequestPasswordReset)
RequestPasswordReset.connect("request_completed", self, "_on_RequestPasswordReset_request_completed")
SWLogger.info("Calling SilentWolf to request a password reset for: " + str(player_name))
var game_id = SilentWolf.config.game_id
var api_key = SilentWolf.config.api_key
var payload = { "game_id": game_id, "player_name": player_name }
SWLogger.debug("SilentWolf request player password reset payload: " + str(payload))
var query = JSON.print(payload)
var headers = [
"Content-Type: application/json",
"x-api-key: " + api_key,
"x-sw-plugin-version: " + SilentWolf.version,
"x-sw-game-id: " + SilentWolf.config.game_id,
"x-sw-godot-version: " + SilentWolf.godot_version
]
RequestPasswordReset.request("https://api.silentwolf.com/request_player_password_reset", headers, true, HTTPClient.METHOD_POST, query)
return self
func reset_player_password(player_name, conf_code, new_password, confirm_password):
ResetPassword = HTTPRequest.new()
wrResetPassword = weakref(ResetPassword)
if OS.get_name() != "HTML5":
ResetPassword.set_use_threads(true)
get_tree().get_root().add_child(ResetPassword)
ResetPassword.connect("request_completed", self, "_on_ResetPassword_request_completed")
SWLogger.info("Calling SilentWolf to reset password for: " + str(player_name))
var game_id = SilentWolf.config.game_id
var api_key = SilentWolf.config.api_key
var payload = { "game_id": game_id, "player_name": player_name, "conf_code": conf_code, "password": new_password, "confirm_password": confirm_password }
SWLogger.debug("SilentWolf request player password reset payload: " + str(payload))
var query = JSON.print(payload)
var headers = [
"Content-Type: application/json",
"x-api-key: " + api_key,
"x-sw-plugin-version: " + SilentWolf.version,
"x-sw-game-id: " + SilentWolf.config.game_id,
"x-sw-godot-version: " + SilentWolf.godot_version
]
ResetPassword.request("https://api.silentwolf.com/reset_player_password", headers, true, HTTPClient.METHOD_POST, query)
return self
func get_player_details(player_name):
GetPlayerDetails = HTTPRequest.new()
wrRegisterPlayer = weakref(GetPlayerDetails)
if OS.get_name() != "HTML5":
GetPlayerDetails.set_use_threads(true)
get_tree().get_root().add_child(GetPlayerDetails)
GetPlayerDetails.connect("request_completed", self, "_on_GetPlayerDetails_request_completed")
SWLogger.info("Calling SilentWolf to get player details")
var game_id = SilentWolf.config.game_id
var game_version = SilentWolf.config.game_version
var api_key = SilentWolf.config.api_key
var payload = { "game_id": game_id, "player_name": player_name }
var query = JSON.print(payload)
var headers = [
"Content-Type: application/json",
"x-api-key: " + api_key,
"x-sw-plugin-version: " + SilentWolf.version,
"x-sw-game-id: " + SilentWolf.config.game_id,
"x-sw-godot-version: " + SilentWolf.godot_version
]
#print("register_player headers: " + str(headers))
GetPlayerDetails.request("https://api.silentwolf.com/get_player_details", headers, true, HTTPClient.METHOD_POST, query)
return self
func _on_LoginPlayer_request_completed( result, response_code, headers, body ):
SWLogger.info("LoginPlayer request completed")
var status_check = CommonErrors.check_status_code(response_code)
#LoginPlayer.queue_free()
SilentWolf.free_request(wrLoginPlayer, LoginPlayer)
SWLogger.debug("response headers: " + str(response_code))
SWLogger.debug("response headers: " + str(headers))
#SWLogger.debug("response body: " + str(body.get_string_from_utf8()))
if status_check:
var json = JSON.parse(body.get_string_from_utf8())
var response = json.result
if "message" in response.keys() and response.message == "Forbidden":
SWLogger.error("You are not authorized to call the SilentWolf API - check your API key configuration: https://silentwolf.com/leaderboard")
else:
if "lookup" in response.keys():
print("remember me lookup: " + str(response.lookup))
save_session(response.lookup, response.validator)
if "validator" in response.keys():
print("remember me validator: " + str(response.validator))
SWLogger.info("SilentWolf login player success? : " + str(response.success))
# TODO: get JWT token and store it
# send a different signal depending on login success or failure
if response.success:
token = response.swtoken
#id_token = response.swidtoken
SWLogger.debug("token: " + token)
set_player_logged_in(tmp_username)
emit_signal("sw_login_succeeded")
else:
emit_signal("sw_login_failed", response.error)
func _on_RegisterPlayer_request_completed( result, response_code, headers, body ):
SWLogger.info("RegisterPlayer request completed")
var status_check = CommonErrors.check_status_code(response_code)
#RegisterPlayer.queue_free()
SilentWolf.free_request(wrRegisterPlayer, RegisterPlayer)
SWLogger.debug("response headers: " + str(response_code))
SWLogger.debug("response headers: " + str(headers))
SWLogger.debug("response body: " + str(body.get_string_from_utf8()))
if status_check:
var json = JSON.parse(body.get_string_from_utf8())
var response = json.result
SWLogger.debug("reponse: " + str(response))
if "message" in response.keys() and response.message == "Forbidden":
SWLogger.error("You are not authorized to call the SilentWolf API - check your API key configuration: https://silentwolf.com/leaderboard")
else:
SWLogger.info("SilentWolf create new player success? : " + str(response.success))
# also get a JWT token here
# send a different signal depending on registration success or failure
if response.success:
var anon = response.anon
if anon:
SWLogger.info("Anonymous Player registration succeeded")
logged_in_anon = true
if 'player_name' in response:
logged_in_player = response.player_name
elif 'player_local_id' in response:
logged_in_player = str("anon##" + response.player_local_id)
else:
logged_in_player = "anon##unknown"
print("Anon registration, logged in player: " + str(logged_in_player))
else:
# if email confirmation is enabled for the game, we can't log in the player just yet
var email_conf_enabled = response.email_conf_enabled
if email_conf_enabled:
SWLogger.info("Player registration succeeded, but player still needs to verify email address")
else:
SWLogger.info("Player registration succeeded, email verification is disabled")
logged_in_player = tmp_username
emit_signal("sw_registration_succeeded")
else:
emit_signal("sw_registration_failed", response.error)
func _on_RegisterPlayerUserPassword_request_completed( result, response_code, headers, body ):
SWLogger.info("RegisterPlayerUserPassword request completed")
var status_check = CommonErrors.check_status_code(response_code)
#RegisterPlayer.queue_free()
SilentWolf.free_request(wrRegisterPlayer, RegisterPlayer)
SWLogger.debug("response headers: " + str(response_code))
SWLogger.debug("response headers: " + str(headers))
SWLogger.debug("response body: " + str(body.get_string_from_utf8()))
if status_check:
var json = JSON.parse(body.get_string_from_utf8())
var response = json.result
SWLogger.debug("reponse: " + str(response))
if "message" in response.keys() and response.message == "Forbidden":
SWLogger.error("You are not authorized to call the SilentWolf API - check your API key configuration: https://silentwolf.com/leaderboard")
else:
SWLogger.info("SilentWolf create new player success? : " + str(response.success))
# also get a JWT token here
# send a different signal depending on registration success or failure
if response.success:
# if email confirmation is enabled for the game, we can't log in the player just yet
var email_conf_enabled = response.email_conf_enabled
SWLogger.info("Player registration with username/password succeeded, player account autoconfirmed")
logged_in_player = tmp_username
emit_signal("sw_registration_user_pwd_succeeded")
else:
emit_signal("sw_registration_failed", response.error)
func _on_VerifyEmail_request_completed( result, response_code, headers, body ):
SWLogger.info("VerifyEmail request completed")
var status_check = CommonErrors.check_status_code(response_code)
SilentWolf.free_request(wrVerifyEmail, VerifyEmail)
SWLogger.debug("response headers: " + str(response_code))
SWLogger.debug("response headers: " + str(headers))
SWLogger.debug("response body: " + str(body.get_string_from_utf8()))
if status_check:
var json = JSON.parse(body.get_string_from_utf8())
var response = json.result
SWLogger.debug("reponse: " + str(response))
if "message" in response.keys() and response.message == "Forbidden":
SWLogger.error("You are not authorized to call the SilentWolf API - check your API key configuration: https://silentwolf.com/playerauth")
else:
SWLogger.info("SilentWolf verify email success? : " + str(response.success))
# also get a JWT token here
# send a different signal depending on registration success or failure
if response.success:
logged_in_player = tmp_username
emit_signal("sw_email_verif_succeeded")
else:
emit_signal("sw_email_verif_failed", response.error)
func _on_ResendConfCode_request_completed( result, response_code, headers, body ):
SWLogger.info("ResendConfCode request completed")
var status_check = CommonErrors.check_status_code(response_code)
SilentWolf.free_request(wrResendConfCode, ResendConfCode)
SWLogger.debug("response headers: " + str(response_code))
SWLogger.debug("response headers: " + str(headers))
SWLogger.debug("response body: " + str(body.get_string_from_utf8()))
if status_check:
var json = JSON.parse(body.get_string_from_utf8())
var response = json.result
SWLogger.debug("reponse: " + str(response))
if "message" in response.keys() and response.message == "Forbidden":
SWLogger.error("You are not authorized to call the SilentWolf API - check your API key configuration: https://silentwolf.com/playerauth")
else:
SWLogger.info("SilentWolf resend conf code success? : " + str(response.success))
# also get a JWT token here
# send a different signal depending on registration success or failure
if response.success:
emit_signal("sw_resend_conf_code_succeeded")
else:
emit_signal("sw_resend_conf_code_failed", response.error)
func _on_RequestPasswordReset_request_completed( result, response_code, headers, body ):
SWLogger.info("RequestPasswordReset request completed")
var status_check = CommonErrors.check_status_code(response_code)
SilentWolf.free_request(wrRequestPasswordReset, RequestPasswordReset)
SWLogger.debug("response headers: " + str(response_code))
SWLogger.debug("response headers: " + str(headers))
SWLogger.debug("response body: " + str(body.get_string_from_utf8()))
if status_check:
var json = JSON.parse(body.get_string_from_utf8())
var response = json.result
SWLogger.debug("reponse: " + str(response))
if "message" in response.keys() and response.message == "Forbidden":
SWLogger.error("You are not authorized to call the SilentWolf API - check your API key configuration: https://silentwolf.com/playerauth")
else:
SWLogger.info("SilentWolf request player password reset success? : " + str(response.success))
if response.success:
emit_signal("sw_request_password_reset_succeeded")
else:
emit_signal("sw_request_password_reset_failed", response.error)
func _on_ResetPassword_request_completed( result, response_code, headers, body ):
SWLogger.info("ResetPassword request completed")
var status_check = CommonErrors.check_status_code(response_code)
SilentWolf.free_request(wrResetPassword, ResetPassword)
SWLogger.debug("response headers: " + str(response_code))
SWLogger.debug("response headers: " + str(headers))
SWLogger.debug("response body: " + str(body.get_string_from_utf8()))
if status_check:
var json = JSON.parse(body.get_string_from_utf8())
var response = json.result
SWLogger.debug("reponse: " + str(response))
if "message" in response.keys() and response.message == "Forbidden":
SWLogger.error("You are not authorized to call the SilentWolf API - check your API key configuration: https://silentwolf.com/playerauth")
else:
SWLogger.info("SilentWolf reset player password success? : " + str(response.success))
if response.success:
emit_signal("sw_reset_password_succeeded")
else:
emit_signal("sw_reset_password_failed", response.error)
func setup_login_timer():
login_timer = Timer.new()
login_timer.set_one_shot(true)
login_timer.set_wait_time(login_timeout)
login_timer.connect("timeout", self, "on_login_timeout_complete")
add_child(login_timer)
func on_login_timeout_complete():
logout_player()
# store lookup (not logged in player name) and validator in local file
func save_session(lookup, validator):
var path = "user://swsession.save"
var session_data = {
"lookup": lookup,
"validator": validator
}
SWLocalFileStorage.save_data("user://swsession.save", session_data, "Saving SilentWolf session: ")
func remove_stored_session():
var path = "user://swsession.save"
SWLocalFileStorage.remove_data(path, "Removing SilentWolf session if any: " )
# reload lookup and validator and send them back to the server to auto-login user
func load_session() -> Dictionary:
var sw_session_data = null
var path = "user://swsession.save"
sw_session_data = SWLocalFileStorage.get_data(path)
if sw_session_data == null:
SWLogger.debug("No local SilentWolf session stored, or session data stored in incorrect format")
SWLogger.info("Found session data: " + str(sw_session_data))
return sw_session_data
func auto_login_player():
var sw_session_data = load_session()
if sw_session_data:
SWLogger.debug("Found saved SilentWolf session data, attempting autologin...")
var lookup = sw_session_data.lookup
var validator = sw_session_data.validator
# whether successful or not, in the end the "sw_session_check_complete" signal will be emitted
validate_player_session(lookup, validator)
else:
SWLogger.debug("No saved SilentWolf session data, so no autologin will be performed")
# the following is needed to delay the emission of the signal just a little bit, otherwise the signal is never received!
setup_complete_session_check_wait_timer()
complete_session_check_wait_timer.start()
return self
# Signal can't be emitted directly from auto_login_player() function
# otherwise it won't connect back to calling script
func complete_session_check(return_value=null):
SWLogger.debug("emitting signal....")
emit_signal("sw_session_check_complete", return_value)
func validate_player_session(lookup, validator, scene=get_tree().get_current_scene()):
ValidateSession = HTTPRequest.new()
wrValidateSession = weakref(ValidateSession)
if OS.get_name() != "HTML5":
ValidateSession.set_use_threads(true)
scene.add_child(ValidateSession)
ValidateSession.connect("request_completed", self, "_on_ValidateSession_request_completed")
SWLogger.info("Calling SilentWolf to validate an existing player session")
var game_id = SilentWolf.config.game_id
var api_key = SilentWolf.config.api_key
var payload = { "game_id": game_id, "lookup": lookup, "validator": validator }
SWLogger.debug("Validate session payload: " + str(payload))
var query = JSON.print(payload)
var headers = ["Content-Type: application/json", "x-api-key: " + api_key, "x-sw-plugin-version: " + SilentWolf.version]
ValidateSession.request("https://api.silentwolf.com/validate_remember_me", headers, true, HTTPClient.METHOD_POST, query)
return self
func _on_ValidateSession_request_completed( result, response_code, headers, body ):
SWLogger.info("SilentWolf - ValidateSession request completed")
var status_check = CommonErrors.check_status_code(response_code)
#ValidateSession.queue_free()
SilentWolf.free_request(wrValidateSession, ValidateSession)
SWLogger.debug("response headers: " + str(response_code))
SWLogger.debug("response headers: " + str(headers))
SWLogger.debug("response body: " + str(body.get_string_from_utf8()))
if status_check:
var json = JSON.parse(body.get_string_from_utf8())
var response = json.result
SWLogger.debug("reponse: " + str(response))
if "message" in response.keys() and response.message == "Forbidden":
SWLogger.error("You are not authorized to call the SilentWolf API - check your API key configuration: https://silentwolf.com/leaderboard")
else:
SWLogger.info("SilentWolf validate session success? : " + str(response.success))
if response.success:
set_player_logged_in(response.player_name)
complete_session_check(logged_in_player)
else:
complete_session_check(response.error)
func _on_GetPlayerDetails_request_completed( result, response_code, headers, body ):
SWLogger.info("SilentWolf - GetPlayerDetails request completed")
var status_check = CommonErrors.check_status_code(response_code)
#ValidateSession.queue_free()
SilentWolf.free_request(wrGetPlayerDetails, GetPlayerDetails)
SWLogger.debug("response headers: " + str(response_code))
SWLogger.debug("response headers: " + str(headers))
SWLogger.debug("response body: " + str(body.get_string_from_utf8()))
if status_check:
var json = JSON.parse(body.get_string_from_utf8())
var response = json.result
SWLogger.debug("reponse: " + str(response))
if "message" in response.keys() and response.message == "Forbidden":
SWLogger.error("You are not authorized to call the SilentWolf API - check your API key configuration: https://silentwolf.com/playerauth")
else:
SWLogger.info("SilentWolf get player details success? : " + str(response.success))
if response.success:
emit_signal("sw_get_player_details_succeeded", response.player_details)
else:
emit_signal("sw_get_player_details_failed")
func setup_complete_session_check_wait_timer():
complete_session_check_wait_timer = Timer.new()
complete_session_check_wait_timer.set_one_shot(true)
complete_session_check_wait_timer.set_wait_time(0.01)
complete_session_check_wait_timer.connect("timeout", self, "complete_session_check")
add_child(complete_session_check_wait_timer)

View file

@ -1,60 +0,0 @@
extends TextureRect
const SWLogger = preload("res://addons/silent_wolf/utils/SWLogger.gd")
func _ready():
SilentWolf.Auth.connect("sw_email_verif_succeeded", self, "_on_confirmation_succeeded")
SilentWolf.Auth.connect("sw_email_verif_failed", self, "_on_confirmation_failed")
SilentWolf.Auth.connect("sw_resend_conf_code_succeeded", self, "_on_resend_code_succeeded")
SilentWolf.Auth.connect("sw_resend_conf_code_failed", self, "_on_resend_code_failed")
func _on_confirmation_succeeded():
SWLogger.info("email verification succeeded: " + str(SilentWolf.Auth.logged_in_player))
# redirect to configured scene (user is logged in after registration)
var scene_name = SilentWolf.auth_config.redirect_to_scene
get_tree().change_scene(scene_name)
func _on_confirmation_failed(error):
hide_processing_label()
SWLogger.info("email verification failed: " + str(error))
$"FormContainer/ErrorMessage".text = error
$"FormContainer/ErrorMessage".show()
func _on_resend_code_succeeded():
SWLogger.info("Code resend succeeded for player: " + str(SilentWolf.Auth.tmp_username))
$"FormContainer/ErrorMessage".text = "Confirmation code was resent to your email address. Please check your inbox (and your spam)."
$"FormContainer/ErrorMessage".show()
func _on_resend_code_failed():
SWLogger.info("Code resend failed for player: " + str(SilentWolf.Auth.tmp_username))
$"FormContainer/ErrorMessage".text = "Confirmation code could not be resent"
$"FormContainer/ErrorMessage".show()
func show_processing_label():
$"FormContainer/ProcessingLabel".show()
func hide_processing_label():
$"FormContainer/ProcessingLabel".hide()
func _on_ConfirmButton_pressed():
var username = SilentWolf.Auth.tmp_username
var code = $"FormContainer/CodeContainer/VerifCode".text
SWLogger.debug("Email verification form submitted, code: " + str(code))
SilentWolf.Auth.verify_email(username, code)
show_processing_label()
func _on_ResendConfCodeButton_pressed():
var username = SilentWolf.Auth.tmp_username
SWLogger.debug("Requesting confirmation code resend")
SilentWolf.Auth.resend_conf_code(username)
show_processing_label()

View file

@ -1,143 +0,0 @@
[gd_scene load_steps=13 format=2]
[ext_resource path="res://addons/silent_wolf/Auth/ConfirmEmail.gd" type="Script" id=1]
[ext_resource path="res://addons/silent_wolf/common/SWButton.tscn" type="PackedScene" id=2]
[ext_resource path="res://addons/silent_wolf/assets/fonts/Comfortaa-Bold.ttf" type="DynamicFontData" id=3]
[sub_resource type="DynamicFontData" id=13]
font_path = "res://addons/silent_wolf/assets/fonts/Comfortaa-Bold.ttf"
[sub_resource type="DynamicFont" id=1]
size = 64
font_data = SubResource( 13 )
[sub_resource type="DynamicFont" id=2]
size = 48
font_data = SubResource( 13 )
[sub_resource type="DynamicFont" id=3]
size = 32
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=4]
size = 32
font_data = SubResource( 13 )
[sub_resource type="StyleBoxFlat" id=5]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.831373, 0.415686, 0.415686, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="StyleBoxFlat" id=6]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.831373, 0.415686, 0.415686, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="StyleBoxFlat" id=7]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.482353, 0.458824, 0.458824, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="DynamicFont" id=8]
size = 64
font_data = ExtResource( 3 )
[node name="ConfirmEmail" type="TextureRect"]
margin_right = 40.0
margin_bottom = 40.0
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="FormContainer" type="VBoxContainer" parent="."]
margin_left = 565.0
margin_top = 197.0
margin_right = 1500.0
margin_bottom = 798.0
custom_constants/separation = 100
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label" type="Label" parent="FormContainer"]
margin_right = 935.0
margin_bottom = 72.0
custom_fonts/font = SubResource( 1 )
text = "Confirm your email address"
align = 1
[node name="CodeContainer" type="HBoxContainer" parent="FormContainer"]
margin_top = 172.0
margin_right = 935.0
margin_bottom = 247.0
custom_constants/separation = 20
[node name="Label" type="Label" parent="FormContainer/CodeContainer"]
margin_top = 10.0
margin_right = 133.0
margin_bottom = 65.0
custom_fonts/font = SubResource( 2 )
text = "Code"
[node name="VerifCode" type="LineEdit" parent="FormContainer/CodeContainer"]
margin_left = 153.0
margin_right = 483.0
margin_bottom = 75.0
rect_min_size = Vector2( 330, 75 )
custom_fonts/font = SubResource( 3 )
max_length = 30
[node name="ErrorMessage" type="Label" parent="FormContainer"]
visible = false
margin_top = 522.0
margin_right = 648.0
margin_bottom = 559.0
custom_fonts/font = SubResource( 4 )
custom_colors/font_color = Color( 0.866667, 0.101961, 0.101961, 1 )
autowrap = true
[node name="ConfirmButton" parent="FormContainer" instance=ExtResource( 2 )]
margin_top = 347.0
margin_right = 935.0
margin_bottom = 465.0
text = "Submit"
[node name="ResendConfCodeButton" parent="FormContainer" instance=ExtResource( 2 )]
margin_top = 565.0
margin_right = 935.0
margin_bottom = 683.0
custom_styles/hover = SubResource( 5 )
custom_styles/pressed = SubResource( 6 )
custom_styles/normal = SubResource( 7 )
custom_fonts/font = SubResource( 8 )
text = "Resend code"
[node name="ProcessingLabel" type="Label" parent="FormContainer"]
visible = false
margin_top = 740.0
margin_right = 648.0
margin_bottom = 812.0
custom_fonts/font = SubResource( 1 )
text = "Processing..."
align = 1
[connection signal="pressed" from="FormContainer/ConfirmButton" to="." method="_on_ConfirmButton_pressed"]
[connection signal="pressed" from="FormContainer/ResendConfCodeButton" to="." method="_on_ResendConfCodeButton_pressed"]

View file

@ -1,41 +0,0 @@
extends TextureRect
const SWLogger = preload("res://addons/silent_wolf/utils/SWLogger.gd")
func _ready():
#var auth_node = get_tree().get_root().get_node("res://addons/silent_wolf/Auth/Auth")
SilentWolf.Auth.connect("sw_login_succeeded", self, "_on_login_succeeded")
SilentWolf.Auth.connect("sw_login_failed", self, "_on_login_failed")
func _on_LoginButton_pressed():
var username = $"FormContainer/UsernameContainer/Username".text
var password = $"FormContainer/PasswordContainer/Password".text
var remember_me = $"FormContainer/RememberMeCheckBox".is_pressed()
SWLogger.debug("Login form submitted, remember_me: " + str(remember_me))
SilentWolf.Auth.login_player(username, password, remember_me)
show_processing_label()
func _on_login_succeeded():
var scene_name = SilentWolf.auth_config.redirect_to_scene
SWLogger.info("logged in as: " + str(SilentWolf.Auth.logged_in_player))
get_tree().change_scene(scene_name)
func _on_login_failed(error):
hide_processing_label()
SWLogger.info("log in failed: " + str(error))
$"FormContainer/ErrorMessage".text = error
$"FormContainer/ErrorMessage".show()
func _on_BackButton_pressed():
get_tree().change_scene(SilentWolf.auth_config.redirect_to_scene)
func show_processing_label():
$"FormContainer/ProcessingLabel".show()
$"FormContainer/ProcessingLabel".show()
func hide_processing_label():
$"FormContainer/ProcessingLabel".hide()
func _on_LinkButton_pressed():
get_tree().change_scene(SilentWolf.auth_config.reset_password_scene)

View file

@ -1,208 +0,0 @@
[gd_scene load_steps=19 format=2]
[ext_resource path="res://addons/silent_wolf/Auth/Login.gd" type="Script" id=1]
[ext_resource path="res://addons/silent_wolf/common/SWButton.tscn" type="PackedScene" id=2]
[ext_resource path="res://addons/silent_wolf/assets/fonts/Comfortaa-Bold.ttf" type="DynamicFontData" id=3]
[ext_resource path="res://addons/silent_wolf/assets/gfx/checkbox_unchecked.png" type="Texture" id=5]
[ext_resource path="res://addons/silent_wolf/assets/gfx/checkbox_checked.png" type="Texture" id=6]
[sub_resource type="StyleBoxFlat" id=1]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.831373, 0.415686, 0.415686, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="StyleBoxFlat" id=2]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.831373, 0.415686, 0.415686, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="StyleBoxFlat" id=3]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.482353, 0.458824, 0.458824, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="DynamicFont" id=4]
size = 64
font_data = ExtResource( 3 )
[sub_resource type="DynamicFontData" id=13]
font_path = "res://addons/silent_wolf/assets/fonts/Comfortaa-Bold.ttf"
[sub_resource type="DynamicFont" id=5]
size = 64
font_data = SubResource( 13 )
[sub_resource type="DynamicFont" id=6]
size = 48
font_data = SubResource( 13 )
[sub_resource type="DynamicFont" id=7]
size = 32
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=8]
size = 32
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=9]
size = 32
outline_color = Color( 0.211765, 0.25098, 0.937255, 1 )
font_data = SubResource( 13 )
[sub_resource type="StyleBoxFlat" id=10]
content_margin_left = 5.0
bg_color = Color( 0.6, 0.6, 0.6, 0 )
[sub_resource type="DynamicFont" id=11]
size = 32
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=12]
size = 32
font_data = SubResource( 13 )
[node name="Login" type="TextureRect"]
margin_right = 40.0
margin_bottom = 40.0
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="BackButton" parent="." instance=ExtResource( 2 )]
margin_left = 339.0
margin_top = 117.0
margin_right = 667.0
margin_bottom = 235.0
custom_styles/hover = SubResource( 1 )
custom_styles/pressed = SubResource( 2 )
custom_styles/normal = SubResource( 3 )
custom_fonts/font = SubResource( 4 )
text = "← Back"
[node name="FormContainer" type="VBoxContainer" parent="."]
margin_left = 679.0
margin_top = 196.75
margin_right = 1327.0
margin_bottom = 933.75
custom_constants/separation = 80
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label" type="Label" parent="FormContainer"]
margin_right = 648.0
margin_bottom = 72.0
custom_fonts/font = SubResource( 5 )
text = "Log in"
align = 1
[node name="UsernameContainer" type="HBoxContainer" parent="FormContainer"]
margin_top = 152.0
margin_right = 648.0
margin_bottom = 227.0
custom_constants/separation = 20
[node name="Label" type="Label" parent="FormContainer/UsernameContainer"]
margin_top = 10.0
margin_right = 269.0
margin_bottom = 65.0
custom_fonts/font = SubResource( 6 )
text = "Username:"
[node name="Username" type="LineEdit" parent="FormContainer/UsernameContainer"]
margin_left = 289.0
margin_right = 619.0
margin_bottom = 75.0
rect_min_size = Vector2( 330, 75 )
custom_fonts/font = SubResource( 7 )
max_length = 30
[node name="PasswordContainer" type="HBoxContainer" parent="FormContainer"]
margin_top = 307.0
margin_right = 648.0
margin_bottom = 382.0
custom_constants/separation = 40
[node name="Label" type="Label" parent="FormContainer/PasswordContainer"]
margin_top = 10.0
margin_right = 247.0
margin_bottom = 65.0
custom_fonts/font = SubResource( 6 )
text = "Password:"
[node name="Password" type="LineEdit" parent="FormContainer/PasswordContainer"]
margin_left = 287.0
margin_right = 617.0
margin_bottom = 75.0
rect_min_size = Vector2( 330, 75 )
custom_fonts/font = SubResource( 8 )
max_length = 30
secret = true
[node name="LinkButton" type="LinkButton" parent="FormContainer"]
margin_top = 462.0
margin_right = 648.0
margin_bottom = 499.0
custom_fonts/font = SubResource( 9 )
custom_colors/font_color = Color( 0.321569, 0.360784, 0.92549, 1 )
text = "Forgot Password?"
[node name="RememberMeCheckBox" type="CheckBox" parent="FormContainer"]
margin_top = 579.0
margin_right = 648.0
margin_bottom = 629.0
rect_min_size = Vector2( 50, 50 )
focus_mode = 0
custom_icons/checked = ExtResource( 6 )
custom_icons/unchecked = ExtResource( 5 )
custom_styles/normal = SubResource( 10 )
custom_fonts/font = SubResource( 11 )
custom_constants/hseparation = 15
text = "Stay signed in for 30 days"
expand_icon = true
[node name="ErrorMessage" type="Label" parent="FormContainer"]
visible = false
margin_top = 522.0
margin_right = 648.0
margin_bottom = 559.0
custom_fonts/font = SubResource( 12 )
custom_colors/font_color = Color( 0.866667, 0.101961, 0.101961, 1 )
autowrap = true
[node name="LoginButton" parent="FormContainer" instance=ExtResource( 2 )]
margin_top = 709.0
margin_right = 648.0
margin_bottom = 827.0
text = "Submit"
[node name="ProcessingLabel" type="Label" parent="FormContainer"]
visible = false
margin_top = 740.0
margin_right = 648.0
margin_bottom = 812.0
custom_fonts/font = SubResource( 5 )
text = "Processing..."
align = 1
[connection signal="pressed" from="BackButton" to="." method="_on_BackButton_pressed"]
[connection signal="pressed" from="FormContainer/LinkButton" to="." method="_on_LinkButton_pressed"]
[connection signal="pressed" from="FormContainer/LoginButton" to="." method="_on_LoginButton_pressed"]

View file

@ -1,81 +0,0 @@
extends TextureRect
const SWLogger = preload("res://addons/silent_wolf/utils/SWLogger.gd")
func _ready():
SilentWolf.check_auth_ready()
SilentWolf.Auth.connect("sw_registration_succeeded", self, "_on_registration_succeeded")
SilentWolf.Auth.connect("sw_registration_user_pwd_succeeded", self, "_on_registration_succeeded")
SilentWolf.Auth.connect("sw_registration_failed", self, "_on_registration_failed")
func _on_RegisterButton_pressed():
var player_name = $"FormContainer/MainFormContainer/FormInputFields/PlayerName".text
var email = $"FormContainer/MainFormContainer/FormInputFields/Email".text
var password = $"FormContainer/MainFormContainer/FormInputFields/Password".text
var confirm_password = $"FormContainer/MainFormContainer/FormInputFields/ConfirmPassword".text
SilentWolf.Auth.register_player(player_name, email, password, confirm_password)
show_processing_label()
func _on_RegisterUPButton_pressed():
var player_name = $"FormContainer/MainFormContainer/FormInputFields/PlayerName".text
var password = $"FormContainer/MainFormContainer/FormInputFields/Password".text
var confirm_password = $"FormContainer/MainFormContainer/FormInputFields/ConfirmPassword".text
SilentWolf.Auth.register_player_user_password(player_name, password, confirm_password)
show_processing_label()
func _on_registration_succeeded():
#get_tree().change_scene("res://addons/silent_wolf/Auth/Login.tscn")
# redirect to configured scene (user is logged in after registration)
var scene_name = SilentWolf.auth_config.redirect_to_scene
# if doing email verification, open scene to confirm email address
if ("email_confirmation_scene" in SilentWolf.auth_config) and (SilentWolf.auth_config.email_confirmation_scene) != "":
SWLogger.info("registration succeeded, waiting for email verification...")
scene_name = SilentWolf.auth_config.email_confirmation_scene
else:
SWLogger.info("registration succeeded, logged in player: " + str(SilentWolf.Auth.logged_in_player))
get_tree().change_scene(scene_name)
func _on_registration_user_pwd_succeeded():
var scene_name = SilentWolf.auth_config.redirect_to_scene
get_tree().change_scene(scene_name)
func _on_registration_failed(error):
hide_processing_label()
SWLogger.info("registration failed: " + str(error))
$"FormContainer/ErrorMessage".text = error
$"FormContainer/ErrorMessage".show()
func _on_BackButton_pressed():
get_tree().change_scene(SilentWolf.auth_config.redirect_to_scene)
func show_processing_label():
$"FormContainer/ProcessingLabel".show()
func hide_processing_label():
$"FormContainer/ProcessingLabel".hide()
func _on_UsernameToolButton_mouse_entered():
$"FormContainer/InfoBox".text = "Username should contain at least 6 characters (letters or numbers) and no spaces."
$"FormContainer/InfoBox".show()
func _on_UsernameToolButton_mouse_exited():
$"FormContainer/InfoBox".hide()
func _on_PasswordToolButton_mouse_entered():
$"FormContainer/InfoBox".text = "Password should contain at least 8 characters including uppercase and lowercase letters, numbers and (optionally) special characters."
$"FormContainer/InfoBox".show()
func _on_PasswordToolButton_mouse_exited():
$"FormContainer/InfoBox".hide()

View file

@ -1,285 +0,0 @@
[gd_scene load_steps=21 format=2]
[ext_resource path="res://addons/silent_wolf/Auth/Register.gd" type="Script" id=1]
[ext_resource path="res://addons/silent_wolf/common/SWButton.tscn" type="PackedScene" id=2]
[ext_resource path="res://addons/silent_wolf/assets/fonts/Comfortaa-Bold.ttf" type="DynamicFontData" id=3]
[ext_resource path="res://assets/fonts/Comfortaa-Bold.ttf" type="DynamicFontData" id=4]
[ext_resource path="res://addons/silent_wolf/assets/gfx/info_icon_small.png" type="Texture" id=5]
[ext_resource path="res://addons/silent_wolf/assets/gfx/dummy_info_icon_small.png" type="Texture" id=6]
[sub_resource type="StyleBoxFlat" id=1]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.831373, 0.415686, 0.415686, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="StyleBoxFlat" id=2]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.831373, 0.415686, 0.415686, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="StyleBoxFlat" id=3]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.482353, 0.458824, 0.458824, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="DynamicFont" id=4]
size = 64
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=5]
size = 64
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=6]
size = 64
font_data = ExtResource( 4 )
[sub_resource type="DynamicFont" id=7]
size = 32
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=8]
size = 32
font_data = ExtResource( 4 )
[sub_resource type="DynamicFont" id=9]
size = 32
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=10]
size = 32
font_data = ExtResource( 3 )
[sub_resource type="StyleBoxFlat" id=11]
content_margin_left = 30.0
content_margin_right = 30.0
content_margin_top = 30.0
content_margin_bottom = 30.0
bg_color = Color( 1, 1, 1, 1 )
border_width_left = 3
border_width_top = 3
border_width_right = 3
border_width_bottom = 3
border_color = Color( 0.666667, 0.223529, 0.223529, 1 )
corner_radius_top_left = 10
corner_radius_top_right = 10
corner_radius_bottom_right = 10
corner_radius_bottom_left = 10
[sub_resource type="DynamicFont" id=12]
size = 32
outline_color = Color( 0.666667, 0.223529, 0.223529, 1 )
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=13]
size = 32
outline_color = Color( 0.854902, 0.0901961, 0.0901961, 1 )
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=14]
size = 32
font_data = ExtResource( 3 )
[node name="Register" type="TextureRect"]
margin_right = 40.0
margin_bottom = 40.0
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="BackButton" parent="." instance=ExtResource( 2 )]
margin_left = 241.0
margin_top = 54.0
margin_right = 529.0
margin_bottom = 172.0
custom_styles/hover = SubResource( 1 )
custom_styles/pressed = SubResource( 2 )
custom_styles/normal = SubResource( 3 )
custom_fonts/font = SubResource( 4 )
text = "← Back"
[node name="FormContainer" type="VBoxContainer" parent="."]
margin_left = 396.0
margin_top = 200.0
margin_right = 1665.0
margin_bottom = 1060.0
grow_horizontal = 0
grow_vertical = 0
custom_constants/separation = 60
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label" type="Label" parent="FormContainer"]
margin_right = 1269.0
margin_bottom = 72.0
custom_fonts/font = SubResource( 5 )
text = "Sign up"
align = 1
[node name="MainFormContainer" type="HBoxContainer" parent="FormContainer"]
margin_top = 132.0
margin_right = 1269.0
margin_bottom = 525.0
custom_constants/separation = 30
[node name="FormLabels" type="VBoxContainer" parent="FormContainer/MainFormContainer"]
margin_right = 625.0
margin_bottom = 393.0
custom_constants/separation = 30
[node name="PlayerNameLabel" type="Label" parent="FormContainer/MainFormContainer/FormLabels"]
margin_right = 625.0
margin_bottom = 80.0
rect_min_size = Vector2( 0, 80 )
custom_fonts/font = SubResource( 6 )
text = "Username:"
[node name="EmailLabel" type="Label" parent="FormContainer/MainFormContainer/FormLabels"]
margin_top = 110.0
margin_right = 625.0
margin_bottom = 182.0
custom_fonts/font = SubResource( 6 )
text = "Email:"
[node name="PasswordLabel" type="Label" parent="FormContainer/MainFormContainer/FormLabels"]
margin_top = 212.0
margin_right = 625.0
margin_bottom = 284.0
custom_fonts/font = SubResource( 6 )
text = "Password:"
[node name="ConfirmPasswordLabel" type="Label" parent="FormContainer/MainFormContainer/FormLabels"]
margin_top = 314.0
margin_right = 625.0
margin_bottom = 386.0
custom_fonts/font = SubResource( 6 )
text = "Confirm password:"
[node name="FormInputFields" type="VBoxContainer" parent="FormContainer/MainFormContainer"]
margin_left = 655.0
margin_right = 1155.0
margin_bottom = 393.0
custom_constants/separation = 30
[node name="PlayerName" type="LineEdit" parent="FormContainer/MainFormContainer/FormInputFields"]
margin_right = 500.0
margin_bottom = 78.0
rect_min_size = Vector2( 500, 78 )
custom_fonts/font = SubResource( 7 )
max_length = 30
[node name="Email" type="LineEdit" parent="FormContainer/MainFormContainer/FormInputFields"]
margin_top = 108.0
margin_right = 500.0
margin_bottom = 183.0
rect_min_size = Vector2( 360, 75 )
custom_fonts/font = SubResource( 8 )
max_length = 50
[node name="Password" type="LineEdit" parent="FormContainer/MainFormContainer/FormInputFields"]
margin_top = 213.0
margin_right = 500.0
margin_bottom = 288.0
rect_min_size = Vector2( 360, 75 )
custom_fonts/font = SubResource( 9 )
max_length = 30
secret = true
[node name="ConfirmPassword" type="LineEdit" parent="FormContainer/MainFormContainer/FormInputFields"]
margin_top = 318.0
margin_right = 500.0
margin_bottom = 393.0
rect_min_size = Vector2( 360, 75 )
custom_fonts/font = SubResource( 10 )
max_length = 30
secret = true
[node name="InfoLabels" type="VBoxContainer" parent="FormContainer/MainFormContainer"]
margin_left = 1185.0
margin_right = 1269.0
margin_bottom = 393.0
rect_min_size = Vector2( 40, 0 )
custom_constants/separation = 24
[node name="UsernameToolButton" type="ToolButton" parent="FormContainer/MainFormContainer/InfoLabels"]
margin_right = 84.0
margin_bottom = 80.0
icon = ExtResource( 5 )
[node name="DummyToolButton1" type="ToolButton" parent="FormContainer/MainFormContainer/InfoLabels"]
margin_top = 104.0
margin_right = 84.0
margin_bottom = 184.0
icon = ExtResource( 6 )
[node name="PasswordToolButton" type="ToolButton" parent="FormContainer/MainFormContainer/InfoLabels"]
margin_top = 208.0
margin_right = 84.0
margin_bottom = 288.0
icon = ExtResource( 5 )
[node name="DummyToolButton2" type="ToolButton" parent="FormContainer/MainFormContainer/InfoLabels"]
margin_top = 312.0
margin_right = 84.0
margin_bottom = 392.0
icon = ExtResource( 6 )
[node name="InfoBox" type="Label" parent="FormContainer"]
visible = false
margin_right = 1269.0
margin_bottom = 137.0
rect_min_size = Vector2( 250, 0 )
custom_styles/normal = SubResource( 11 )
custom_fonts/font = SubResource( 12 )
custom_colors/font_color = Color( 0.666667, 0.223529, 0.223529, 1 )
custom_colors/font_outline_modulate = Color( 0.937255, 0.917647, 0.917647, 1 )
text = "Password should contain at least 8 characters including uppercase and lowercase letters, numbers and (optionally) special characters."
autowrap = true
[node name="ErrorMessage" type="Label" parent="FormContainer"]
visible = false
margin_right = 1189.0
margin_bottom = 37.0
custom_fonts/font = SubResource( 13 )
custom_colors/font_color = Color( 0.866667, 0.101961, 0.101961, 1 )
autowrap = true
[node name="RegisterButton" parent="FormContainer" instance=ExtResource( 2 )]
margin_top = 585.0
margin_right = 1269.0
margin_bottom = 703.0
text = "Submit"
[node name="ProcessingLabel" type="Label" parent="FormContainer"]
visible = false
margin_right = 1189.0
margin_bottom = 72.0
custom_fonts/font = SubResource( 14 )
text = "Processing..."
align = 1
[connection signal="pressed" from="BackButton" to="." method="_on_BackButton_pressed"]
[connection signal="mouse_entered" from="FormContainer/MainFormContainer/InfoLabels/UsernameToolButton" to="." method="_on_UsernameToolButton_mouse_entered"]
[connection signal="mouse_exited" from="FormContainer/MainFormContainer/InfoLabels/UsernameToolButton" to="." method="_on_UsernameToolButton_mouse_exited"]
[connection signal="mouse_entered" from="FormContainer/MainFormContainer/InfoLabels/PasswordToolButton" to="." method="_on_PasswordToolButton_mouse_entered"]
[connection signal="mouse_exited" from="FormContainer/MainFormContainer/InfoLabels/PasswordToolButton" to="." method="_on_PasswordToolButton_mouse_exited"]
[connection signal="pressed" from="FormContainer/RegisterButton" to="." method="_on_RegisterButton_pressed"]

View file

@ -1,266 +0,0 @@
[gd_scene load_steps=20 format=2]
[ext_resource path="res://addons/silent_wolf/Auth/Register.gd" type="Script" id=1]
[ext_resource path="res://addons/silent_wolf/common/SWButton.tscn" type="PackedScene" id=2]
[ext_resource path="res://addons/silent_wolf/assets/fonts/Comfortaa-Bold.ttf" type="DynamicFontData" id=3]
[ext_resource path="res://assets/fonts/Comfortaa-Bold.ttf" type="DynamicFontData" id=4]
[ext_resource path="res://addons/silent_wolf/assets/gfx/info_icon_small.png" type="Texture" id=5]
[ext_resource path="res://addons/silent_wolf/assets/gfx/dummy_info_icon_small.png" type="Texture" id=6]
[sub_resource type="StyleBoxFlat" id=1]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.831373, 0.415686, 0.415686, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="StyleBoxFlat" id=2]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.831373, 0.415686, 0.415686, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="StyleBoxFlat" id=3]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.482353, 0.458824, 0.458824, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="DynamicFont" id=4]
size = 64
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=5]
size = 64
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=6]
size = 64
font_data = ExtResource( 4 )
[sub_resource type="DynamicFont" id=7]
size = 32
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=8]
size = 32
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=9]
size = 32
font_data = ExtResource( 3 )
[sub_resource type="StyleBoxFlat" id=10]
content_margin_left = 30.0
content_margin_right = 30.0
content_margin_top = 30.0
content_margin_bottom = 30.0
bg_color = Color( 1, 1, 1, 1 )
border_width_left = 3
border_width_top = 3
border_width_right = 3
border_width_bottom = 3
border_color = Color( 0.666667, 0.223529, 0.223529, 1 )
corner_radius_top_left = 10
corner_radius_top_right = 10
corner_radius_bottom_right = 10
corner_radius_bottom_left = 10
[sub_resource type="DynamicFont" id=11]
size = 32
outline_color = Color( 0.666667, 0.223529, 0.223529, 1 )
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=12]
size = 32
outline_color = Color( 0.854902, 0.0901961, 0.0901961, 1 )
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=13]
size = 32
font_data = ExtResource( 3 )
[node name="Register" type="TextureRect"]
margin_right = 40.0
margin_bottom = 40.0
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="BackButton" parent="." instance=ExtResource( 2 )]
margin_left = 241.0
margin_top = 54.0
margin_right = 529.0
margin_bottom = 172.0
custom_styles/hover = SubResource( 1 )
custom_styles/pressed = SubResource( 2 )
custom_styles/normal = SubResource( 3 )
custom_fonts/font = SubResource( 4 )
text = "← Back"
[node name="FormContainer" type="VBoxContainer" parent="."]
margin_left = 396.0
margin_top = 200.0
margin_right = 1665.0
margin_bottom = 1060.0
grow_horizontal = 0
grow_vertical = 0
custom_constants/separation = 60
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label" type="Label" parent="FormContainer"]
margin_right = 1269.0
margin_bottom = 72.0
custom_fonts/font = SubResource( 5 )
text = "Sign up"
align = 1
[node name="MainFormContainer" type="HBoxContainer" parent="FormContainer"]
margin_top = 132.0
margin_right = 1269.0
margin_bottom = 524.0
custom_constants/separation = 30
[node name="FormLabels" type="VBoxContainer" parent="FormContainer/MainFormContainer"]
margin_right = 625.0
margin_bottom = 392.0
custom_constants/separation = 30
[node name="PlayerNameLabel" type="Label" parent="FormContainer/MainFormContainer/FormLabels"]
margin_right = 625.0
margin_bottom = 80.0
rect_min_size = Vector2( 0, 80 )
custom_fonts/font = SubResource( 6 )
text = "Username:"
[node name="PasswordLabel" type="Label" parent="FormContainer/MainFormContainer/FormLabels"]
margin_top = 110.0
margin_right = 625.0
margin_bottom = 182.0
custom_fonts/font = SubResource( 6 )
text = "Password:"
[node name="ConfirmPasswordLabel" type="Label" parent="FormContainer/MainFormContainer/FormLabels"]
margin_top = 212.0
margin_right = 625.0
margin_bottom = 284.0
custom_fonts/font = SubResource( 6 )
text = "Confirm password:"
[node name="FormInputFields" type="VBoxContainer" parent="FormContainer/MainFormContainer"]
margin_left = 655.0
margin_right = 1155.0
margin_bottom = 392.0
custom_constants/separation = 30
[node name="PlayerName" type="LineEdit" parent="FormContainer/MainFormContainer/FormInputFields"]
margin_right = 500.0
margin_bottom = 78.0
rect_min_size = Vector2( 500, 78 )
custom_fonts/font = SubResource( 7 )
max_length = 30
[node name="Password" type="LineEdit" parent="FormContainer/MainFormContainer/FormInputFields"]
margin_top = 108.0
margin_right = 500.0
margin_bottom = 183.0
rect_min_size = Vector2( 360, 75 )
custom_fonts/font = SubResource( 8 )
max_length = 30
secret = true
[node name="ConfirmPassword" type="LineEdit" parent="FormContainer/MainFormContainer/FormInputFields"]
margin_top = 213.0
margin_right = 500.0
margin_bottom = 288.0
rect_min_size = Vector2( 360, 75 )
custom_fonts/font = SubResource( 9 )
max_length = 30
secret = true
[node name="InfoLabels" type="VBoxContainer" parent="FormContainer/MainFormContainer"]
margin_left = 1185.0
margin_right = 1269.0
margin_bottom = 392.0
rect_min_size = Vector2( 40, 0 )
custom_constants/separation = 24
[node name="UsernameToolButton" type="ToolButton" parent="FormContainer/MainFormContainer/InfoLabels"]
margin_right = 84.0
margin_bottom = 80.0
icon = ExtResource( 5 )
[node name="DummyToolButton1" type="ToolButton" parent="FormContainer/MainFormContainer/InfoLabels"]
margin_top = 104.0
margin_right = 84.0
margin_bottom = 184.0
icon = ExtResource( 6 )
[node name="PasswordToolButton" type="ToolButton" parent="FormContainer/MainFormContainer/InfoLabels"]
margin_top = 208.0
margin_right = 84.0
margin_bottom = 288.0
icon = ExtResource( 5 )
[node name="DummyToolButton2" type="ToolButton" parent="FormContainer/MainFormContainer/InfoLabels"]
margin_top = 312.0
margin_right = 84.0
margin_bottom = 392.0
icon = ExtResource( 6 )
[node name="InfoBox" type="Label" parent="FormContainer"]
visible = false
margin_right = 1269.0
margin_bottom = 137.0
rect_min_size = Vector2( 250, 0 )
custom_styles/normal = SubResource( 10 )
custom_fonts/font = SubResource( 11 )
custom_colors/font_color = Color( 0.666667, 0.223529, 0.223529, 1 )
custom_colors/font_outline_modulate = Color( 0.937255, 0.917647, 0.917647, 1 )
text = "Password should contain at least 8 characters including uppercase and lowercase letters, numbers and (optionally) special characters."
autowrap = true
[node name="ErrorMessage" type="Label" parent="FormContainer"]
visible = false
margin_right = 1189.0
margin_bottom = 37.0
custom_fonts/font = SubResource( 12 )
custom_colors/font_color = Color( 0.866667, 0.101961, 0.101961, 1 )
autowrap = true
[node name="RegisterUPButton" parent="FormContainer" instance=ExtResource( 2 )]
margin_top = 584.0
margin_right = 1269.0
margin_bottom = 702.0
text = "Submit"
[node name="ProcessingLabel" type="Label" parent="FormContainer"]
visible = false
margin_right = 1189.0
margin_bottom = 72.0
custom_fonts/font = SubResource( 13 )
text = "Processing..."
align = 1
[connection signal="pressed" from="BackButton" to="." method="_on_BackButton_pressed"]
[connection signal="mouse_entered" from="FormContainer/MainFormContainer/InfoLabels/UsernameToolButton" to="." method="_on_UsernameToolButton_mouse_entered"]
[connection signal="mouse_exited" from="FormContainer/MainFormContainer/InfoLabels/UsernameToolButton" to="." method="_on_UsernameToolButton_mouse_exited"]
[connection signal="mouse_entered" from="FormContainer/MainFormContainer/InfoLabels/PasswordToolButton" to="." method="_on_PasswordToolButton_mouse_entered"]
[connection signal="mouse_exited" from="FormContainer/MainFormContainer/InfoLabels/PasswordToolButton" to="." method="_on_PasswordToolButton_mouse_exited"]
[connection signal="pressed" from="FormContainer/RegisterUPButton" to="." method="_on_RegisterUPButton_pressed"]

View file

@ -1,63 +0,0 @@
extends TextureRect
var player_name = null
var login_scene = "res://addons/silent_wolf/Auth/Login.tscn"
# Called when the node enters the scene tree for the first time.
func _ready():
$"RequestFormContainer/ProcessingLabel".hide()
$"PwdResetFormContainer/ProcessingLabel".hide()
$"PasswordChangedContainer".hide()
$"PwdResetFormContainer".hide()
$"RequestFormContainer".show()
SilentWolf.Auth.connect("sw_request_password_reset_succeeded", self, "_on_send_code_succeeded")
SilentWolf.Auth.connect("sw_request_password_reset_failed", self, "_on_send_code_failed")
SilentWolf.Auth.connect("sw_reset_password_succeeded", self, "_on_reset_succeeded")
SilentWolf.Auth.connect("sw_reset_password_failed", self, "_on_reset_failed")
if "login_scene" in SilentWolf.Auth:
login_scene = SilentWolf.Auth.login_scene
func _on_BackButton_pressed():
get_tree().change_scene(login_scene)
func _on_PlayerNameSubmitButton_pressed():
player_name = $"RequestFormContainer/FormContainer/FormInputFields/PlayerName".text
SilentWolf.Auth.request_player_password_reset(player_name)
$"RequestFormContainer/ProcessingLabel".show()
func _on_send_code_succeeded():
$"RequestFormContainer/ProcessingLabel".hide()
$"RequestFormContainer".hide()
$"PwdResetFormContainer".show()
func _on_send_code_failed(error):
$"RequestFormContainer/ProcessingLabel".hide()
$"RequestFormContainer/ErrorMessage".text = "Could not send confirmation code. " + str(error)
$"RequestFormContainer/ErrorMessage".show()
func _on_NewPasswordSubmitButton_pressed():
var code = $"PwdResetFormContainer/FormContainer/FormInputFields/Code".text
var password = $"PwdResetFormContainer/FormContainer/FormInputFields/Password".text
var confirm_password = $"PwdResetFormContainer/FormContainer/FormInputFields/ConfirmPassword".text
SilentWolf.Auth.reset_player_password(player_name, code, password, confirm_password)
$"PwdResetFormContainer/ProcessingLabel".show()
func _on_reset_succeeded():
$"PwdResetFormContainer/ProcessingLabel".hide()
$"PwdResetFormContainer".hide()
$"PasswordChangedContainer".show()
func _on_reset_failed(error):
$"PwdResetFormContainer/ProcessingLabel".hide()
$"PwdResetFormContainer/ErrorMessage".text = "Could not reset password. " + str(error)
$"PwdResetFormContainer/ErrorMessage".show()
func _on_CloseButton_pressed():
get_tree().change_scene(login_scene)

View file

@ -1,395 +0,0 @@
[gd_scene load_steps=27 format=2]
[ext_resource path="res://addons/silent_wolf/Auth/ResetPassword.gd" type="Script" id=1]
[ext_resource path="res://addons/silent_wolf/common/SWButton.tscn" type="PackedScene" id=2]
[ext_resource path="res://addons/silent_wolf/assets/fonts/Comfortaa-Bold.ttf" type="DynamicFontData" id=3]
[ext_resource path="res://assets/fonts/Comfortaa-Bold.ttf" type="DynamicFontData" id=6]
[sub_resource type="StyleBoxFlat" id=1]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.831373, 0.415686, 0.415686, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="StyleBoxFlat" id=2]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.831373, 0.415686, 0.415686, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="StyleBoxFlat" id=3]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.482353, 0.458824, 0.458824, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="DynamicFont" id=4]
size = 64
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=5]
size = 64
font_data = ExtResource( 6 )
[sub_resource type="DynamicFont" id=6]
size = 32
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=7]
size = 64
font_data = ExtResource( 6 )
[sub_resource type="DynamicFont" id=8]
size = 32
font_data = ExtResource( 6 )
[sub_resource type="DynamicFont" id=9]
size = 32
font_data = ExtResource( 6 )
[sub_resource type="StyleBoxFlat" id=10]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.831373, 0.415686, 0.415686, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="StyleBoxFlat" id=11]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.831373, 0.415686, 0.415686, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="StyleBoxFlat" id=12]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.666667, 0.223529, 0.223529, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="DynamicFont" id=13]
size = 64
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=14]
size = 64
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=15]
size = 32
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=16]
size = 64
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=17]
size = 64
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=18]
size = 64
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=19]
size = 32
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=20]
size = 32
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=21]
size = 32
outline_color = Color( 0.854902, 0.0901961, 0.0901961, 1 )
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=22]
size = 32
font_data = ExtResource( 3 )
[node name="ResetPassword" type="TextureRect"]
margin_right = 40.0
margin_bottom = 40.0
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="BackButton" parent="." instance=ExtResource( 2 )]
margin_left = 339.0
margin_top = 117.0
margin_right = 667.0
margin_bottom = 235.0
custom_styles/hover = SubResource( 1 )
custom_styles/pressed = SubResource( 2 )
custom_styles/normal = SubResource( 3 )
custom_fonts/font = SubResource( 4 )
text = "← Back"
[node name="RequestFormContainer" type="VBoxContainer" parent="."]
visible = false
margin_left = 679.0
margin_top = 196.75
margin_right = 1327.0
margin_bottom = 933.75
custom_constants/separation = 65
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label" type="Label" parent="RequestFormContainer"]
margin_right = 1035.0
margin_bottom = 72.0
custom_fonts/font = SubResource( 5 )
text = "Reset password"
align = 1
[node name="LabelExplainer" type="Label" parent="RequestFormContainer"]
margin_top = 137.0
margin_right = 1035.0
margin_bottom = 174.0
custom_fonts/font = SubResource( 6 )
text = "Please enter your player name below."
autowrap = true
[node name="FormContainer" type="HBoxContainer" parent="RequestFormContainer"]
margin_top = 239.0
margin_right = 1035.0
margin_bottom = 314.0
custom_constants/separation = 50
[node name="FormLabels" type="VBoxContainer" parent="RequestFormContainer/FormContainer"]
margin_right = 426.0
margin_bottom = 75.0
custom_constants/separation = 30
[node name="PlayerNameLabel" type="Label" parent="RequestFormContainer/FormContainer/FormLabels"]
margin_right = 426.0
margin_bottom = 72.0
custom_fonts/font = SubResource( 7 )
text = "Player name:"
[node name="FormInputFields" type="VBoxContainer" parent="RequestFormContainer/FormContainer"]
margin_left = 476.0
margin_right = 836.0
margin_bottom = 75.0
custom_constants/separation = 30
[node name="PlayerName" type="LineEdit" parent="RequestFormContainer/FormContainer/FormInputFields"]
margin_right = 360.0
margin_bottom = 75.0
rect_min_size = Vector2( 360, 75 )
custom_fonts/font = SubResource( 8 )
max_length = 50
[node name="ErrorMessage" type="Label" parent="RequestFormContainer"]
visible = false
margin_top = 522.0
margin_right = 648.0
margin_bottom = 559.0
custom_fonts/font = SubResource( 9 )
custom_colors/font_color = Color( 0.866667, 0.101961, 0.101961, 1 )
autowrap = true
[node name="PlayerNameSubmitButton" parent="RequestFormContainer" instance=ExtResource( 2 )]
margin_top = 379.0
margin_right = 1035.0
margin_bottom = 497.0
custom_styles/hover = SubResource( 10 )
custom_styles/pressed = SubResource( 11 )
custom_styles/normal = SubResource( 12 )
custom_fonts/font = SubResource( 13 )
text = "Submit"
[node name="ProcessingLabel" type="Label" parent="RequestFormContainer"]
visible = false
margin_top = 740.0
margin_right = 648.0
margin_bottom = 812.0
custom_fonts/font = SubResource( 5 )
text = "Processing..."
align = 1
[node name="PwdResetFormContainer" type="VBoxContainer" parent="."]
margin_left = 679.0
margin_top = 196.75
margin_right = 1714.0
margin_bottom = 973.75
custom_constants/separation = 70
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label" type="Label" parent="PwdResetFormContainer"]
margin_right = 1035.0
margin_bottom = 72.0
custom_fonts/font = SubResource( 14 )
text = "Reset password"
align = 1
[node name="LabelExplainer" type="Label" parent="PwdResetFormContainer"]
margin_top = 142.0
margin_right = 1035.0
margin_bottom = 219.0
custom_fonts/font = SubResource( 15 )
text = "Please enter below the code we sent you by email and your new password twice."
autowrap = true
[node name="FormContainer" type="HBoxContainer" parent="PwdResetFormContainer"]
margin_top = 289.0
margin_right = 1035.0
margin_bottom = 574.0
custom_constants/separation = 50
[node name="FormLabels" type="VBoxContainer" parent="PwdResetFormContainer/FormContainer"]
margin_right = 625.0
margin_bottom = 285.0
custom_constants/separation = 30
[node name="CodeLabel" type="Label" parent="PwdResetFormContainer/FormContainer/FormLabels"]
margin_right = 625.0
margin_bottom = 72.0
custom_fonts/font = SubResource( 16 )
text = "Code:"
[node name="PasswordLabel" type="Label" parent="PwdResetFormContainer/FormContainer/FormLabels"]
margin_top = 102.0
margin_right = 625.0
margin_bottom = 174.0
custom_fonts/font = SubResource( 17 )
text = "Password:"
[node name="ConfirmPasswordLabel" type="Label" parent="PwdResetFormContainer/FormContainer/FormLabels"]
margin_top = 204.0
margin_right = 625.0
margin_bottom = 276.0
custom_fonts/font = SubResource( 18 )
text = "Confirm password:"
[node name="FormInputFields" type="VBoxContainer" parent="PwdResetFormContainer/FormContainer"]
margin_left = 675.0
margin_right = 1035.0
margin_bottom = 285.0
custom_constants/separation = 30
[node name="Code" type="LineEdit" parent="PwdResetFormContainer/FormContainer/FormInputFields"]
margin_right = 360.0
margin_bottom = 75.0
rect_min_size = Vector2( 360, 75 )
custom_fonts/font = SubResource( 8 )
max_length = 50
[node name="Password" type="LineEdit" parent="PwdResetFormContainer/FormContainer/FormInputFields"]
margin_top = 105.0
margin_right = 360.0
margin_bottom = 180.0
rect_min_size = Vector2( 360, 75 )
custom_fonts/font = SubResource( 19 )
max_length = 30
secret = true
[node name="ConfirmPassword" type="LineEdit" parent="PwdResetFormContainer/FormContainer/FormInputFields"]
margin_top = 210.0
margin_right = 360.0
margin_bottom = 285.0
rect_min_size = Vector2( 360, 75 )
custom_fonts/font = SubResource( 20 )
max_length = 30
secret = true
[node name="ErrorMessage" type="Label" parent="PwdResetFormContainer"]
visible = false
margin_top = 522.0
margin_right = 648.0
margin_bottom = 559.0
custom_fonts/font = SubResource( 21 )
custom_colors/font_color = Color( 0.866667, 0.101961, 0.101961, 1 )
autowrap = true
[node name="NewPasswordSubmitButton" parent="PwdResetFormContainer" instance=ExtResource( 2 )]
margin_top = 644.0
margin_right = 1035.0
margin_bottom = 762.0
custom_styles/hover = SubResource( 10 )
custom_styles/pressed = SubResource( 11 )
custom_styles/normal = SubResource( 12 )
custom_fonts/font = SubResource( 13 )
text = "Submit"
[node name="ProcessingLabel" type="Label" parent="PwdResetFormContainer"]
visible = false
margin_top = 740.0
margin_right = 648.0
margin_bottom = 812.0
custom_fonts/font = SubResource( 22 )
text = "Processing..."
align = 1
[node name="PasswordChangedContainer" type="VBoxContainer" parent="."]
visible = false
margin_left = 679.0
margin_top = 312.0
margin_right = 1327.0
margin_bottom = 933.0
custom_constants/separation = 100
__meta__ = {
"_edit_use_anchors_": false
}
[node name="PwdChanedLabel" type="Label" parent="PasswordChangedContainer"]
margin_right = 524.0
margin_bottom = 72.0
custom_fonts/font = SubResource( 5 )
text = "Password reset"
align = 1
[node name="PasswordChangedLabelExplainer" type="Label" parent="PasswordChangedContainer"]
margin_top = 76.0
margin_right = 524.0
margin_bottom = 153.0
custom_fonts/font = SubResource( 15 )
text = "Your password was changed successfully."
autowrap = true
[node name="CloseButton" parent="PasswordChangedContainer" instance=ExtResource( 2 )]
margin_top = 157.0
margin_right = 524.0
margin_bottom = 275.0
custom_styles/hover = SubResource( 10 )
custom_styles/pressed = SubResource( 11 )
custom_styles/normal = SubResource( 12 )
custom_fonts/font = SubResource( 13 )
text = "Close"
[connection signal="pressed" from="BackButton" to="." method="_on_BackButton_pressed"]
[connection signal="pressed" from="RequestFormContainer/PlayerNameSubmitButton" to="." method="_on_PlayerNameSubmitButton_pressed"]
[connection signal="pressed" from="PwdResetFormContainer/NewPasswordSubmitButton" to="." method="_on_NewPasswordSubmitButton_pressed"]
[connection signal="pressed" from="PasswordChangedContainer/CloseButton" to="." method="_on_CloseButton_pressed"]

Binary file not shown.

View file

@ -1,39 +0,0 @@
extends Node
onready var WSClient = Node.new()
var mp_ws_ready = false
var mp_session_started = false
var mp_player_name = ""
func _ready():
mp_ws_ready = false
mp_session_started = false
var ws_client_script = load("res://addons/silent_wolf/Multiplayer/ws/WSClient.gd")
WSClient.set_script(ws_client_script)
add_child(WSClient)
func init_mp_session(player_name):
#mp_player_name = player_name
WSClient.init_mp_session(player_name)
# TODO: instead of waiting an arbitrary amount of time, yield on
# a function that guarantees that child ready() function has run
#yield(get_tree().create_timer(0.3), "timeout")
func _send_init_message():
WSClient.init_mp_session(mp_player_name)
mp_ws_ready = true
mp_session_started = true
func send(data: Dictionary):
# First check that WSClient is in tree
print("Attempting to send data to web socket server")
if WSClient.is_inside_tree():
# TODO: check if data is properly formatted (should be dictionary?)
print("Sending data to web socket server...")
WSClient.send_to_server("update", data)

View file

@ -1,81 +0,0 @@
extends Node
const SWLogger = preload("res://addons/silent_wolf/utils/SWLogger.gd")
# The URL we will connect to
export var websocket_url = "wss://ws.silentwolfmp.com/server"
export var ws_room_init_url = "wss://ws.silentwolfmp.com/init"
signal ws_client_ready
# Our WebSocketClient instance
var _client = WebSocketClient.new()
func _ready():
SWLogger.debug("Entering MPClient _ready function")
# Connect base signals to get notified of connection open, close, and errors.
_client.connect("connection_closed", self, "_closed")
_client.connect("connection_error", self, "_closed")
_client.connect("connection_established", self, "_connected")
# This signal is emitted when not using the Multiplayer API every time
# a full packet is received.
# Alternatively, you could check get_peer(1).get_available_packets() in a loop.
_client.connect("data_received", self, "_on_data")
# Initiate connection to the given URL.
var err = _client.connect_to_url(websocket_url)
if err != OK:
#SWLogger.debug("Unable to connect to WS server")
print("Unable to connect to WS server")
set_process(false)
emit_signal("ws_client_ready")
func _closed(was_clean = false):
# was_clean will tell you if the disconnection was correctly notified
# by the remote peer before closing the socket.
SWLogger.debug("WS connection closed, clean: " + str(was_clean))
set_process(false)
func _connected(proto = ""):
# This is called on connection, "proto" will be the selected WebSocket
# sub-protocol (which is optional)
#SWLogger.debug("Connected with protocol: " + str(proto))
print("Connected with protocol: ", proto)
# You MUST always use get_peer(1).put_packet to send data to server,
# and not put_packet directly when not using the MultiplayerAPI.
#var test_packet = { "data": "Test packet" }
#send_to_server(test_packet)
#_client.get_peer(1).put_packet("Test packet".to_utf8())
func _on_data():
# Print the received packet, you MUST always use get_peer(1).get_packet
# to receive data from server, and not get_packet directly when not
# using the MultiplayerAPI.
#SWLogger.debug("Got data from WS server: " + str(_client.get_peer(1).get_packet().get_string_from_utf8()))
print("Got data from WS server: ", _client.get_peer(1).get_packet().get_string_from_utf8())
func _process(delta):
# Call this in _process or _physics_process. Data transfer, and signals
# emission will only happen when calling this function.
_client.poll()
# send arbitrary data to backend
func send_to_server(message_type, data):
data["message_type"] = message_type
print("Sending data to server: " + str(data))
_client.get_peer(1).put_packet(str(JSON.print(data)).to_utf8())
func init_mp_session(player_name):
print("WSClient init_mp_session, sending initialisation packet to server")
var init_packet = {
"player_name": player_name
}
return send_to_server("init", init_packet)
func create_room():
pass

View file

@ -1,199 +0,0 @@
extends Node
const CommonErrors = preload("res://addons/silent_wolf/common/CommonErrors.gd")
const SWLogger = preload("res://addons/silent_wolf/utils/SWLogger.gd")
signal sw_player_data_received
signal sw_player_data_posted
signal sw_player_data_removed
var GetPlayerData = null
var PushPlayerData = null
var RemovePlayerData = null
# wekrefs
var wrGetPlayerData = null
var wrPushPlayerData = null
var wrRemovePlayerData = null
var player_name = null
var player_data = null
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
func set_player_data(new_player_data):
player_data = new_player_data
func clear_player_data():
player_name = null
player_data = null
func get_stats():
var stats = null
if player_data:
stats = {
"strength": player_data.strength,
"speed": player_data.speed,
"reflexes": player_data.reflexes,
"max_health": player_data.max_health,
"career": player_data.career
}
return stats
func get_inventory():
var inventory = null
if player_data:
inventory = {
"weapons": player_data.weapons,
"gold": player_data.gold
}
return inventory
func get_player_data(player_name):
GetPlayerData = HTTPRequest.new()
wrGetPlayerData = weakref(GetPlayerData)
if OS.get_name() != "HTML5":
GetPlayerData.set_use_threads(true)
get_tree().get_root().add_child(GetPlayerData)
GetPlayerData.connect("request_completed", self, "_on_GetPlayerData_request_completed")
SWLogger.info("Calling SilentWolf to get player data")
var game_id = SilentWolf.config.game_id
var game_version = SilentWolf.config.game_version
var api_key = SilentWolf.config.api_key
var headers = [
"x-api-key: " + api_key,
"x-sw-plugin-version: " + SilentWolf.version,
"x-sw-game-id: " + SilentWolf.config.game_id,
"x-sw-godot-version: " + SilentWolf.godot_version
]
GetPlayerData.request("https://api.silentwolf.com/get_player_data/" + game_id + "/" + player_name, headers, true, HTTPClient.METHOD_GET)
return self
func post_player_data(player_name, player_data, overwrite=true):
if typeof(player_data) != TYPE_DICTIONARY:
SWLogger.error("Player data should be of type Dictionary, instead it is of type: " + str(typeof(player_data)))
PushPlayerData = HTTPRequest.new()
wrPushPlayerData = weakref(PushPlayerData)
if OS.get_name() != "HTML5":
PushPlayerData.set_use_threads(true)
get_tree().get_root().add_child(PushPlayerData)
PushPlayerData.connect("request_completed", self, "_on_PushPlayerData_request_completed")
SWLogger.info("Calling SilentWolf to post player data")
var game_id = SilentWolf.config.game_id
var game_version = SilentWolf.config.game_version
var api_key = SilentWolf.config.api_key
var headers = [
"Content-Type: application/json",
"x-api-key: " + api_key,
"x-sw-plugin-version: " + SilentWolf.version,
"x-sw-game-id: " + SilentWolf.config.game_id,
"x-sw-godot-version: " + SilentWolf.godot_version
]
var payload = { "game_id": game_id, "game_version": game_version, "player_name": player_name, "player_data": player_data, "overwrite": overwrite }
var query = JSON.print(payload)
PushPlayerData.request("https://api.silentwolf.com/push_player_data", headers, true, HTTPClient.METHOD_POST, query)
return self
func delete_player_weapons(player_name):
var weapons = { "Weapons": [] }
delete_player_data(player_name, weapons)
func remove_player_money(player_name):
var money = { "Money": 0 }
delete_player_data(player_name, money)
func delete_player_items(player_name, item_name):
var item = { item_name: "" }
delete_player_data(player_name, item)
func delete_all_player_data(player_name):
delete_player_data(player_name, "")
func delete_player_data(player_name, player_data):
RemovePlayerData = HTTPRequest.new()
wrRemovePlayerData = weakref(RemovePlayerData)
if OS.get_name() != "HTML5":
RemovePlayerData.set_use_threads(true)
get_tree().get_root().add_child(RemovePlayerData)
RemovePlayerData.connect("request_completed", self, "_on_RemovePlayerData_request_completed")
SWLogger.info("Calling SilentWolf to remove player data")
var game_id = SilentWolf.config.game_id
var api_key = SilentWolf.config.api_key
var headers = [
"Content-Type: application/json",
"x-api-key: " + api_key,
"x-sw-plugin-version: " + SilentWolf.version,
"x-sw-game-id: " + SilentWolf.config.game_id,
"x-sw-godot-version: " + SilentWolf.godot_version
]
var payload = { "game_id": game_id, "player_name": player_name, "player_data": player_data }
var query = JSON.print(payload)
RemovePlayerData.request("https://api.silentwolf.com/remove_player_data", headers, true, HTTPClient.METHOD_POST, query)
return self
func _on_GetPlayerData_request_completed(result, response_code, headers, body):
SWLogger.info("GetPlayerData request completed")
var status_check = CommonErrors.check_status_code(response_code)
#print("client status: " + str(GetPlayerData.get_http_client_status()))
if is_instance_valid(GetPlayerData):
SilentWolf.free_request(wrGetPlayerData, GetPlayerData)
#GetPlayerData.queue_free()
SWLogger.debug("response headers: " + str(response_code))
SWLogger.debug("response headers: " + str(headers))
SWLogger.debug("response body: " + str(body.get_string_from_utf8()))
if status_check:
var json = JSON.parse(body.get_string_from_utf8())
var response = json.result
if "message" in response.keys() and response.message == "Forbidden":
SWLogger.error("You are not authorized to call the SilentWolf API - check your API key configuration: https://silentwolf.com/playerdata")
else:
SWLogger.info("SilentWolf get player data success")
player_name = response.player_name
player_data = response.player_data
SWLogger.debug("Request completed: Player data: " + str(player_data))
emit_signal("sw_player_data_received", player_name, player_data)
func _on_PushPlayerData_request_completed(result, response_code, headers, body):
SWLogger.info("PushPlayerData request completed")
var status_check = CommonErrors.check_status_code(response_code)
if is_instance_valid(PushPlayerData):
#PushPlayerData.queue_free()
SilentWolf.free_request(wrPushPlayerData, PushPlayerData)
SWLogger.debug("response headers: " + str(response_code))
SWLogger.debug("response headers: " + str(headers))
SWLogger.debug("response body: " + str(body.get_string_from_utf8()))
if status_check:
var json = JSON.parse(body.get_string_from_utf8())
var response = json.result
if "message" in response.keys() and response.message == "Forbidden":
SWLogger.error("You are not authorized to call the SilentWolf API - check your API key configuration: https://silentwolf.com/playerdata")
else:
SWLogger.info("SilentWolf post player data score success: " + str(response_code))
var player_name = response.player_name
emit_signal("sw_player_data_posted", player_name)
func _on_RemovePlayerData_request_completed(result, response_code, headers, body):
SWLogger.info("RemovePlayerData request completed")
var status_check = CommonErrors.check_status_code(response_code)
if is_instance_valid(RemovePlayerData):
RemovePlayerData.queue_free()
SWLogger.debug("response headers: " + str(response_code))
SWLogger.debug("response headers: " + str(headers))
SWLogger.debug("response body: " + str(body.get_string_from_utf8()))
if status_check:
var json = JSON.parse(body.get_string_from_utf8())
var response = json.result
if "message" in response.keys() and response.message == "Forbidden":
SWLogger.error("You are not authorized to call the SilentWolf API - check your API key configuration: https://silentwolf.com/playerdata")
else:
SWLogger.info("SilentWolf post player data score success: " + str(response_code))
var player_name = response.player_name
# return player_data after (maybe partial) removal
var player_data = response.player_data
emit_signal("sw_player_data_removed", player_name, player_data)

Binary file not shown.

View file

@ -1,126 +0,0 @@
tool
extends Node2D
const ScoreItem = preload("ScoreItem.tscn")
const SWLogger = preload("res://addons/silent_wolf/utils/SWLogger.gd")
var list_index = 0
# Replace the leaderboard name if you're not using the default leaderboard
var ld_name = "main"
var max_scores = 10
func _ready():
print("SilentWolf.Scores.leaderboards: " + str(SilentWolf.Scores.leaderboards))
print("SilentWolf.Scores.ldboard_config: " + str(SilentWolf.Scores.ldboard_config))
#var scores = SilentWolf.Scores.scores
var scores = []
if ld_name in SilentWolf.Scores.leaderboards:
scores = SilentWolf.Scores.leaderboards[ld_name]
var local_scores = SilentWolf.Scores.local_scores
if len(scores) > 0:
render_board(scores, local_scores)
else:
# use a signal to notify when the high scores have been returned, and show a "loading" animation until it's the case...
add_loading_scores_message()
yield(SilentWolf.Scores.get_high_scores(), "sw_scores_received")
hide_message()
render_board(SilentWolf.Scores.scores, local_scores)
func render_board(scores, local_scores):
var all_scores = scores
if ld_name in SilentWolf.Scores.ldboard_config and is_default_leaderboard(SilentWolf.Scores.ldboard_config[ld_name]):
all_scores = merge_scores_with_local_scores(scores, local_scores, max_scores)
if !scores and !local_scores:
add_no_scores_message()
else:
if !scores:
add_no_scores_message()
if !all_scores:
for score in scores:
add_item(score.player_name, str(int(score.score)))
else:
for score in all_scores:
add_item(score.player_name, str(int(score.score)))
func is_default_leaderboard(ld_config):
var default_insert_opt = (ld_config.insert_opt == "keep")
var not_time_based = !("time_based" in ld_config)
return default_insert_opt and not_time_based
func merge_scores_with_local_scores(scores, local_scores, max_scores=10):
if local_scores:
for score in local_scores:
var in_array = score_in_score_array(scores, score)
if !in_array:
scores.append(score)
scores.sort_custom(self, "sort_by_score");
var return_scores = scores
if scores.size() > max_scores:
return_scores = scores.resize(max_scores)
return return_scores
func sort_by_score(a, b):
if a.score > b.score:
return true;
else:
if a.score < b.score:
return false;
else:
return true;
func score_in_score_array(scores, new_score):
var in_score_array = false
if new_score and scores:
for score in scores:
if score.score_id == new_score.score_id: # score.player_name == new_score.player_name and score.score == new_score.score:
in_score_array = true
return in_score_array
func add_item(player_name, score):
var item = ScoreItem.instance()
list_index += 1
item.get_node("PlayerName").text = str(list_index) + str(". ") + player_name
item.get_node("Score").text = score
item.margin_top = list_index * 100
$"Board/HighScores/ScoreItemContainer".add_child(item)
func add_no_scores_message():
var item = $"Board/MessageContainer/TextMessage"
item.text = "No scores yet!"
$"Board/MessageContainer".show()
item.margin_top = 135
func add_loading_scores_message():
var item = $"Board/MessageContainer/TextMessage"
item.text = "Loading scores..."
$"Board/MessageContainer".show()
item.margin_top = 135
func hide_message():
$"Board/MessageContainer".hide()
func clear_leaderboard():
var score_item_container = $"Board/HighScores/ScoreItemContainer"
if score_item_container.get_child_count() > 0:
var children = score_item_container.get_children()
for c in children:
score_item_container.remove_child(c)
c.queue_free()
func _on_CloseButton_pressed():
var scene_name = SilentWolf.scores_config.open_scene_on_close
SWLogger.info("Closing SilentWolf leaderboard, switching to scene: " + str(scene_name))
#global.reset()
get_tree().change_scene(scene_name)

View file

@ -1,88 +0,0 @@
[gd_scene load_steps=8 format=2]
[ext_resource path="res://addons/silent_wolf/Scores/Leaderboard.gd" type="Script" id=1]
[ext_resource path="res://addons/silent_wolf/Scores/assets/fonts/Comfortaa-Bold.ttf" type="DynamicFontData" id=2]
[ext_resource path="res://addons/silent_wolf/assets/fonts/Comfortaa-Bold.ttf" type="DynamicFontData" id=3]
[ext_resource path="res://addons/silent_wolf/common/SWButton.tscn" type="PackedScene" id=4]
[sub_resource type="DynamicFont" id=1]
size = 76
font_data = ExtResource( 2 )
[sub_resource type="DynamicFont" id=2]
size = 32
font_data = ExtResource( 3 )
[sub_resource type="Theme" id=3]
[node name="Leaderboard" type="Node2D"]
script = ExtResource( 1 )
[node name="OldBoard" type="MarginContainer" parent="."]
visible = false
margin_left = 50.0
margin_right = 50.0
margin_bottom = 40.0
[node name="HighScores" type="TextureRect" parent="OldBoard"]
margin_bottom = 40.0
[node name="Board" type="VBoxContainer" parent="."]
margin_left = 20.0
margin_top = 20.0
margin_right = 1884.0
margin_bottom = 1071.0
custom_constants/separation = 0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="TitleContainer" type="CenterContainer" parent="Board"]
margin_right = 1864.0
margin_bottom = 85.0
[node name="Label" type="Label" parent="Board/TitleContainer"]
margin_left = 667.0
margin_right = 1196.0
margin_bottom = 85.0
custom_fonts/font = SubResource( 1 )
text = "Leaderboard"
[node name="MessageContainer" type="CenterContainer" parent="Board"]
visible = false
margin_top = 89.0
margin_right = 1864.0
margin_bottom = 126.0
[node name="TextMessage" type="Label" parent="Board/MessageContainer"]
margin_left = 789.0
margin_right = 1075.0
margin_bottom = 37.0
custom_fonts/font = SubResource( 2 )
text = "Loading scores..."
valign = 1
[node name="HighScores" type="CenterContainer" parent="Board"]
margin_top = 85.0
margin_right = 1864.0
margin_bottom = 185.0
rect_min_size = Vector2( 0, 100 )
theme = SubResource( 3 )
[node name="ScoreItemContainer" type="VBoxContainer" parent="Board/HighScores"]
margin_left = 932.0
margin_top = 50.0
margin_right = 932.0
margin_bottom = 50.0
[node name="CloseButtonContainer" type="CenterContainer" parent="Board"]
margin_top = 185.0
margin_right = 1864.0
margin_bottom = 303.0
[node name="CloseButton" parent="Board/CloseButtonContainer" instance=ExtResource( 4 )]
margin_left = 582.0
margin_right = 1281.0
margin_bottom = 118.0
text = "Close Leaderboard"
[connection signal="pressed" from="Board/CloseButtonContainer/CloseButton" to="." method="_on_CloseButton_pressed"]

View file

@ -1,48 +0,0 @@
[gd_scene load_steps=5 format=2]
[ext_resource path="res://addons/silent_wolf/assets/fonts/Comfortaa-Bold.ttf" type="DynamicFontData" id=2]
[sub_resource type="StyleBoxFlat" id=1]
bg_color = Color( 0.831373, 0.415686, 0.415686, 1 )
[sub_resource type="DynamicFont" id=2]
size = 32
font_data = ExtResource( 2 )
[sub_resource type="DynamicFont" id=3]
size = 40
use_mipmaps = true
use_filter = true
font_data = ExtResource( 2 )
[node name="ScoreItem" type="Panel"]
margin_right = 782.0
margin_bottom = 76.0
grow_horizontal = 0
grow_vertical = 0
rect_min_size = Vector2( 782, 76 )
custom_styles/panel = SubResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="PlayerName" type="RichTextLabel" parent="."]
margin_left = 22.0
margin_top = 18.0
margin_right = 589.0
margin_bottom = 73.0
custom_fonts/normal_font = SubResource( 2 )
text = "1. Godzilla"
[node name="Score" type="Label" parent="."]
margin_left = 671.0
margin_top = 17.0
margin_right = 756.0
margin_bottom = 65.0
custom_fonts/font = SubResource( 3 )
text = "13"
align = 2
valign = 1
__meta__ = {
"_edit_use_anchors_": false
}

View file

@ -1,528 +0,0 @@
extends Node
const CommonErrors = preload("res://addons/silent_wolf/common/CommonErrors.gd")
const SWLogger = preload("res://addons/silent_wolf/utils/SWLogger.gd")
const UUID = preload("res://addons/silent_wolf/utils/UUID.gd")
const SWHashing = preload("res://addons/silent_wolf/utils/SWHashing.gd")
# legacy signals
signal scores_received
signal position_received
signal score_posted
# new signals
signal sw_scores_received
signal sw_player_scores_received
signal sw_top_player_score_received
signal sw_position_received
signal sw_scores_around_received
signal sw_score_posted
signal sw_leaderboard_wiped
signal sw_score_deleted
# leaderboard scores by leaderboard name
var leaderboards = {}
# leaderboard scores from past periods by leaderboard name and period_offset (negative integers)
var leaderboards_past_periods = {}
# leaderboard configurations by leaderboard name
var ldboard_config = {}
# contains only the scores from one leaderboard at a time
var scores = []
var player_scores = []
var player_top_score = null
var local_scores = []
#var custom_local_scores = []
var score_id = ""
var position = 0
var scores_above = []
var scores_below = []
#var request_timeout = 3
#var request_timer = null
# latest number of scores to be fetched from the backend
var latest_max = 10
var ScorePosition = null
var ScoresAround = null
var HighScores = null
var ScoresByPlayer = null
var TopScoreByPlayer = null
var PostScore = null
var WipeLeaderboard = null
var DeleteScore = null
# wekrefs
var wrScorePosition = null
var wrScoresAround = null
var wrHighScores = null
var wrScoresByPlayer = null
var wrTopScoreByPlayer = null
var wrPostScore = null
var wrWipeLeaderboard = null
var wrDeleteScore = null
# Called when the node enters the scene tree for the first time.
func _ready():
pass
#connect("request_completed", self, "_on_Scores_request_completed")
#setup_request_timer()
func get_score_position(score, ldboard_name="main"):
var score_id = null
var score_value = null
print("score: " + str(score))
if UUID.is_uuid(str(score)):
score_id = score
else:
score_value = score
ScorePosition = HTTPRequest.new()
wrScorePosition = weakref(ScorePosition)
if OS.get_name() != "HTML5":
ScorePosition.set_use_threads(true)
get_tree().get_root().call_deferred("add_child", ScorePosition)
ScorePosition.connect("request_completed", self, "_on_GetScorePosition_request_completed")
SWLogger.info("Calling SilentWolf to get score position")
var game_id = SilentWolf.config.game_id
var game_version = SilentWolf.config.game_version
var payload = { "game_id": game_id, "game_version": game_version, "ldboard_name": ldboard_name }
if score_id:
payload["score_id"] = score_id
if score_value:
payload["score_value"] = score_value
var request_url = "https://api.silentwolf.com/get_score_position"
send_post_request(ScorePosition, request_url, payload)
return self
func get_scores_around(score, scores_to_fetch=3, ldboard_name="main"):
var score_id = null
var score_value = null
print("score: " + str(score))
if UUID.is_uuid(str(score)):
score_id = score
else:
score_value = score
ScoresAround = HTTPRequest.new()
wrScoresAround = weakref(ScoresAround)
if OS.get_name() != "HTML5":
ScoresAround.set_use_threads(true)
get_tree().get_root().call_deferred("add_child",ScoresAround)
ScoresAround.connect("request_completed", self, "_on_ScoresAround_request_completed")
SWLogger.info("Calling SilentWolf backend to scores above and below a certain score...")
# resetting the latest_number value in case the first requests times out, we need to request the same amount of top scores in the retry
#latest_max = maximum
var game_id = SilentWolf.config.game_id
var game_version = SilentWolf.config.game_version
var request_url = "https://api.silentwolf.com/get_scores_around/" + str(game_id) + "?version=" + str(game_version) + "&scores_to_fetch=" + str(scores_to_fetch) + "&ldboard_name=" + str(ldboard_name) + "&score_id=" + str(score_id) + "&score_value=" + str(score_value)
send_get_request(ScoresAround, request_url)
return self
func get_high_scores(maximum=10, ldboard_name="main", period_offset=0):
HighScores = HTTPRequest.new()
wrHighScores = weakref(HighScores)
if OS.get_name() != "HTML5":
HighScores.set_use_threads(true)
get_tree().get_root().call_deferred("add_child", HighScores)
HighScores.connect("request_completed", self, "_on_GetHighScores_request_completed")
SWLogger.info("Calling SilentWolf backend to get scores...")
# resetting the latest_number value in case the first requests times out, we need to request the same amount of top scores in the retry
latest_max = maximum
var game_id = SilentWolf.config.game_id
var game_version = SilentWolf.config.game_version
var request_url = "https://api.silentwolf.com/get_top_scores/" + str(game_id) + "?version=" + str(game_version) + "&max=" + str(maximum) + "&ldboard_name=" + str(ldboard_name) + "&period_offset=" + str(period_offset)
send_get_request(HighScores, request_url)
return self
func get_scores_by_player(player_name, maximum=10, ldboard_name="main", period_offset=0):
print("get_scores_by_player, player_name = " + str(player_name))
if player_name == null:
SWLogger.error("Error in SilentWolf.Scores.get_scores_by_player: provided player_name is null")
else:
ScoresByPlayer = HTTPRequest.new()
wrScoresByPlayer = weakref(ScoresByPlayer)
if OS.get_name() != "HTML5":
ScoresByPlayer.set_use_threads(true)
get_tree().get_root().call_deferred("add_child", ScoresByPlayer)
ScoresByPlayer.connect("request_completed", self, "_on_GetScoresByPlayer_request_completed")
SWLogger.info("Calling SilentWolf backend to get scores for player: " + str(player_name))
# resetting the latest_number value in case the first requests times out, we need to request the same amount of top scores in the retry
latest_max = maximum
var game_id = SilentWolf.config.game_id
var game_version = SilentWolf.config.game_version
print("ldboard_name: " + str(ldboard_name))
var request_url = "https://api.silentwolf.com/get_scores_by_player/" + str(game_id) + "?version=" + str(game_version) + "&max=" + str(maximum) + "&ldboard_name=" + str(ldboard_name.percent_encode()) + "&player_name=" + str(player_name.percent_encode()) + "&period_offset=" + str(period_offset)
send_get_request(ScoresByPlayer, request_url)
return self
func get_top_score_by_player(player_name, maximum=10, ldboard_name="main", period_offset=0):
SWLogger.info("get_top_score_by_player, player_name = " + str(player_name))
if player_name == null:
SWLogger.error("Error in SilentWolf.Scores.get_top_score_by_player: provided player_name is null")
else:
TopScoreByPlayer = HTTPRequest.new()
wrTopScoreByPlayer = weakref(TopScoreByPlayer)
if OS.get_name() != "HTML5":
TopScoreByPlayer.set_use_threads(true)
get_tree().get_root().call_deferred("add_child", TopScoreByPlayer)
TopScoreByPlayer.connect("request_completed", self, "_on_GetTopScoreByPlayer_request_completed")
SWLogger.info("Calling SilentWolf backend to get scores for player: " + str(player_name))
# resetting the latest_number value in case the first requests times out, we need to request the same amount of top scores in the retry
latest_max = maximum
var game_id = SilentWolf.config.game_id
var game_version = SilentWolf.config.game_version
var request_url = "https://api.silentwolf.com/get_top_score_by_player/" + str(game_id) + "?version=" + str(game_version) + "&max=" + str(maximum) + "&ldboard_name=" + str(ldboard_name.percent_encode()) + "&player_name=" + str(player_name.percent_encode()) + "&period_offset=" + str(period_offset)
send_get_request(TopScoreByPlayer, request_url)
return self
func add_to_local_scores(game_result, ld_name="main"):
var local_score = { "score_id": game_result.score_id, "game_id_version" : game_result.game_id + ";" + game_result.game_version, "player_name": game_result.player_name, "score": game_result.score }
local_scores.append(local_score)
#if ld_name == "main":
# TODO: even here, since the main leader board can be customized, we can't just blindly write to the local_scores variable and pull up the scores later
# we need to know what type of leader board it is, or local caching is useless
#local_scores.append(local_score)
#else:
#if ld_name in custom_local_scores:
# TODO: problem: can't just append here - what if it's a highest/latest/accumulator/time-based leaderboard?
# maybe don't use local scores for these special cases? performance?
#custom_local_scores[ld_name].append(local_score)
#else:
#custom_local_scores[ld_name] = [local_score]
SWLogger.debug("local scores: " + str(local_scores))
# metadata, if included should be a dictionary
func persist_score(player_name, score, ldboard_name="main", metadata={}):
# player_name must be present
if player_name == null or player_name == "":
SWLogger.error("ERROR in SilentWolf.Scores.persist_score - please enter a valid player name")
elif typeof(ldboard_name) != TYPE_STRING:
# check that ldboard_name, if present is a String
SWLogger.error("ERROR in ilentWolf.Scores.persist_score - leaderboard name must be a String")
elif typeof(metadata) != TYPE_DICTIONARY:
# check that metadata, if present, is a dictionary
SWLogger.error("ERROR in SilentWolf.Scores.persist_score - metadata must be a dictionary")
else:
PostScore = HTTPRequest.new()
wrPostScore = weakref(PostScore)
if OS.get_name() != "HTML5":
PostScore.set_use_threads(true)
get_tree().get_root().call_deferred("add_child", PostScore)
PostScore.connect("request_completed", self, "_on_PostNewScore_request_completed")
SWLogger.info("Calling SilentWolf backend to post new score...")
var game_id = SilentWolf.config.game_id
var game_version = SilentWolf.config.game_version
var score_uuid = UUID.generate_uuid_v4()
score_id = score_uuid
var payload = {
"score_id" : score_id,
"player_name" : player_name,
"game_id": game_id,
"game_version": game_version,
"score": score,
"ldboard_name": ldboard_name
}
print("!metadata.empty(): " + str(!metadata.empty()))
if !metadata.empty():
print("metadata: " + str(metadata))
payload["metadata"] = metadata
SWLogger.debug("payload: " + str(payload))
# also add to local scores
add_to_local_scores(payload)
var request_url = "https://api.silentwolf.com/post_new_score"
send_post_request(PostScore, request_url, payload)
return self
# Deletes all your scores for your game and version
# Scores are permanently deleted, no going back!
func wipe_leaderboard(ldboard_name='main'):
WipeLeaderboard = HTTPRequest.new()
wrWipeLeaderboard = weakref(WipeLeaderboard)
if OS.get_name() != "HTML5":
WipeLeaderboard.set_use_threads(true)
get_tree().get_root().call_deferred("add_child", WipeLeaderboard)
WipeLeaderboard.connect("request_completed", self, "_on_WipeLeaderboard_request_completed")
SWLogger.info("Calling SilentWolf backend to wipe leaderboard...")
var game_id = SilentWolf.config.game_id
var game_version = SilentWolf.config.game_version
var payload = { "game_id": game_id, "game_version": game_version, "ldboard_name": ldboard_name }
var request_url = "https://api.silentwolf.com/wipe_leaderboard"
send_post_request(WipeLeaderboard, request_url, payload)
return self
func delete_score(score_id):
DeleteScore = HTTPRequest.new()
wrDeleteScore = weakref(DeleteScore)
if OS.get_name() != "HTML5":
DeleteScore.set_use_threads(true)
get_tree().get_root().call_deferred("add_child", DeleteScore)
DeleteScore.connect("request_completed", self, "_on_DeleteScore_request_completed")
SWLogger.info("Calling SilentWolf to delete a score")
var game_id = SilentWolf.config.game_id
var game_version = SilentWolf.config.game_version
var request_url = "https://api.silentwolf.com/delete_score?game_id=" + str(game_id) + "&game_version=" + str(game_version) + "&score_id=" + str(score_id)
send_get_request(DeleteScore, request_url)
return self
func _on_GetScoresByPlayer_request_completed(result, response_code, headers, body):
SWLogger.info("GetScoresByPlayer request completed")
var status_check = CommonErrors.check_status_code(response_code)
#print("client status: " + str(HighScores.get_http_client_status()))
#HighScores.queue_free()
SilentWolf.free_request(wrScoresByPlayer, ScoresByPlayer)
SWLogger.debug("response code: " + str(response_code))
SWLogger.debug("response headers: " + str(headers))
SWLogger.debug("response body: " + str(body.get_string_from_utf8()))
if status_check:
var json = JSON.parse(body.get_string_from_utf8())
print("json: " + str(json))
var response = json.result
if response == null:
SWLogger.error("No data returned in GetScoresByPlayer response. Leaderboard may be empty")
emit_signal("sw_player_scores_received", 'No Leaderboard found', scores)
elif "message" in response.keys() and response.message == "Forbidden":
SWLogger.error("You are not authorized to call the SilentWolf API - check your API key configuration: https://silentwolf.com/leaderboard")
else:
SWLogger.info("SilentWolf get scores by player success")
if "top_scores" in response:
player_scores = response.top_scores
SWLogger.debug("scores: " + str(scores))
var ld_name = response.ld_name
#print("ld_name: " + str(ld_name))
var ld_config = response.ld_config
var player_name = response.player_name
#print("latest_scores: " + str(leaderboards))
emit_signal("sw_player_scores_received", player_scores)
func _on_GetTopScoreByPlayer_request_completed(result, response_code, headers, body):
SWLogger.info("GetTopScoreByPlayer request completed")
var status_check = CommonErrors.check_status_code(response_code)
SilentWolf.free_request(wrTopScoreByPlayer, TopScoreByPlayer)
SWLogger.debug("response code: " + str(response_code))
SWLogger.debug("response headers: " + str(headers))
SWLogger.debug("response body: " + str(body.get_string_from_utf8()))
if status_check:
var json = JSON.parse(body.get_string_from_utf8())
print("json: " + str(json))
var response = json.result
if response == null:
SWLogger.error("No data returned in GetTopScoreByPlayer response. There was a problem getting the response from the backend.")
emit_signal("sw_player_scores_received", 'No Leaderboard found', scores)
elif "message" in response.keys() and response.message == "Forbidden":
SWLogger.error("You are not authorized to call the SilentWolf API - check your API key configuration: https://silentwolf.com/leaderboard")
else:
SWLogger.info("SilentWolf get top score by player success")
if "top_score" in response:
print("top score from response: " + str(response.top_score))
if response.top_score == {}:
player_top_score = {}
else:
player_top_score = response.top_score
SWLogger.debug("top score: " + str(player_top_score))
var ld_name = response.ld_name
#print("ld_name: " + str(ld_name))
var ld_config = response.ld_config
var player_name = response.player_name
#print("latest_scores: " + str(leaderboards))
emit_signal("sw_top_player_score_received", player_top_score)
func _on_GetHighScores_request_completed(result, response_code, headers, body):
SWLogger.info("GetHighScores request completed")
var status_check = CommonErrors.check_status_code(response_code)
#print("client status: " + str(HighScores.get_http_client_status()))
#HighScores.queue_free()
SilentWolf.free_request(wrHighScores, HighScores)
SWLogger.debug("response code: " + str(response_code))
SWLogger.debug("response headers: " + str(headers))
SWLogger.debug("response body: " + str(body.get_string_from_utf8()))
if status_check:
var json = JSON.parse(body.get_string_from_utf8())
var response = json.result
if response == null:
SWLogger.error("No data returned in GetHighScores response. Leaderboard may be empty")
emit_signal("sw_scores_received", 'No Leaderboard found', scores)
emit_signal("scores_received", scores)
elif "message" in response.keys() and response.message == "Forbidden":
SWLogger.error("You are not authorized to call the SilentWolf API - check your API key configuration: https://silentwolf.com/leaderboard")
else:
SWLogger.info("SilentWolf get high score success")
if "top_scores" in response:
scores = response.top_scores
SWLogger.debug("scores: " + str(scores))
var ld_name = response.ld_name
#print("ld_name: " + str(ld_name))
var ld_config = response.ld_config
#print("ld_config: " + str(ld_config))
if "period_offset" in response:
var period_offset = str(response["period_offset"])
leaderboards_past_periods[ld_name + ";" + period_offset] = scores
else:
leaderboards[ld_name] = scores
ldboard_config[ld_name] = ld_config
#print("latest_scores: " + str(leaderboards))
emit_signal("sw_scores_received", ld_name, scores)
emit_signal("scores_received", scores)
#var retries = 0
#request_timer.stop()
func _on_DeleteScore_request_completed(result, response_code, headers, body):
SWLogger.info("DeleteScore request completed")
var status_check = CommonErrors.check_status_code(response_code)
SilentWolf.free_request(wrDeleteScore, DeleteScore)
SWLogger.debug("response headers: " + str(response_code))
SWLogger.debug("response headers: " + str(headers))
SWLogger.debug("response body: " + str(body.get_string_from_utf8()))
if status_check:
var json = JSON.parse(body.get_string_from_utf8())
var response = json.result
if "message" in response.keys() and response.message == "Forbidden":
SWLogger.error("You are not authorized to call the SilentWolf API - check your API key configuration: https://silentwolf.com/leaderboard")
else:
SWLogger.info("SilentWolf delete score success")
emit_signal("sw_score_deleted")
func _on_PostNewScore_request_completed(result, response_code, headers, body):
SWLogger.info("PostNewScore request completed")
var status_check = CommonErrors.check_status_code(response_code)
#PostScore.queue_free()
SilentWolf.free_request(wrPostScore, PostScore)
SWLogger.debug("response headers: " + str(response_code))
SWLogger.debug("response headers: " + str(headers))
SWLogger.debug("response body: " + str(body.get_string_from_utf8()))
if status_check:
var json = JSON.parse(body.get_string_from_utf8())
var response = json.result
if "message" in response.keys() and response.message == "Forbidden":
SWLogger.error("You are not authorized to call the SilentWolf API - check your API key configuration: https://silentwolf.com/leaderboard")
else:
SWLogger.info("SilentWolf post score success: " + str(response_code))
if "score_id" in response:
emit_signal("sw_score_posted", response["score_id"])
else:
emit_signal("sw_score_posted")
emit_signal("score_posted")
func _on_GetScorePosition_request_completed(result, response_code, headers, body):
SWLogger.info("GetScorePosition request completed")
var status_check = CommonErrors.check_status_code(response_code)
#ScorePosition.queue_free()
SilentWolf.free_request(wrScorePosition, ScorePosition)
SWLogger.debug("response headers: " + str(response_code))
SWLogger.debug("response headers: " + str(headers))
SWLogger.debug("response body: " + str(body.get_string_from_utf8()))
if status_check:
var json = JSON.parse(body.get_string_from_utf8())
var response = json.result
if "message" in response.keys() and response.message == "Forbidden":
SWLogger.error("You are not authorized to call the SilentWolf API - check your API key configuration: https://silentwolf.com/leaderboard")
else:
SWLogger.info("SilentWolf find score position success.")
position = int(response.position)
emit_signal("sw_position_received", position)
emit_signal("position_received", position)
func _on_ScoresAround_request_completed(result, response_code, headers, body):
SWLogger.info("ScoresAround request completed")
var status_check = CommonErrors.check_status_code(response_code)
SilentWolf.free_request(wrScoresAround, ScoresAround)
SWLogger.debug("response headers: " + str(response_code))
SWLogger.debug("response headers: " + str(headers))
SWLogger.debug("response body: " + str(body.get_string_from_utf8()))
if status_check:
var json = JSON.parse(body.get_string_from_utf8())
var response = json.result
if "message" in response.keys() and response.message == "Forbidden":
SWLogger.error("You are not authorized to call the SilentWolf API - check your API key configuration: https://silentwolf.com/leaderboard")
else:
SWLogger.info("SilentWolf get scores around success")
if "scores_above" in response:
scores_above = response.scores_above
scores_below = response.scores_below
var ld_name = response.ld_name
#print("ld_name: " + str(ld_name))
var ld_config = response.ld_config
#print("ld_config: " + str(ld_config))
ldboard_config[ld_name] = ld_config
if "score_position" in response:
position = response.score_position
emit_signal("sw_scores_around_received", scores_above, scores_below, position)
func _on_WipeLeaderboard_request_completed(result, response_code, headers, body):
SWLogger.info("WipeLeaderboard request completed")
var status_check = CommonErrors.check_status_code(response_code)
#WipeLeaderboard.queue_free()
SilentWolf.free_request(wrWipeLeaderboard, WipeLeaderboard)
SWLogger.debug("response headers: " + str(response_code))
SWLogger.debug("response headers: " + str(headers))
SWLogger.debug("response body: " + str(body.get_string_from_utf8()))
if status_check:
var json = JSON.parse(body.get_string_from_utf8())
var response = json.result
if "message" in response.keys() and response.message == "Forbidden":
SWLogger.error("You are not authorized to call the SilentWolf API - check your API key configuration: https://silentwolf.com/leaderboard")
else:
SWLogger.info("SilentWolf wipe leaderboard success.")
emit_signal("sw_leaderboard_wiped")
func send_get_request(http_node, request_url):
var headers = ["x-api-key: " + SilentWolf.config.api_key, "x-sw-plugin-version: " + SilentWolf.version]
if !http_node.is_inside_tree():
yield(get_tree().create_timer(0.01), "timeout")
SWLogger.debug("Method: GET")
SWLogger.debug("request_url: " + str(request_url))
SWLogger.debug("headers: " + str(headers))
http_node.request(request_url, headers)
func send_post_request(http_node, request_url, payload):
var headers = [
"Content-Type: application/json",
"x-api-key: " + SilentWolf.config.api_key,
"x-sw-plugin-version: " + SilentWolf.version
]
if "post_new_score" in request_url:
SWLogger.info("We're doing a post score")
var player_name = payload["player_name"]
var player_score = payload["score"]
var timestamp = OS.get_system_time_msecs()
var to_be_hashed = [player_name, player_score, timestamp]
SWLogger.debug("send_post_request to_be_hashed: " + str(to_be_hashed))
var hashed = SWHashing.hash_values(to_be_hashed)
SWLogger.debug("send_post_request hashed: " + str(hashed))
headers.append("x-sw-act-tmst: " + str(timestamp))
headers.append("x-sw-act-dig: " + hashed)
var use_ssl = true
if !http_node.is_inside_tree():
yield(get_tree().create_timer(0.01), "timeout")
var query = JSON.print(payload)
SWLogger.info("Method: POST")
SWLogger.info("request_url: " + str(request_url))
SWLogger.info("headers: " + str(headers))
SWLogger.info("query: " + str(query))
http_node.request(request_url, headers, use_ssl, HTTPClient.METHOD_POST, query)

Binary file not shown.

View file

@ -1,178 +0,0 @@
extends Node
const version = "0.6.20"
var godot_version = Engine.get_version_info().string
const SWHashing = preload("res://addons/silent_wolf/utils/SWHashing.gd")
onready var Auth = Node.new()
onready var Scores = Node.new()
onready var Players = Node.new()
onready var Multiplayer = Node.new()
#
# SILENTWOLF CONFIG: THE CONFIG VARIABLES BELOW WILL BE OVERRIDED THE
# NEXT TIME YOU UPDATE YOUR PLUGIN!
#
# As a best practice, use SilentWolf.configure from your game's
# code instead to set the SilentWolf configuration.
#
# See https://silentwolf.com for more details
#
var config = {
"api_key": "FmKF4gtm0Z2RbUAEU62kZ2OZoYLj4PYOURAPIKEY",
"game_id": "YOURGAMEID",
"game_version": "0.0.0",
"log_level": 0
}
var scores_config = {
"open_scene_on_close": "res://scenes/Splash.tscn"
}
var auth_config = {
"redirect_to_scene": "res://scenes/Splash.tscn",
"login_scene": "res://addons/silent_wolf/Auth/Login.tscn",
"email_confirmation_scene": "res://addons/silent_wolf/Auth/ConfirmEmail.tscn",
"reset_password_scene": "res://addons/silent_wolf/Auth/ResetPassword.tscn",
"session_duration_seconds": 0,
"saved_session_expiration_days": 30
}
var SWLogger = load("res://addons/silent_wolf/utils/SWLogger.gd")
var auth_script = load("res://addons/silent_wolf/Auth/Auth.gd")
var scores_script = load("res://addons/silent_wolf/Scores/Scores.gd")
var players_script = load("res://addons/silent_wolf/Players/Players.gd")
var multiplayer_script = load("res://addons/silent_wolf/Multiplayer/Multiplayer.gd")
func _init():
print("SW Init timestamp: " + str(OS.get_time()))
func _ready():
# The following line would keep SilentWolf working even if the game tree is paused.
#pause_mode = Node.PAUSE_MODE_PROCESS
print("SW ready start timestamp: " + str(OS.get_time()))
Auth.set_script(auth_script)
add_child(Auth)
Scores.set_script(scores_script)
add_child(Scores)
Players.set_script(players_script)
add_child(Players)
Multiplayer.set_script(multiplayer_script)
add_child(Multiplayer)
print("SW ready end timestamp: " + str(OS.get_time()))
func configure(json_config):
config = json_config
func configure_api_key(api_key):
config.apiKey = api_key
func configure_game_id(game_id):
config.game_id = game_id
func configure_game_version(game_version):
config.game_version = game_version
##################################################################
# Log levels:
# 0 - error (only log errors)
# 1 - info (log errors and the main actions taken by the SilentWolf plugin) - default setting
# 2 - debug (detailed logs, including the above and much more, to be used when investigating a problem). This shouldn't be the default setting in production.
##################################################################
func configure_log_level(log_level):
config.log_level = log_level
func configure_scores(json_scores_config):
scores_config = json_scores_config
func configure_scores_open_scene_on_close(scene):
scores_config.open_scene_on_close = scene
func configure_auth(json_auth_config):
auth_config = json_auth_config
func configure_auth_redirect_to_scene(scene):
auth_config.open_scene_on_close = scene
func configure_auth_session_duration(duration):
auth_config.session_duration = duration
func free_request(weak_ref, object):
if (weak_ref.get_ref()):
object.queue_free()
func send_get_request(http_node, request_url):
var headers = [
"x-api-key: " + SilentWolf.config.api_key,
"x-sw-game-id: " + SilentWolf.config.game_id,
"x-sw-plugin-version: " + SilentWolf.version,
"x-sw-godot-version: " + godot_version
]
if !http_node.is_inside_tree():
yield(get_tree().create_timer(0.01), "timeout")
SWLogger.debug("Method: GET")
SWLogger.debug("request_url: " + str(request_url))
SWLogger.debug("headers: " + str(headers))
http_node.request(request_url, headers)
func send_post_request(http_node, request_url, payload):
var headers = [
"Content-Type: application/json",
"x-api-key: " + SilentWolf.config.api_key,
"x-sw-game-id: " + SilentWolf.config.game_id,
"x-sw-plugin-version: " + SilentWolf.version,
"x-sw-godot-version: " + godot_version
]
# TODO: this os specific to post_new_score - should be made generic
# or make a section for each type of post request with inetgrity check
# (e.g. also push player data)
if "post_new_score" in request_url:
SWLogger.info("We're doing a post score")
var player_name = payload["player_name"]
var player_score = payload["score"]
var timestamp = OS.get_system_time_msecs()
var to_be_hashed = [player_name, player_score, timestamp]
SWLogger.debug("send_post_request to_be_hashed: " + str(to_be_hashed))
var hashed = SWHashing.hash_values(to_be_hashed)
SWLogger.debug("send_post_request hashed: " + str(hashed))
headers.append("x-sw-act-tmst: " + str(timestamp))
headers.append("x-sw-act-dig: " + hashed)
var use_ssl = true
if !http_node.is_inside_tree():
yield(get_tree().create_timer(0.01), "timeout")
var query = JSON.print(payload)
SWLogger.info("Method: POST")
SWLogger.info("request_url: " + str(request_url))
SWLogger.info("headers: " + str(headers))
SWLogger.info("query: " + str(query))
http_node.request(request_url, headers, use_ssl, HTTPClient.METHOD_POST, query)
func check_auth_ready():
if !Auth:
yield(get_tree().create_timer(0.01), "timeout")
func check_scores_ready():
if !Scores:
yield(get_tree().create_timer(0.01), "timeout")
func check_players_ready():
if !Players:
yield(get_tree().create_timer(0.01), "timeout")
func check_multiplayer_ready():
if !Multiplayer:
yield(get_tree().create_timer(0.01), "timeout")
func check_sw_ready():
if !Auth or !Scores or !Players or !Multiplayer:
yield(get_tree().create_timer(0.01), "timeout")

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 813 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View file

@ -1,17 +0,0 @@
extends Node
const SWLogger = preload("res://addons/silent_wolf/utils/SWLogger.gd")
func _ready():
pass
static func check_status_code(status_code):
SWLogger.debug("status_code: " + str(status_code))
var check_ok = true
if status_code == 0:
no_connection_error()
check_ok = false
return check_ok
static func no_connection_error():
SWLogger.error("Godot couldn't connect to the SilentWolf backend. There are several reasons why this might happen. See https://silentwolf.com/troubleshooting for more details. If the problem persists you can reach out to us at support@silentwolf.com")

View file

@ -1,49 +0,0 @@
[gd_scene load_steps=6 format=2]
[ext_resource path="res://addons/silent_wolf/assets/fonts/Comfortaa-Bold.ttf" type="DynamicFontData" id=1]
[sub_resource type="StyleBoxFlat" id=1]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.831373, 0.415686, 0.415686, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="StyleBoxFlat" id=2]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.831373, 0.415686, 0.415686, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="StyleBoxFlat" id=3]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.666667, 0.223529, 0.223529, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="DynamicFont" id=4]
size = 64
font_data = ExtResource( 1 )
[node name="SWButton" type="Button"]
margin_right = 12.0
margin_bottom = 20.0
custom_styles/hover = SubResource( 1 )
custom_styles/pressed = SubResource( 2 )
custom_styles/normal = SubResource( 3 )
custom_fonts/font = SubResource( 4 )
text = "Sample text"

Binary file not shown.

View file

@ -1,87 +0,0 @@
tool
extends Node2D
const ScoreItem = preload("res://addons/silent_wolf/Scores/ScoreItem.tscn")
const SWLogger = preload("res://addons/silent_wolf/utils/SWLogger.gd")
var list_index = 0
var ld_name = "main"
func _ready():
var scores = []
if ld_name in SilentWolf.Scores.leaderboards:
scores = SilentWolf.Scores.leaderboards[ld_name]
if len(scores) > 0:
render_board(scores)
else:
# use a signal to notify when the high scores have been returned, and show a "loading" animation until it's the case...
add_loading_scores_message()
yield(SilentWolf.Scores.get_high_scores(0), "sw_scores_received")
hide_message()
render_board(SilentWolf.Scores.scores)
func render_board(scores):
if !scores:
add_no_scores_message()
else:
if len(scores) > 1 and scores[0].score > scores[-1].score:
scores.invert()
for i in range(len(scores)):
var score = scores[i]
add_item(score.player_name, str(int(score.score)))
#var time = display_time(scores[i].score)
#add_item(score.player_name, time)
#func display_time(time_in_millis):
# var minutes = int(floor(time_in_millis / 60000))
# var seconds = int(floor((time_in_millis % 60000) / 1000))
# var millis = time_in_millis - minutes*60000 - seconds*1000
# var displayable_time = str(minutes) + ":" + str(seconds) + ":" + str(millis)
# return displayable_time
func reverse_order(scores):
var reverted_scores = scores
if len(scores) > 1 and scores[0].score > scores[-1].score:
reverted_scores = scores.invert()
return reverted_scores
func sort_by_score(a, b):
if a.score > b.score:
return true;
else:
if a.score < b.score:
return false;
else:
return true;
func add_item(player_name, score):
var item = ScoreItem.instance()
list_index += 1
item.get_node("PlayerName").text = str(list_index) + str(". ") + player_name
item.get_node("Score").text = score
item.margin_top = list_index * 100
$"Board/HighScores/ScoreItemContainer".add_child(item)
func add_no_scores_message():
var item = $"Board/MessageContainer/TextMessage"
item.text = "No scores yet!"
$"Board/MessageContainer".show()
item.margin_top = 135
func add_loading_scores_message():
var item = $"Board/MessageContainer/TextMessage"
item.text = "Loading scores..."
$"Board/MessageContainer".show()
item.margin_top = 135
func hide_message():
$"Board/MessageContainer".hide()
func _on_CloseButton_pressed():
var scene_name = SilentWolf.scores_config.open_scene_on_close
print("scene_name: " + str(scene_name))
get_tree().change_scene(scene_name)

View file

@ -1,119 +0,0 @@
[gd_scene load_steps=12 format=2]
[ext_resource path="res://addons/silent_wolf/assets/fonts/Comfortaa-Bold.ttf" type="DynamicFontData" id=2]
[ext_resource path="res://addons/silent_wolf/Scores/assets/fonts/Comfortaa-Bold.ttf" type="DynamicFontData" id=3]
[ext_resource path="res://addons/silent_wolf/common/SWButton.tscn" type="PackedScene" id=4]
[ext_resource path="res://addons/silent_wolf/examples/CustomLeaderboards/ReverseLeaderboard.gd" type="Script" id=5]
[sub_resource type="DynamicFont" id=1]
size = 76
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=7]
size = 32
font_data = ExtResource( 2 )
[sub_resource type="Theme" id=2]
[sub_resource type="StyleBoxFlat" id=3]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.831373, 0.415686, 0.415686, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="StyleBoxFlat" id=4]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.831373, 0.415686, 0.415686, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="StyleBoxFlat" id=5]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.666667, 0.223529, 0.223529, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="DynamicFont" id=6]
size = 64
font_data = ExtResource( 2 )
[node name="ReverseLeaderboard" type="Node2D"]
script = ExtResource( 5 )
[node name="Board" type="VBoxContainer" parent="."]
margin_left = 20.0
margin_top = 20.0
margin_right = 1884.0
margin_bottom = 1071.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="TitleContainer" type="CenterContainer" parent="Board"]
margin_right = 1864.0
margin_bottom = 85.0
[node name="Label" type="Label" parent="Board/TitleContainer"]
margin_left = 502.0
margin_right = 1362.0
margin_bottom = 85.0
custom_fonts/font = SubResource( 1 )
text = "Reverse Leaderboard"
[node name="MessageContainer" type="CenterContainer" parent="Board"]
visible = false
margin_top = 89.0
margin_right = 1864.0
margin_bottom = 126.0
[node name="TextMessage" type="Label" parent="Board/MessageContainer"]
margin_left = 789.0
margin_right = 1075.0
margin_bottom = 37.0
custom_fonts/font = SubResource( 7 )
text = "Loading scores..."
valign = 1
[node name="HighScores" type="CenterContainer" parent="Board"]
margin_top = 89.0
margin_right = 1864.0
margin_bottom = 189.0
rect_min_size = Vector2( 0, 100 )
theme = SubResource( 2 )
[node name="ScoreItemContainer" type="VBoxContainer" parent="Board/HighScores"]
margin_left = 932.0
margin_top = 50.0
margin_right = 932.0
margin_bottom = 50.0
[node name="CloseButtonContainer" type="CenterContainer" parent="Board"]
margin_top = 193.0
margin_right = 1864.0
margin_bottom = 311.0
[node name="CloseButton" parent="Board/CloseButtonContainer" instance=ExtResource( 4 )]
margin_left = 582.0
margin_right = 1281.0
margin_bottom = 118.0
custom_styles/hover = SubResource( 3 )
custom_styles/pressed = SubResource( 4 )
custom_styles/normal = SubResource( 5 )
custom_fonts/font = SubResource( 6 )
text = "Close Leaderboard"
[connection signal="pressed" from="Board/CloseButtonContainer/CloseButton" to="." method="_on_CloseButton_pressed"]

View file

@ -1,14 +0,0 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://addons/silent_wolf/Scores/ScoreItem.tscn" type="PackedScene" id=1]
[sub_resource type="StyleBoxFlat" id=1]
bg_color = Color( 0.831373, 0.415686, 0.415686, 1 )
[node name="ScoreItem" index="0" instance=ExtResource( 1 )]
rect_min_size = Vector2( 434, 64 )
custom_styles/panel = SubResource( 1 )
[node name="Score" parent="." index="1"]
margin_left = 360.0
margin_right = 427.0

View file

@ -1,81 +0,0 @@
extends Node2D
const ScoreItem = preload("SmallScoreItem.tscn")
const SWLogger = preload("res://addons/silent_wolf/utils/SWLogger.gd")
var ld_names = ["Weekly", "Monthly", "main"]
func _ready():
SilentWolf.Scores.connect("sw_scores_received", self, "_on_scores_received")
#var scores = SilentWolf.Scores.scores
add_loading_scores_message()
SilentWolf.Scores.get_high_scores(10, "main")
# the other leaderboard scores will be called once the main call in finished
# (see signal connected above and _on_scores_received function below)
# when all the scores are loaded the leaderboard scene can be opened
func render_boards(leaderboards):
#print("leaderboards: " + str(leaderboards))
var board_number = 0
for board in leaderboards:
var list_index = 1
#print("ld name: " + str(ld_names[board_number]))
#print("ld scores: " + str(board))
for score in board:
add_item(ld_names[board_number], score.player_name, str(int(score.score)), list_index)
list_index += 1
board_number += 1
func add_item(ld_name, player_name, score, list_index):
var item = ScoreItem.instance()
item.get_node("PlayerName").text = str(list_index) + str(". ") + player_name
item.get_node("Score").text = score
item.margin_top = list_index * 100
get_node("MainContainer/Boards/" + ld_name + "/HighScores/ScoreItemContainer").add_child(item)
func add_no_scores_message():
var item = $"MainContainer/MessageContainer/TextMessage"
item.text = "No scores yet!"
$"MainContainer/MessageContainer".show()
item.margin_top = 135
func add_loading_scores_message():
var item = $"MainContainer/MessageContainer/TextMessage"
item.text = "Loading scores..."
$"MainContainer/MessageContainer".show()
item.margin_top = 135
func hide_message():
$"MainContainer/MessageContainer".hide()
func _on_CloseButton_pressed():
var scene_name = SilentWolf.scores_config.open_scene_on_close
SWLogger.info("Closing SilentWolf leaderboard, switching to scene: " + str(scene_name))
#global.reset()
get_tree().change_scene(scene_name)
func _on_scores_received(ld_name, scores):
if ld_name == "main":
SilentWolf.Scores.get_high_scores(10, "Weekly")
#SilentWolf.Scores.get_high_scores(10, "Weekly", -1)
elif ld_name == "Weekly":
SilentWolf.Scores.get_high_scores(10, "Monthly")
else:
#print("SilentWolf.Scores.leaderboards: " + str(SilentWolf.Scores.leaderboards))
var ld_scores = []
for i in [0, 1, 2]:
if ld_names[i] in SilentWolf.Scores.leaderboards:
ld_scores.append(SilentWolf.Scores.leaderboards[ld_names[i]])
#elif (ld_names[i] + ";-1") in SilentWolf.Scores.leaderboards_past_periods:
# ld_scores.append(SilentWolf.Scores.leaderboards_past_periods[(ld_names[i] + ";-1")])
else:
ld_scores.append([])
hide_message()
render_boards(ld_scores)

View file

@ -1,228 +0,0 @@
[gd_scene load_steps=13 format=2]
[ext_resource path="res://addons/silent_wolf/assets/fonts/Comfortaa-Bold.ttf" type="DynamicFontData" id=2]
[ext_resource path="res://addons/silent_wolf/Scores/assets/fonts/Comfortaa-Bold.ttf" type="DynamicFontData" id=3]
[ext_resource path="res://addons/silent_wolf/common/SWButton.tscn" type="PackedScene" id=4]
[ext_resource path="res://addons/silent_wolf/examples/CustomLeaderboards/TimeBasedLboards.gd" type="Script" id=5]
[sub_resource type="DynamicFont" id=1]
size = 120
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=2]
size = 76
font_data = ExtResource( 3 )
[sub_resource type="Theme" id=3]
[sub_resource type="DynamicFont" id=8]
size = 32
font_data = ExtResource( 2 )
[sub_resource type="StyleBoxFlat" id=4]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.831373, 0.415686, 0.415686, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="StyleBoxFlat" id=5]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.831373, 0.415686, 0.415686, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="StyleBoxFlat" id=6]
content_margin_left = 23.0
content_margin_right = 23.0
content_margin_top = 23.0
content_margin_bottom = 23.0
bg_color = Color( 0.666667, 0.223529, 0.223529, 1 )
corner_radius_top_left = 20
corner_radius_top_right = 20
corner_radius_bottom_right = 20
corner_radius_bottom_left = 20
[sub_resource type="DynamicFont" id=7]
size = 64
font_data = ExtResource( 2 )
[node name="TimeBasedLBoards" type="Node2D"]
script = ExtResource( 5 )
[node name="MainContainer" type="VBoxContainer" parent="."]
margin_right = 1918.0
margin_bottom = 1078.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="TitleContainer" type="CenterContainer" parent="MainContainer"]
margin_right = 1918.0
margin_bottom = 135.0
[node name="Label2" type="Label" parent="MainContainer/TitleContainer"]
margin_left = 540.0
margin_right = 1378.0
margin_bottom = 135.0
custom_fonts/font = SubResource( 1 )
text = "Leaderboard"
[node name="Boards" type="HBoxContainer" parent="MainContainer"]
margin_top = 139.0
margin_right = 1918.0
margin_bottom = 328.0
custom_constants/separation = 160
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Weekly" type="VBoxContainer" parent="MainContainer/Boards"]
margin_right = 532.0
margin_bottom = 189.0
size_flags_horizontal = 3
__meta__ = {
"_edit_use_anchors_": false
}
[node name="TitleContainer" type="CenterContainer" parent="MainContainer/Boards/Weekly"]
margin_right = 532.0
margin_bottom = 85.0
[node name="Label" type="Label" parent="MainContainer/Boards/Weekly/TitleContainer"]
margin_left = 76.0
margin_right = 456.0
margin_bottom = 85.0
size_flags_horizontal = 4
custom_fonts/font = SubResource( 2 )
text = "This week"
[node name="HighScores" type="CenterContainer" parent="MainContainer/Boards/Weekly"]
margin_left = 266.0
margin_top = 89.0
margin_right = 266.0
margin_bottom = 189.0
rect_min_size = Vector2( 0, 100 )
size_flags_horizontal = 4
theme = SubResource( 3 )
[node name="ScoreItemContainer" type="VBoxContainer" parent="MainContainer/Boards/Weekly/HighScores"]
margin_top = 50.0
margin_bottom = 50.0
[node name="Monthly" type="VBoxContainer" parent="MainContainer/Boards"]
margin_left = 692.0
margin_right = 1224.0
margin_bottom = 189.0
size_flags_horizontal = 3
__meta__ = {
"_edit_use_anchors_": false
}
[node name="TitleContainer" type="CenterContainer" parent="MainContainer/Boards/Monthly"]
margin_right = 532.0
margin_bottom = 85.0
[node name="Label" type="Label" parent="MainContainer/Boards/Monthly/TitleContainer"]
margin_left = 44.0
margin_right = 488.0
margin_bottom = 85.0
custom_fonts/font = SubResource( 2 )
text = "This month"
[node name="HighScores" type="CenterContainer" parent="MainContainer/Boards/Monthly"]
margin_left = 266.0
margin_top = 89.0
margin_right = 266.0
margin_bottom = 189.0
rect_min_size = Vector2( 0, 100 )
size_flags_horizontal = 4
theme = SubResource( 3 )
[node name="ScoreItemContainer" type="VBoxContainer" parent="MainContainer/Boards/Monthly/HighScores"]
margin_top = 50.0
margin_bottom = 50.0
[node name="main" type="VBoxContainer" parent="MainContainer/Boards"]
margin_left = 1384.0
margin_right = 1918.0
margin_bottom = 189.0
size_flags_horizontal = 3
__meta__ = {
"_edit_use_anchors_": false
}
[node name="TitleContainer" type="CenterContainer" parent="MainContainer/Boards/main"]
margin_right = 534.0
margin_bottom = 85.0
[node name="Label" type="Label" parent="MainContainer/Boards/main/TitleContainer"]
margin_left = 121.0
margin_right = 413.0
margin_bottom = 85.0
custom_fonts/font = SubResource( 2 )
text = "All time"
align = 1
[node name="HighScores" type="CenterContainer" parent="MainContainer/Boards/main"]
margin_left = 267.0
margin_top = 89.0
margin_right = 267.0
margin_bottom = 189.0
rect_min_size = Vector2( 0, 100 )
size_flags_horizontal = 4
theme = SubResource( 3 )
[node name="ScoreItemContainer" type="VBoxContainer" parent="MainContainer/Boards/main/HighScores"]
margin_top = 50.0
margin_bottom = 50.0
[node name="MessageContainer" type="CenterContainer" parent="MainContainer"]
visible = false
margin_left = 1144.0
margin_top = 228.0
margin_right = 3008.0
margin_bottom = 265.0
[node name="TextMessage" type="Label" parent="MainContainer/MessageContainer"]
margin_left = 789.0
margin_right = 1075.0
margin_bottom = 37.0
custom_fonts/font = SubResource( 8 )
text = "Loading scores..."
valign = 1
[node name="CenterContainer" type="CenterContainer" parent="MainContainer"]
margin_top = 332.0
margin_right = 1918.0
margin_bottom = 450.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="CloseButtonContainer" type="CenterContainer" parent="MainContainer/CenterContainer"]
margin_left = 609.0
margin_right = 1308.0
margin_bottom = 118.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="CloseButton" parent="MainContainer/CenterContainer/CloseButtonContainer" instance=ExtResource( 4 )]
margin_right = 699.0
margin_bottom = 118.0
custom_styles/hover = SubResource( 4 )
custom_styles/pressed = SubResource( 5 )
custom_styles/normal = SubResource( 6 )
custom_fonts/font = SubResource( 7 )
text = "Close Leaderboard"
[connection signal="pressed" from="MainContainer/CenterContainer/CloseButtonContainer/CloseButton" to="." method="_on_CloseButton_pressed"]

View file

@ -1,7 +0,0 @@
[plugin]
name="Silent Wolf plugin"
description="Backend services for Godot Engine."
author="Brass Harpooner"
version="0.6.6"
script="silent_wolf.gd"

View file

@ -1,8 +0,0 @@
tool
extends EditorPlugin
func _enter_tree():
add_autoload_singleton("SilentWolf", "res://addons/silent_wolf/SilentWolf.gd")
func _exit_tree():
remove_autoload_singleton("SilentWolf")

View file

@ -1,9 +0,0 @@
extends Node
static func hash_values(values: Array) -> String:
var to_be_hashed = ""
for value in values:
to_be_hashed = to_be_hashed + str(value)
var hashed = to_be_hashed.md5_text()
#print("Computed hashed: " + str(hashed))
return hashed

View file

@ -1,45 +0,0 @@
extends Node
const SWLogger = preload("res://addons/silent_wolf/utils/SWLogger.gd")
# Retrieves data stored as JSON in local storage
# example path: "user://swsession.save"
# store lookup (not logged in player name) and validator in local file
static func save_data(path: String, data: Dictionary, debug_message: String='Saving data to file in local storage: ') -> void:
var local_file = File.new()
local_file.open(path, File.WRITE)
SWLogger.debug(debug_message + str(data))
local_file.store_line(to_json(data))
local_file.close()
static func remove_data(path: String, debug_message: String='Removing data from file in local storage: ') -> void:
var local_file = File.new()
local_file.open(path, File.WRITE)
var data = {}
SWLogger.debug(debug_message + str(data))
local_file.store_line(to_json(data))
local_file.close()
static func does_file_exist(path: String, file: File=null) -> bool:
var local_file = file
if local_file == null:
local_file = File.new()
return local_file.file_exists(path)
static func get_data(path: String) -> Dictionary:
var local_file = File.new()
var return_data = null
if does_file_exist(path, local_file):
local_file.open(path, File.READ)
var data = parse_json(local_file.get_as_text())
if typeof(data) == TYPE_DICTIONARY:
return_data = data
else:
SWLogger.debug("Invalid data in local storage")
else:
SWLogger.debug("Could not find any data at: " + str(path))
return return_data

View file

@ -1,21 +0,0 @@
extends Node
static func get_log_level():
var log_level = 1
if SilentWolf.config.has('log_level'):
log_level = SilentWolf.config.log_level
else:
error("Couldn't find SilentWolf.config.log_level, defaulting to 1")
return log_level
static func error(text):
printerr(str(text))
push_error(str(text))
static func info(text):
if get_log_level() > 0:
print(str(text))
static func debug(text):
if get_log_level() > 1:
print(str(text))

View file

@ -1,47 +0,0 @@
static func getRandomInt(max_value):
randomize()
return randi() % max_value
static func randomBytes(n):
var r = []
for index in range(0, n):
r.append(getRandomInt(256))
return r
static func uuidbin():
var b = randomBytes(16)
b[6] = (b[6] & 0x0f) | 0x40
b[8] = (b[8] & 0x3f) | 0x80
return b
static func generate_uuid_v4():
var b = uuidbin()
var low = '%02x%02x%02x%02x' % [b[0], b[1], b[2], b[3]]
var mid = '%02x%02x' % [b[4], b[5]]
var hi = '%02x%02x' % [b[6], b[7]]
var clock = '%02x%02x' % [b[8], b[9]]
var node = '%02x%02x%02x%02x%02x%02x' % [b[10], b[11], b[12], b[13], b[14], b[15]]
return '%s-%s-%s-%s-%s' % [low, mid, hi, clock, node]
# argument must be of type string!
static func is_uuid(test_string):
# if length of string is 36 and contains exactly 4 dashes, it's a UUID
return test_string.length() == 36 and test_string.count("-") == 4
# MIT License
# Copyright (c) 2018 Xavier Sellier
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.

View file

@ -14,16 +14,6 @@ _global_script_classes=[ {
"language": "GDScript",
"path": "res://src/actor/Actor.gd"
}, {
"base": "Node",
"class": "AsepriteImportData",
"language": "GDScript",
"path": "res://addons/aseprite_importer/classes/AsepriteImportData.gd"
}, {
"base": "Node",
"class": "AsepriteImporter",
"language": "GDScript",
"path": "res://addons/aseprite_importer/classes/AsepriteImporter.gd"
}, {
"base": "Actor",
"class": "Box",
"language": "GDScript",
@ -34,11 +24,6 @@ _global_script_classes=[ {
"language": "GDScript",
"path": "res://src/class/EaseMover.gd"
}, {
"base": "Node",
"class": "EditorTheme",
"language": "GDScript",
"path": "res://addons/aseprite_importer/classes/EditorTheme.gd"
}, {
"base": "Actor",
"class": "Exit",
"language": "GDScript",
@ -81,11 +66,8 @@ _global_script_classes=[ {
} ]
_global_script_class_icons={
"Actor": "",
"AsepriteImportData": "",
"AsepriteImporter": "",
"Box": "",
"EaseMover": "",
"EditorTheme": "",
"Exit": "",
"Key": "",
"Menu": "",
@ -141,7 +123,7 @@ search_in_file_extensions=PoolStringArray( "gd", "gdshader", "shader", "tscn" )
[editor_plugins]
enabled=PoolStringArray( "res://addons/aseprite_importer/plugin.cfg", "res://addons/silent_wolf/plugin.cfg" )
enabled=PoolStringArray( "res://addons/silent_wolf/plugin.cfg" )
[global]

View file

@ -1,57 +0,0 @@
extends Node
onready var api_file = load("silent_wolf_api_key.gd")
var api_key := ""
var is_online := false
var scores := {}
signal new_score
func _ready():
is_online = api_file is Script
if !is_online: return
print("Leaderboard Shared.username: ", Shared.username)
api_key = api_file.source_code.strip_edges().replace('"', "")
SilentWolf.configure({
"api_key": api_key,
"game_id": "TinyCrate",
"game_version": "1.0.0",
"log_level": 1})
SilentWolf.configure_scores({"open_scene_on_close": "res://scenes/MainPage.tscn"})
yield(get_tree(), "idle_frame")
SilentWolf.Scores.persist_score(Shared.username, 1)
func refresh_scores():
if !is_online: return
var a = Shared.maps.duplicate()
var notes = []
for i in a:
notes.append(i + "-note")
a.append_array(notes)
for i in a:
yield(SilentWolf.Scores.get_high_scores(0, i), "sw_scores_received")
if SilentWolf.Scores.leaderboards.has(i):
var s = SilentWolf.Scores.leaderboards[i]
scores[i] = s
func refresh_score(map_name):
if !is_online: return
yield(SilentWolf.Scores.get_high_scores(0, map_name), "sw_scores_received")
if SilentWolf.Scores.leaderboards.has(map_name):
var s = SilentWolf.Scores.leaderboards[map_name]
scores[map_name] = s
emit_signal("new_score")
#print(s)
func submit_score(board_name, score, _username := Shared.username):
if !is_online: return
SilentWolf.Scores.persist_score(_username , score, board_name)

View file

@ -464,7 +464,7 @@ func win():
print("map complete")
Leaderboard.submit_score(m, -map_frame)
#Leaderboard.submit_score(m, -map_frame)
wipe_scene(level_select_path)
@ -502,8 +502,8 @@ func die():
else:
s["die"] += 1
Leaderboard.submit_score("death", 1)
Leaderboard.submit_score("death", 1, map_name)
#Leaderboard.submit_score("death", 1)
#Leaderboard.submit_score("death", 1, map_name)
print("you died")
func pick_player_colors():

View file

@ -63,8 +63,8 @@ var blink_clock := 0.0
var blink_count = 10
func _ready():
Leaderboard.connect("new_score", self, "new_score")
SilentWolf.Scores.connect("sw_scores_received", self, "new_score")
#Leaderboard.connect("new_score", self, "new_score")
#SilentWolf.Scores.connect("sw_scores_received", self, "new_score")
is_faster_note = Shared.is_faster_note
is_faster = is_faster_note or Shared.is_faster
@ -276,7 +276,7 @@ func refresh_score(var map_name : String = current_map):
write_score()
if !last_refresh.has(map_name) or last_refresh[map_name] == 0:
Leaderboard.refresh_score(map_name)
#Leaderboard.refresh_score(map_name)
print(map_name, " FRESH FRESH FRESH FRESH FRESH FRESH FRESH FRESH FRESH FRESH FRESH FRESH FRESH FRESH FRESH ")
last_refresh[map_name] = refresh_wait
@ -287,27 +287,14 @@ func write_score():
var map_name = current_map + ("-note" if show_score == 2 else "")
var t = ""
var count = 0
if Leaderboard.is_online:
if Leaderboard.scores.has(map_name):
var s = Leaderboard.scores[map_name]
if s.empty():
t = "no data!"
else:
for i in s:
t += Shared.time_to_string(-int(i["score"])) + " " + str(i["player_name"]) + "\n"
count += 1
if count > 9 : break
else:
t = "loading..."
if Shared.replays.has(map_name):
for i in Shared.replays[map_name]:
if i.has("frames"):
t += Shared.time_to_string(int(i["frames"])) + "\n"
count += 1
if count > 9 : break
else:
if Shared.replays.has(map_name):
for i in Shared.replays[map_name]:
if i.has("frames"):
t += Shared.time_to_string(int(i["frames"])) + "\n"
count += 1
if count > 9 : break
else:
t = "NO DATA!"
t = "NO DATA!"
score_list.text = t