XML tuner, config presets, fix reset bind saving bug

This commit is contained in:
MeowcaTheoRange 2024-12-01 01:36:12 -06:00
parent 1dab54da0f
commit 7e44e3d08a
39 changed files with 1706 additions and 73 deletions

View file

@ -1,34 +1,14 @@
[remap]
importer="texture"
type="CompressedTexture2D"
importer="image"
type="Image"
uid="uid://b6x537wsl3853"
path="res://.godot/imported/BOYFRIEND.png-39cdb7ee73d5290fc66317ae894c5c49.ctex"
metadata={
"vram_texture": false
}
path="res://.godot/imported/BOYFRIEND.png-39cdb7ee73d5290fc66317ae894c5c49.image"
[deps]
source_file="res://assets/BOYFRIEND.png"
dest_files=["res://.godot/imported/BOYFRIEND.png-39cdb7ee73d5290fc66317ae894c5c49.ctex"]
dest_files=["res://.godot/imported/BOYFRIEND.png-39cdb7ee73d5290fc66317ae894c5c49.image"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://eudnts7c3nxy"
path="res://.godot/imported/background_checker.png-9bc2f2d6b47432d820b975ab35c9e5e1.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/background_checker.png"
dest_files=["res://.godot/imported/background_checker.png-9bc2f2d6b47432d820b975ab35c9e5e1.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

4
assets/config/bg.tres Normal file
View file

@ -0,0 +1,4 @@
[gd_resource type="StyleBoxFlat" format=3 uid="uid://bdkv45xc5lotp"]
[resource]
bg_color = Color(0.12549, 0.12549, 0.12549, 1)

View file

@ -0,0 +1,9 @@
[gd_resource type="LabelSettings" load_steps=2 format=3 uid="uid://55elphqx3dqw"]
[ext_resource type="FontFile" uid="uid://ce5fs0ro7kp8r" path="res://assets/fonts/Lexend.ttf" id="1_3s1q8"]
[resource]
font = ExtResource("1_3s1q8")
font_size = 14
shadow_color = Color(0, 0, 0, 1)
shadow_offset = Vector2(0, 1)

BIN
assets/icons/arrow_down.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dbyhyqbmk8nip"
path="res://.godot/imported/arrow_down.png-c93ce13fc34e8f54091b090433da4319.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/icons/arrow_down.png"
dest_files=["res://.godot/imported/arrow_down.png-c93ce13fc34e8f54091b090433da4319.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

BIN
assets/icons/arrow_up.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bb6o3ff20sfcr"
path="res://.godot/imported/arrow_up.png-9447ca0e8f31ae4bf4a5d58081e09faa.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/icons/arrow_up.png"
dest_files=["res://.godot/imported/arrow_up.png-9447ca0e8f31ae4bf4a5d58081e09faa.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

13
assets/icons/checker.tres Normal file
View file

@ -0,0 +1,13 @@
[gd_resource type="GradientTexture2D" load_steps=2 format=3 uid="uid://c3sqmkn1m8f8"]
[sub_resource type="Gradient" id="Gradient_7tml3"]
interpolation_mode = 1
offsets = PackedFloat32Array(0, 0.5)
metadata/_snap_enabled = true
[resource]
gradient = SubResource("Gradient_7tml3")
width = 2
height = 2
fill_to = Vector2(1, 1)
repeat = 1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 289 B

After

Width:  |  Height:  |  Size: 436 B

BIN
assets/icons/frame_open.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dinhxs3byoi3s"
path="res://.godot/imported/frame_open.png-10f0b7b27982187741fba18357825080.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/icons/frame_open.png"
dest_files=["res://.godot/imported/frame_open.png-10f0b7b27982187741fba18357825080.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c5qf8o3yefmij"
path="res://.godot/imported/frames_open.png-642496cc6c7b46c1d0dd7b48beb9f71b.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/icons/frames_open.png"
dest_files=["res://.godot/imported/frames_open.png-642496cc6c7b46c1d0dd7b48beb9f71b.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

BIN
assets/icons/preset_use.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://m546urtgoxrk"
path="res://.godot/imported/preset_use.png-b19662e013e899f02e64516b13961eb7.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/icons/preset_use.png"
dest_files=["res://.godot/imported/preset_use.png-b19662e013e899f02e64516b13961eb7.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

3
assets/test.tres Normal file
View file

@ -0,0 +1,3 @@
[gd_resource type="Image" format=3 uid="uid://s7gvwrccwxv"]
[resource]

View file

@ -21,7 +21,7 @@ script_export_mode=2
custom_template/debug=""
custom_template/release=""
debug/export_console_wrapper=1
binary_format/embed_pck=true
binary_format/embed_pck=false
texture_format/s3tc_bptc=true
texture_format/etc2_astc=false
binary_format/architecture="x86_64"

View file

@ -11,7 +11,7 @@ config_version=5
[application]
config/name="FunkPanion"
config/version="0.9.2"
config/version="0.10.0"
run/main_scene="res://scenes/main.tscn"
run/disable_stderr=true
config/use_custom_user_dir=true
@ -104,3 +104,4 @@ mod_snap_coarse={
renderer/rendering_method="gl_compatibility"
renderer/rendering_method.mobile="gl_compatibility"
environment/defaults/default_clear_color=Color(0.188235, 0.188235, 0.188235, 1)

View file

@ -1,18 +1,17 @@
[gd_scene load_steps=13 format=3 uid="uid://b0m4v3w4sqrfs"]
[gd_scene load_steps=14 format=3 uid="uid://b0m4v3w4sqrfs"]
[ext_resource type="Script" path="res://scripts/config/config_window.gd" id="1_3y2tp"]
[ext_resource type="StyleBox" uid="uid://bdkv45xc5lotp" path="res://assets/config/bg.tres" id="1_kscu5"]
[ext_resource type="LabelSettings" uid="uid://2iu8q0tylumo" path="res://assets/config/header_bold.tres" id="1_lbm3n"]
[ext_resource type="FontFile" uid="uid://ce5fs0ro7kp8r" path="res://assets/fonts/Lexend.ttf" id="2_bbfo5"]
[ext_resource type="Script" path="res://scripts/config/form_handler.gd" id="2_ouac2"]
[ext_resource type="FontFile" uid="uid://4e3o2ds5xy7p" path="res://assets/fonts/MatSymOut.ttf" id="2_pm82g"]
[ext_resource type="LabelSettings" uid="uid://c2s3eclr25ots" path="res://assets/config/body.tres" id="3_gn7vd"]
[ext_resource type="FontFile" uid="uid://c6ck52v6qotm" path="res://assets/fonts/B_Lexend.ttf" id="3_qguou"]
[ext_resource type="Script" path="res://scripts/config/config_presets.gd" id="6_th0jy"]
[ext_resource type="FontVariation" uid="uid://d1apfvux6r82v" path="res://assets/config/button_icon.tres" id="8_qusr6"]
[ext_resource type="Script" path="res://scripts/config/open_file_dialog.gd" id="9_1o6y4"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_3ax2o"]
bg_color = Color(0.12549, 0.12549, 0.12549, 1)
[sub_resource type="LabelSettings" id="LabelSettings_gk6wd"]
font = ExtResource("3_qguou")
font_size = 32
@ -30,7 +29,7 @@ grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_styles/panel = SubResource("StyleBoxFlat_3ax2o")
theme_override_styles/panel = ExtResource("1_kscu5")
follow_focus = true
horizontal_scroll_mode = 0
script = ExtResource("1_3y2tp")
@ -71,15 +70,14 @@ size_flags_horizontal = 3
text = "Config"
label_settings = SubResource("LabelSettings_gk6wd")
[node name="Reset" type="Button" parent="MarginContainer/Form/Header"]
[node name="Button" type="Button" parent="MarginContainer/Form/Header"]
custom_minimum_size = Vector2(40, 40)
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
tooltip_text = "Reset your configuration."
tooltip_text = "Manage your configuration presets."
theme_override_fonts/font = ExtResource("2_pm82g")
theme_override_font_sizes/font_size = 24
text = "reset_settings"
text = "stack_hexagon"
script = ExtResource("6_th0jy")
[node name="OSD and UI" type="VBoxContainer" parent="MarginContainer/Form"]
layout_mode = 2
@ -602,4 +600,3 @@ select_mode = 1
[connection signal="pressed" from="MarginContainer/Form/Header/BackButton" to="." method="_on_back_button_pressed"]
[connection signal="pressed" from="MarginContainer/Form/Header/BackButton" to="MarginContainer/Form" method="_on_back_button_pressed"]
[connection signal="pressed" from="MarginContainer/Form/Header/Reset" to="." method="_on_reset_pressed"]

View file

@ -0,0 +1,83 @@
[gd_scene load_steps=5 format=3 uid="uid://b7a6e4l7mhqmt"]
[ext_resource type="StyleBox" uid="uid://bdkv45xc5lotp" path="res://assets/config/bg.tres" id="1_no4mj"]
[ext_resource type="Script" path="res://scripts/config/config_window_presets.gd" id="2_yjvpe"]
[ext_resource type="FontFile" uid="uid://4e3o2ds5xy7p" path="res://assets/fonts/MatSymOut.ttf" id="3_bra08"]
[ext_resource type="LabelSettings" uid="uid://2iu8q0tylumo" path="res://assets/config/header_bold.tres" id="4_mvauf"]
[node name="ScrollContainer" type="ScrollContainer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
theme_override_styles/panel = ExtResource("1_no4mj")
horizontal_scroll_mode = 0
vertical_scroll_mode = 0
script = ExtResource("2_yjvpe")
[node name="MarginContainer" type="MarginContainer" parent="."]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/margin_left = 8
theme_override_constants/margin_top = 8
theme_override_constants/margin_right = 8
theme_override_constants/margin_bottom = 8
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
layout_mode = 2
[node name="Header" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="CloseButton" type="Button" parent="MarginContainer/VBoxContainer/Header"]
custom_minimum_size = Vector2(40, 40)
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
theme_override_fonts/font = ExtResource("3_bra08")
theme_override_font_sizes/font_size = 24
text = "close"
flat = true
[node name="Header" type="Label" parent="MarginContainer/VBoxContainer/Header"]
layout_mode = 2
size_flags_horizontal = 3
text = "Presets"
label_settings = ExtResource("4_mvauf")
[node name="ResetButton" type="Button" parent="MarginContainer/VBoxContainer/Header"]
custom_minimum_size = Vector2(40, 40)
layout_mode = 2
tooltip_text = "Reset your current configuration."
theme_override_fonts/font = ExtResource("3_bra08")
theme_override_font_sizes/font_size = 24
text = "reset_settings"
[node name="Tree" type="Tree" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
columns = 2
column_titles_visible = true
hide_folding = true
enable_recursive_folding = false
hide_root = true
select_mode = 1
scroll_horizontal_enabled = false
[node name="AddNew" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="name" type="LineEdit" parent="MarginContainer/VBoxContainer/AddNew"]
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "Preset Name"
[node name="switch" type="Button" parent="MarginContainer/VBoxContainer/AddNew"]
layout_mode = 2
text = "Save Preset"
[connection signal="pressed" from="MarginContainer/VBoxContainer/Header/CloseButton" to="." method="_on_close_button_pressed"]
[connection signal="pressed" from="MarginContainer/VBoxContainer/Header/ResetButton" to="." method="_on_reset_button_pressed"]

View file

@ -1,17 +1,15 @@
[gd_scene load_steps=11 format=3 uid="uid://d0hedjnfwtu0"]
[gd_scene load_steps=10 format=3 uid="uid://d0hedjnfwtu0"]
[ext_resource type="Script" path="res://scripts/window.gd" id="1_6nwqw"]
[ext_resource type="Script" path="res://scripts/animator.gd" id="2_hov7x"]
[ext_resource type="PackedScene" uid="uid://qnb6qrsgpbwc" path="res://scenes/osd.tscn" id="2_m7sf8"]
[ext_resource type="AudioStream" uid="uid://bj6b8h153h1bn" path="res://assets/beep.ogg" id="3_tvnah"]
[ext_resource type="AudioStream" uid="uid://8ij8fr2uqb65" path="res://assets/tap.wav" id="3_xnh3p"]
[ext_resource type="Texture2D" uid="uid://b6x537wsl3853" path="res://assets/BOYFRIEND.png" id="4_fraqq"]
[ext_resource type="Theme" uid="uid://e62vyqlhf1v1" path="res://osd.tres" id="7_bx315"]
[ext_resource type="FontFile" uid="uid://4e3o2ds5xy7p" path="res://assets/fonts/MatSymOut.ttf" id="7_q7jy6"]
[ext_resource type="Script" path="res://scripts/menu.gd" id="8_3lc1r"]
[sub_resource type="AtlasTexture" id="AtlasTexture_y0egr"]
atlas = ExtResource("4_fraqq")
region = Rect2(0, 0, 1, 1)
[node name="Control" type="ColorRect"]
@ -77,8 +75,10 @@ theme = ExtResource("7_bx315")
theme_override_fonts/font = ExtResource("7_q7jy6")
theme_override_font_sizes/font_size = 32
text = "menu"
item_count = 2
item_count = 3
popup/item_0/text = "Config"
popup/item_1/text = "Exit"
popup/item_1/text = "XML Tuner"
popup/item_1/id = 1
popup/item_2/text = "Exit"
popup/item_2/id = 2
script = ExtResource("8_3lc1r")

477
scenes/xml_editor.tscn Normal file
View file

@ -0,0 +1,477 @@
[gd_scene load_steps=12 format=3 uid="uid://d0w4cbu1jgqnx"]
[ext_resource type="Script" path="res://scripts/xmle/xml_editor_window.gd" id="1_gspou"]
[ext_resource type="StyleBox" uid="uid://bdkv45xc5lotp" path="res://assets/config/bg.tres" id="1_j0s65"]
[ext_resource type="LabelSettings" uid="uid://c2s3eclr25ots" path="res://assets/config/body.tres" id="2_m7ywi"]
[ext_resource type="LabelSettings" uid="uid://55elphqx3dqw" path="res://assets/config/section_header.tres" id="2_mi1pb"]
[ext_resource type="Script" path="res://scripts/xmle/load.gd" id="3_0whnd"]
[ext_resource type="Texture2D" uid="uid://eudnts7c3nxy" path="res://assets/background_checker.png" id="3_06msg"]
[ext_resource type="Script" path="res://scripts/xmle/form_handler.gd" id="3_aomrl"]
[ext_resource type="Script" path="res://scripts/xmle/save.gd" id="4_ye3qr"]
[sub_resource type="AtlasTexture" id="AtlasTexture_k1djj"]
[sub_resource type="AtlasTexture" id="AtlasTexture_3qyg2"]
[sub_resource type="AtlasTexture" id="AtlasTexture_iddor"]
[node name="PanelContainer" type="PanelContainer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_styles/panel = ExtResource("1_j0s65")
script = ExtResource("1_gspou")
[node name="VBoxContainer" type="VBoxContainer" parent="."]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/separation = 0
[node name="Menu" type="MarginContainer" parent="VBoxContainer"]
z_index = 1
layout_mode = 2
theme_override_constants/margin_left = 8
theme_override_constants/margin_top = 4
theme_override_constants/margin_right = 8
theme_override_constants/margin_bottom = 4
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/Menu"]
layout_mode = 2
theme_override_constants/separation = 8
[node name="Load" type="MenuButton" parent="VBoxContainer/Menu/HBoxContainer"]
layout_mode = 2
text = "Load..."
item_count = 2
popup/item_0/text = "Load XML"
popup/item_1/text = "Load reference image"
popup/item_1/id = 1
script = ExtResource("3_0whnd")
[node name="Edit" type="MenuButton" parent="VBoxContainer/Menu/HBoxContainer"]
visible = false
layout_mode = 2
text = "Edit..."
item_count = 1
popup/item_0/text = "Image atlas wizard"
popup/item_0/id = 1
[node name="Save" type="Button" parent="VBoxContainer/Menu/HBoxContainer"]
layout_mode = 2
text = "Save"
flat = true
script = ExtResource("4_ye3qr")
[node name="Spacer" type="Control" parent="VBoxContainer/Menu/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
[node name="Exit" type="Button" parent="VBoxContainer/Menu/HBoxContainer"]
layout_mode = 2
text = "Exit"
flat = true
[node name="Editor" type="MarginContainer" parent="VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
theme_override_constants/margin_left = 8
theme_override_constants/margin_top = 8
theme_override_constants/margin_right = 8
theme_override_constants/margin_bottom = 8
script = ExtResource("3_aomrl")
[node name="HSplitContainer" type="HSplitContainer" parent="VBoxContainer/Editor"]
layout_mode = 2
size_flags_vertical = 3
theme_override_constants/separation = 0
theme_override_constants/autohide = 0
[node name="VSplitContainer" type="VSplitContainer" parent="VBoxContainer/Editor/HSplitContainer"]
layout_mode = 2
theme_override_constants/separation = 0
theme_override_constants/autohide = 0
[node name="Frames" type="VBoxContainer" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer"]
layout_mode = 2
size_flags_vertical = 3
[node name="Label" type="Label" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer/Frames"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 1
tooltip_text = "How big the character's sprites are allowed to get.
To FunkPanion, this is the window's size.
To Sparrow, Flixel, and FNF, this is the \"frame_\" properties on each frame."
mouse_filter = 0
text = "Frames"
label_settings = ExtResource("2_mi1pb")
vertical_alignment = 1
[node name="Tree" type="Tree" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer/Frames"]
custom_minimum_size = Vector2(200, 50)
layout_mode = 2
size_flags_vertical = 3
columns = 2
allow_search = false
hide_folding = true
enable_recursive_folding = false
select_mode = 1
scroll_horizontal_enabled = false
[node name="align_all" type="HBoxContainer" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer/Frames"]
custom_minimum_size = Vector2(0, 32)
layout_mode = 2
[node name="preset" type="MenuButton" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer/Frames/align_all"]
layout_mode = 2
size_flags_horizontal = 3
tooltip_text = "Align all frames in the animation."
text = "Align All..."
flat = false
item_count = 9
popup/item_0/text = "Top Left"
popup/item_1/text = "Top"
popup/item_1/id = 1
popup/item_2/text = "Top Right"
popup/item_2/id = 2
popup/item_3/text = "Left"
popup/item_3/id = 3
popup/item_4/text = "Center"
popup/item_4/id = 4
popup/item_5/text = "Right"
popup/item_5/id = 5
popup/item_6/text = "Bottom Left"
popup/item_6/id = 6
popup/item_7/text = "Bottom"
popup/item_7/id = 7
popup/item_8/text = "Bottom Right"
popup/item_8/id = 8
[node name="autocrop" type="Button" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer/Frames/align_all"]
layout_mode = 2
size_flags_horizontal = 3
tooltip_text = "Crop out transparent pixels in all frames of the animation."
text = "Autocrop All"
[node name="oskin" type="HBoxContainer" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer/Frames"]
custom_minimum_size = Vector2(0, 32)
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer/Frames/oskin"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 1
tooltip_text = "How many frames each animation will have."
mouse_filter = 0
text = "Onion Skin"
label_settings = ExtResource("2_m7ywi")
vertical_alignment = 1
[node name="prev" type="CheckBox" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer/Frames/oskin"]
layout_mode = 2
text = "Previous"
[node name="next" type="CheckBox" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer/Frames/oskin"]
layout_mode = 2
text = "Next"
[node name="Animations" type="VBoxContainer" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer"]
custom_minimum_size = Vector2(0, 100)
layout_mode = 2
size_flags_vertical = 3
[node name="Label" type="Label" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer/Animations"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 1
tooltip_text = "How big the character's sprites are allowed to get.
To FunkPanion, this is the window's size.
To Sparrow, Flixel, and FNF, this is the \"frame_\" properties on each frame."
mouse_filter = 0
text = "Animations"
label_settings = ExtResource("2_mi1pb")
vertical_alignment = 1
[node name="Tree" type="Tree" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer/Animations"]
layout_mode = 2
size_flags_vertical = 3
allow_search = false
hide_folding = true
enable_recursive_folding = false
hide_root = true
select_mode = 1
scroll_horizontal_enabled = false
[node name="AddNew" type="HBoxContainer" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer/Animations"]
layout_mode = 2
[node name="name" type="LineEdit" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer/Animations/AddNew"]
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "Animation Name"
[node name="switch" type="Button" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer/Animations/AddNew"]
layout_mode = 2
text = "Add"
[node name="sprite_size" type="HBoxContainer" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer/Animations"]
custom_minimum_size = Vector2(0, 32)
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer/Animations/sprite_size"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 1
tooltip_text = "How big the character's sprites are allowed to get.
To FunkPanion, this is the window's size.
To Sparrow, Flixel, and FNF, this is the \"frame_width/height\" properties on each frame."
mouse_filter = 0
text = "Sprite Size"
label_settings = ExtResource("2_m7ywi")
vertical_alignment = 1
[node name="value_w" type="SpinBox" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer/Animations/sprite_size"]
layout_mode = 2
size_flags_horizontal = 8
size_flags_vertical = 4
max_value = 8192.0
value = 500.0
select_all_on_focus = true
[node name="value_h" type="SpinBox" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer/Animations/sprite_size"]
layout_mode = 2
size_flags_horizontal = 8
size_flags_vertical = 4
max_value = 8192.0
value = 500.0
select_all_on_focus = true
[node name="frame_count" type="HBoxContainer" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer/Animations"]
custom_minimum_size = Vector2(0, 32)
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer/Animations/frame_count"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 1
tooltip_text = "How many frames each animation will have."
mouse_filter = 0
text = "Frame Count"
label_settings = ExtResource("2_m7ywi")
vertical_alignment = 1
[node name="value" type="SpinBox" parent="VBoxContainer/Editor/HSplitContainer/VSplitContainer/Animations/frame_count"]
layout_mode = 2
size_flags_horizontal = 8
size_flags_vertical = 4
max_value = 240.0
value = 10.0
select_all_on_focus = true
[node name="Region" type="VBoxContainer" parent="VBoxContainer/Editor/HSplitContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/Editor/HSplitContainer/Region"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 1
tooltip_text = "How big the character's sprites are allowed to get.
To FunkPanion, this is the window's size.
To Sparrow, Flixel, and FNF, this is the \"frame_\" properties on each frame."
mouse_filter = 0
text = "Region"
label_settings = ExtResource("2_mi1pb")
vertical_alignment = 2
[node name="RegionView" type="SubViewportContainer" parent="VBoxContainer/Editor/HSplitContainer/Region"]
custom_minimum_size = Vector2(250, 250)
layout_mode = 2
size_flags_vertical = 3
stretch = true
[node name="Viewport" type="SubViewport" parent="VBoxContainer/Editor/HSplitContainer/Region/RegionView"]
disable_3d = true
handle_input_locally = false
size = Vector2i(363, 298)
render_target_update_mode = 4
[node name="BG" type="TextureRect" parent="VBoxContainer/Editor/HSplitContainer/Region/RegionView/Viewport"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource("3_06msg")
stretch_mode = 1
[node name="ReferenceRect" type="ReferenceRect" parent="VBoxContainer/Editor/HSplitContainer/Region/RegionView/Viewport"]
border_width = 2.0
editor_only = false
[node name="OSPrevCharacter" type="TextureRect" parent="VBoxContainer/Editor/HSplitContainer/Region/RegionView/Viewport/ReferenceRect"]
visible = false
modulate = Color(0, 0, 1, 0.501961)
layout_mode = 0
offset_right = 1.0
offset_bottom = 1.0
size_flags_horizontal = 4
size_flags_vertical = 4
texture = SubResource("AtlasTexture_k1djj")
stretch_mode = 2
[node name="Character" type="TextureRect" parent="VBoxContainer/Editor/HSplitContainer/Region/RegionView/Viewport/ReferenceRect"]
layout_mode = 0
offset_right = 1.0
offset_bottom = 1.0
size_flags_horizontal = 4
size_flags_vertical = 4
texture = SubResource("AtlasTexture_3qyg2")
stretch_mode = 2
[node name="OSNextCharacter" type="TextureRect" parent="VBoxContainer/Editor/HSplitContainer/Region/RegionView/Viewport/ReferenceRect"]
visible = false
modulate = Color(1, 0, 0, 0.501961)
layout_mode = 0
offset_right = 1.0
offset_bottom = 1.0
size_flags_horizontal = 4
size_flags_vertical = 4
texture = SubResource("AtlasTexture_iddor")
stretch_mode = 2
[node name="ReferenceRect" type="ReferenceRect" parent="VBoxContainer/Editor/HSplitContainer/Region/RegionView/Viewport/ReferenceRect"]
layout_mode = 0
border_color = Color(0, 0, 1, 1)
border_width = 2.0
editor_only = false
[node name="Controls" type="VBoxContainer" parent="VBoxContainer/Editor/HSplitContainer/Region"]
layout_mode = 2
[node name="region_pos" type="HBoxContainer" parent="VBoxContainer/Editor/HSplitContainer/Region/Controls"]
custom_minimum_size = Vector2(0, 32)
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/Editor/HSplitContainer/Region/Controls/region_pos"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 1
tooltip_text = "Position of the frame on the spritesheet."
mouse_filter = 0
text = "Region Position"
label_settings = ExtResource("2_m7ywi")
vertical_alignment = 1
[node name="value_w" type="SpinBox" parent="VBoxContainer/Editor/HSplitContainer/Region/Controls/region_pos"]
layout_mode = 2
size_flags_horizontal = 8
size_flags_vertical = 4
max_value = 8192.0
value = 500.0
select_all_on_focus = true
[node name="value_h" type="SpinBox" parent="VBoxContainer/Editor/HSplitContainer/Region/Controls/region_pos"]
layout_mode = 2
size_flags_horizontal = 8
size_flags_vertical = 4
max_value = 8192.0
value = 500.0
select_all_on_focus = true
[node name="region_size" type="HBoxContainer" parent="VBoxContainer/Editor/HSplitContainer/Region/Controls"]
custom_minimum_size = Vector2(0, 32)
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/Editor/HSplitContainer/Region/Controls/region_size"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 1
tooltip_text = "Size of the frame on the spritesheet."
mouse_filter = 0
text = "Region Size"
label_settings = ExtResource("2_m7ywi")
vertical_alignment = 1
[node name="autocrop" type="Button" parent="VBoxContainer/Editor/HSplitContainer/Region/Controls/region_size"]
layout_mode = 2
tooltip_text = "Crop out transparent pixels."
text = "Autocrop"
[node name="value_w" type="SpinBox" parent="VBoxContainer/Editor/HSplitContainer/Region/Controls/region_size"]
layout_mode = 2
size_flags_horizontal = 8
size_flags_vertical = 4
max_value = 8192.0
value = 500.0
select_all_on_focus = true
[node name="value_h" type="SpinBox" parent="VBoxContainer/Editor/HSplitContainer/Region/Controls/region_size"]
layout_mode = 2
size_flags_horizontal = 8
size_flags_vertical = 4
max_value = 8192.0
value = 500.0
select_all_on_focus = true
[node name="sprite_offset" type="HBoxContainer" parent="VBoxContainer/Editor/HSplitContainer/Region/Controls"]
custom_minimum_size = Vector2(0, 32)
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/Editor/HSplitContainer/Region/Controls/sprite_offset"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 1
tooltip_text = "Where the sprite is relative to the character size.
To FunkPanion, this is a margin.
To Sparrow, Flixel, and FNF, this is the inverse of the \"frame_x/y\" properties on each frame."
mouse_filter = 0
text = "Sprite Offset"
label_settings = ExtResource("2_m7ywi")
vertical_alignment = 1
[node name="preset" type="MenuButton" parent="VBoxContainer/Editor/HSplitContainer/Region/Controls/sprite_offset"]
layout_mode = 2
text = "Align..."
item_count = 9
popup/item_0/text = "Top Left"
popup/item_1/text = "Top"
popup/item_1/id = 1
popup/item_2/text = "Top Right"
popup/item_2/id = 2
popup/item_3/text = "Left"
popup/item_3/id = 3
popup/item_4/text = "Center"
popup/item_4/id = 4
popup/item_5/text = "Right"
popup/item_5/id = 5
popup/item_6/text = "Bottom Left"
popup/item_6/id = 6
popup/item_7/text = "Bottom"
popup/item_7/id = 7
popup/item_8/text = "Bottom Right"
popup/item_8/id = 8
[node name="value_w" type="SpinBox" parent="VBoxContainer/Editor/HSplitContainer/Region/Controls/sprite_offset"]
layout_mode = 2
size_flags_horizontal = 8
size_flags_vertical = 4
max_value = 8192.0
value = 500.0
select_all_on_focus = true
[node name="value_h" type="SpinBox" parent="VBoxContainer/Editor/HSplitContainer/Region/Controls/sprite_offset"]
layout_mode = 2
size_flags_horizontal = 8
size_flags_vertical = 4
max_value = 8192.0
value = 500.0
select_all_on_focus = true
[connection signal="pressed" from="VBoxContainer/Menu/HBoxContainer/Exit" to="." method="_on_exit_pressed"]

136
scenes/xml_wizard.tscn Normal file
View file

@ -0,0 +1,136 @@
[gd_scene load_steps=4 format=3 uid="uid://te4su73iol18"]
[ext_resource type="Texture2D" uid="uid://eudnts7c3nxy" path="res://assets/background_checker.png" id="1_cpi1h"]
[ext_resource type="Script" path="res://scripts/xmle/xml_wizard_window.gd" id="1_xn2dv"]
[sub_resource type="AtlasTexture" id="AtlasTexture_k1kbl"]
region = Rect2(0, 0, 1, 1)
[node name="Control" type="PanelContainer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
script = ExtResource("1_xn2dv")
[node name="MarginContainer" type="MarginContainer" parent="."]
layout_mode = 2
theme_override_constants/margin_left = 8
theme_override_constants/margin_top = 8
theme_override_constants/margin_right = 8
theme_override_constants/margin_bottom = 8
[node name="HSplitContainer" type="HSplitContainer" parent="MarginContainer"]
layout_mode = 2
size_flags_vertical = 3
theme_override_constants/separation = 0
theme_override_constants/autohide = 0
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/HSplitContainer"]
custom_minimum_size = Vector2(200, 0)
layout_mode = 2
theme_override_constants/separation = 8
[node name="AddNew" type="HBoxContainer" parent="MarginContainer/HSplitContainer/VBoxContainer"]
layout_mode = 2
[node name="name" type="LineEdit" parent="MarginContainer/HSplitContainer/VBoxContainer/AddNew"]
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "Animation Name"
[node name="switch" type="Button" parent="MarginContainer/HSplitContainer/VBoxContainer/AddNew"]
layout_mode = 2
text = "Add"
[node name="Tree" type="Tree" parent="MarginContainer/HSplitContainer/VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
allow_search = false
hide_folding = true
enable_recursive_folding = false
hide_root = true
select_mode = 1
scroll_horizontal_enabled = false
[node name="preset" type="MenuButton" parent="MarginContainer/HSplitContainer/VBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
tooltip_text = "Align all frames in the animation."
text = "Align All..."
flat = false
item_count = 9
popup/item_0/text = "Top Left"
popup/item_1/text = "Top"
popup/item_1/id = 1
popup/item_2/text = "Top Right"
popup/item_2/id = 2
popup/item_3/text = "Left"
popup/item_3/id = 3
popup/item_4/text = "Center"
popup/item_4/id = 4
popup/item_5/text = "Right"
popup/item_5/id = 5
popup/item_6/text = "Bottom Left"
popup/item_6/id = 6
popup/item_7/text = "Bottom"
popup/item_7/id = 7
popup/item_8/text = "Bottom Right"
popup/item_8/id = 8
[node name="Region" type="VBoxContainer" parent="MarginContainer/HSplitContainer"]
layout_mode = 2
theme_override_constants/separation = 8
[node name="RegionView" type="SubViewportContainer" parent="MarginContainer/HSplitContainer/Region"]
layout_mode = 2
size_flags_vertical = 3
stretch = true
[node name="Viewport" type="SubViewport" parent="MarginContainer/HSplitContainer/Region/RegionView"]
disable_3d = true
handle_input_locally = false
size = Vector2i(416, 428)
render_target_update_mode = 4
[node name="BG" type="TextureRect" parent="MarginContainer/HSplitContainer/Region/RegionView/Viewport"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource("1_cpi1h")
stretch_mode = 1
[node name="ReferenceRect" type="ReferenceRect" parent="MarginContainer/HSplitContainer/Region/RegionView/Viewport"]
border_width = 2.0
editor_only = false
[node name="Character" type="TextureRect" parent="MarginContainer/HSplitContainer/Region/RegionView/Viewport/ReferenceRect"]
layout_mode = 0
offset_right = 1.0
offset_bottom = 1.0
size_flags_horizontal = 4
size_flags_vertical = 4
texture = SubResource("AtlasTexture_k1kbl")
stretch_mode = 2
[node name="ReferenceRect" type="ReferenceRect" parent="MarginContainer/HSplitContainer/Region/RegionView/Viewport/ReferenceRect"]
layout_mode = 0
border_color = Color(0, 0, 1, 1)
border_width = 2.0
editor_only = false
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/HSplitContainer/Region"]
layout_mode = 2
alignment = 2
[node name="Button" type="Button" parent="MarginContainer/HSplitContainer/Region/HBoxContainer"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
text = "OK"

View file

@ -188,3 +188,10 @@ func format_config() -> Dictionary:
dict.anim_needs_enable = self.anim_needs_enable
dict.anim_binds = self.anim_binds.duplicate(true)
return dict
func save_to_file(file:String) -> void:
var dict = self.format_config()
var config = ConfigFile.new()
for key in dict:
config.set_value("FunkPanion", key, dict[key])
config.save(file)

View file

@ -5,7 +5,6 @@ extends Config
func _ready() -> void:
load_from_file()
bind_keys()
print(InputMap.get_actions())
func bind_keys() -> void:
bind_all_keys(self.bpm_increase, "bpm_increase")
@ -32,24 +31,21 @@ func bind_all_keys(array, action) -> void:
InputMap.action_add_event(action, ev)
func reset_settings() -> void:
var config = ConfigFile.new()
GlobalConfig.clone_config(Config.new())
config.save("user://config.cfg")
bind_keys()
GlobalConfig.save_to_file()
func save_to_file() -> void:
func save_to_file(file:String = "user://config.cfg") -> void:
var dict = self.format_config()
var config = ConfigFile.new()
for key in dict:
config.set_value("FunkPanion", key, dict[key])
config.save("user://config.cfg")
config.save(file)
bind_keys()
func load_from_file() -> void:
func load_from_file(file:String = "user://config.cfg") -> void:
var config = ConfigFile.new()
var err = config.load("user://config.cfg")
var err = config.load(file)
if err != OK:
return

View file

@ -33,7 +33,7 @@ func parse_spritesheet(path):
if not animations.has(frame_name):
animations[frame_name] = []
var array = animations[frame_name]
var frame_data = {}
@ -83,7 +83,7 @@ func get_props_of_animation_frame(anim:String, frameno:int):
margin = Rect2(-frame.frame_pos, frame.frame_size - frame.size)
}
static func load_image(path: String):
static func load_image(path: String) -> Image:
if path.begins_with('res'):
return load(path)
else:
@ -92,10 +92,24 @@ static func load_image(path: String):
print(str("Could not load image at: ",path))
return
var buffer = file.get_buffer(file.get_length())
var image = Image.new()
var image:Image = Image.new()
var error = image.load_png_from_buffer(buffer)
if error != OK:
print(str("Could not load image at: ",path," with error: ",error))
return
var texture = ImageTexture.create_from_image(image)
return texture
return image
static func spritesheet_to_xml(anims:Array, size: Vector2i, imgpath: String):
var xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
xml += "<TextureAtlas imagePath=\"%s\">\n" % imgpath
for animation in anims:
var animation_stack = ""
for frame in animation.frames.size():
var cur_frame = animation.frames[frame]
if cur_frame == null: continue
var frame_id = animation.name + str(frame).pad_zeros(4)
animation_stack += "\t<SubTexture name=\"%s\" x=\"%s\" y=\"%s\" width=\"%s\" height=\"%s\" frameX=\"%s\" frameY=\"%s\" frameWidth=\"%s\" frameHeight=\"%s\" />\n" % \
[ frame_id, cur_frame.pos.x, cur_frame.pos.y, cur_frame.size.x, cur_frame.size.y, -cur_frame.frame_pos.x, -cur_frame.frame_pos.y, size.x, size.y ]
xml += animation_stack
xml += "</TextureAtlas>"
return xml

View file

@ -9,7 +9,7 @@ var active_anims = []
func _ready() -> void:
texture = AtlasTexture.new()
texture.atlas = SpritesheetParser.load_image(GlobalConfig.spritesheet_image)
texture.atlas = ImageTexture.create_from_image(SpritesheetParser.load_image(GlobalConfig.spritesheet_image))
texture.region = Rect2(0, 0, 1, 1)
spritesheet_parser.parse_spritesheet(GlobalConfig.spritesheet_data)

View file

@ -0,0 +1,31 @@
extends Button
var config_presets = preload("res://scenes/config_presets.tscn")
@onready var root = get_tree().root
@onready var form = $"../.."
func _pressed() -> void:
var preset_window = Popup.new()
var cfps = config_presets.instantiate()
cfps.conf_reference = form.temp_config
preset_window.add_child(cfps)
root.add_child(preset_window)
preset_window.popup_centered_ratio()
var close = func():
preset_window.hide()
root.remove_child(preset_window)
preset_window.queue_free()
cfps.queue_free()
cfps.reset.connect(func():
GlobalConfig.reset_settings()
close.call()
get_tree().reload_current_scene()
)
cfps.close.connect(close)
cfps.preset_use.connect(func():
close.call()
get_tree().reload_current_scene()
)

View file

@ -1,31 +1,17 @@
extends ScrollContainer
var main_window
var exiting_to_config = false
var main_window: Window
# Called when the node enters the scene tree for the first time.
func _enter_tree() -> void:
print("enter tree")
main_window = get_tree().root
main_window.borderless = false
main_window.always_on_top = false
main_window.transparent = false
main_window.min_size = Vector2i(640, 480)
main_window.size = Vector2i(640, 480)
main_window.title = "FunkPanion Config"
ProjectSettings.set_setting("display/window/subwindows/embed_subwindows", false)
func _exit_tree() -> void:
if exiting_to_config: return
main_window.borderless = true
main_window.always_on_top = true
main_window.transparent = true
main_window.min_size = Vector2i(100, 100)
ProjectSettings.set_setting("display/window/subwindows/embed_subwindows", true)
func _on_back_button_pressed() -> void:
get_tree().change_scene_to_file("res://scenes/main.tscn")
func _on_reset_pressed() -> void:
GlobalConfig.reset_settings()
exiting_to_config = true
get_tree().reload_current_scene()

View file

@ -0,0 +1,76 @@
extends ScrollContainer
signal reset
signal preset_use
signal close
var dir
var conf_reference:Config
@onready var tree = $"MarginContainer/VBoxContainer/Tree"
var tree_root: TreeItem
@onready var addnew_name = $"MarginContainer/VBoxContainer/AddNew/name"
@onready var addnew_switch = $"MarginContainer/VBoxContainer/AddNew/switch"
@onready var close_icon = load("res://assets/icons/close.png")
@onready var preset_use_icon = load("res://assets/icons/preset_use.png")
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
tree.set_column_title(0, "Name")
tree.set_column_title(1, "Created")
tree_root = tree.create_item()
dir = DirAccess.open("user://presets/")
tree.button_clicked.connect(func(item:TreeItem, column:int, id:int, _mbi:int):
if column == 1:
if id == 0:
GlobalConfig.load_from_file(item.get_metadata(0))
GlobalConfig.save_to_file()
preset_use.emit()
if id == 1:
dir.remove(item.get_metadata(0))
refresh_tree()
)
addnew_switch.pressed.connect(func():
if addnew_name.text.length() > 0 and addnew_name.text.is_valid_filename():
addnew_name.text = addnew_name.text.simplify_path()
if addnew_name.text.get_extension() != "cfg":
addnew_name.text = addnew_name.text.get_basename() + ".cfg"
conf_reference.save_to_file(dir.get_current_dir().path_join(addnew_name.text))
addnew_name.text = ""
refresh_tree()
)
refresh_tree()
func refresh_tree() -> void:
for child in tree_root.get_children():
child.free()
if not dir:
DirAccess.make_dir_absolute("user://presets/")
dir = DirAccess.open("user://presets/")
dir.list_dir_begin()
var file_name = dir.get_next()
while file_name != "":
if file_name.get_extension() == "cfg":
var child:TreeItem = tree.create_item(tree_root)
var abs_file_name = dir.get_current_dir().path_join(file_name)
child.set_cell_mode(0, TreeItem.CELL_MODE_STRING)
child.set_text(0, file_name.get_basename())
var mod_time = FileAccess.get_modified_time(abs_file_name)
child.set_text(1, Time.get_datetime_string_from_unix_time(mod_time, true))
child.add_button(1, preset_use_icon)
child.add_button(1, close_icon)
child.set_metadata(0, abs_file_name)
file_name = dir.get_next()
func _on_close_button_pressed() -> void:
close.emit()
func _on_reset_button_pressed() -> void:
reset.emit()

View file

@ -6,6 +6,8 @@ func _index_pressed(idx: int):
if idx == 0:
get_tree().change_scene_to_file("res://scenes/config.tscn")
elif idx == 1:
get_tree().change_scene_to_file("res://scenes/xml_editor.tscn")
elif idx == 2:
get_tree().quit()
# Called when the node enters the scene tree for the first time.

View file

@ -24,6 +24,16 @@ var character_opacity = 100.0
var numerator = int(GlobalConfig.tempo_numerator)
var change_array = []
func _enter_tree() -> void:
main_window = get_tree().root
main_window.borderless = true
main_window.always_on_top = true
main_window.transparent = true
main_window.min_size = Vector2i(100, 100)
main_window.title = "FunkPanion"
main_window.set_mode(Window.MODE_WINDOWED)
ProjectSettings.set_setting("display/window/subwindows/embed_subwindows", true)
func _ready() -> void:
horiz_align.alignment = GlobalConfig.spritesheet_anchor[0]
vert_align.alignment = GlobalConfig.spritesheet_anchor[1]

View file

@ -0,0 +1,513 @@
extends Node
@onready var anims_tree = $"HSplitContainer/VSplitContainer/Animations"
@onready var frames_tree = $"HSplitContainer/VSplitContainer/Frames"
@onready var region_viewport = $"HSplitContainer/Region/RegionView/Viewport"
@onready var rg_oskin_prev_char = $"HSplitContainer/Region/RegionView/Viewport/ReferenceRect/OSPrevCharacter"
@onready var rg_oskin_next_char = $"HSplitContainer/Region/RegionView/Viewport/ReferenceRect/OSNextCharacter"
@onready var frame_count = $"HSplitContainer/VSplitContainer/Animations/frame_count"
@onready var sprite_size = $"HSplitContainer/VSplitContainer/Animations/sprite_size"
@onready var region_pos = $"HSplitContainer/Region/Controls/region_pos"
@onready var region_size = $"HSplitContainer/Region/Controls/region_size"
@onready var sprite_offset = $"HSplitContainer/Region/Controls/sprite_offset"
@onready var align_all = $"HSplitContainer/VSplitContainer/Frames/align_all"
@onready var oskin = $"HSplitContainer/VSplitContainer/Frames/oskin"
@onready var menu = $"../Menu/HBoxContainer"
@onready var close_icon = load("res://assets/icons/close.png")
@onready var frames_open_icon = load("res://assets/icons/frames_open.png")
@onready var frame_open_icon = load("res://assets/icons/frame_open.png")
@onready var arrow_up_icon = load("res://assets/icons/arrow_up.png")
@onready var arrow_down_icon = load("res://assets/icons/arrow_down.png")
var spritesheet_parser: SpritesheetParser = SpritesheetParser.new()
var preview_image:ImageTexture
var process_image:Image
var spritesheet_animations:Array = []
var spritesheet_size:Vector2i = Vector2i.ZERO
var spritesheet_frames:int = 0
var selected_animation:int = 0
var selected_frame:int = 0
var image_path = GlobalConfig.spritesheet_image
var data_path = GlobalConfig.spritesheet_data
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
var frame:ReferenceRect = region_viewport.get_node("ReferenceRect")
region_viewport.size_changed.connect(func():
frame.position = (region_viewport.size / 2) - Vector2i(frame.size / 2)
)
link_range_to_callable(frame_count, func(val: int):
for animation in spritesheet_animations:
spritesheet_frames = val
if selected_frame >= spritesheet_frames:
selected_frame = spritesheet_frames - 1
animation.frames.resize(spritesheet_frames)
set_frames_tree()
, spritesheet_frames)
link_pos_to_callable_e(sprite_size, func(_val: int):
spritesheet_size = get_vector(sprite_size)
set_region_view()
)
link_pos_to_callable_e(region_pos, func(_val: int):
if ts_dont_change_internal: return
set_property_on_current_frame("pos", get_vector(region_pos))
set_region_view()
)
link_pos_to_callable_e(region_size, func(_val: int):
if ts_dont_change_internal: return
set_property_on_current_frame("size", get_vector(region_size))
set_region_view()
update_current_frame_child()
)
link_pos_to_callable_e(sprite_offset, func(_val: int):
if ts_dont_change_internal: return
set_property_on_current_frame("frame_pos", get_vector(sprite_offset))
set_region_view()
)
var rs_autocrop:Button = region_size.get_node("autocrop")
rs_autocrop.pressed.connect(func():
var pos = get_property_on_current_frame("pos")
var size = get_property_on_current_frame("size")
var cropped_image = process_image.get_region(Rect2i(pos, size))
var flood_fill_result = cropped_image.get_used_rect()
set_property_on_current_frame("pos", flood_fill_result.position + pos)
set_property_on_current_frame("size", flood_fill_result.size)
update_current_frame_child()
set_region_view()
set_three_stooges()
)
var aa_autocrop:Button = align_all.get_node("autocrop")
aa_autocrop.pressed.connect(func():
var cur_anim = spritesheet_animations[selected_animation]
if cur_anim.frames.size() < 1: return
for cur_frame in cur_anim.frames:
if cur_frame == null: continue
var cropped_image = process_image.get_region(Rect2i(cur_frame.pos, cur_frame.size))
var flood_fill_result = cropped_image.get_used_rect()
cur_frame.pos = (flood_fill_result.position + cur_frame.pos).max(cur_frame.pos)
cur_frame.size = flood_fill_result.size.min(cur_frame.size)
set_frames_tree()
set_region_view()
set_three_stooges()
)
var so_preset:MenuButton = sprite_offset.get_node("preset")
var sopre_pop:PopupMenu = so_preset.get_popup()
sopre_pop.index_pressed.connect(func(idx: int):
var frame_size = get_property_on_current_frame("size")
if frame_size == null: return
set_property_on_current_frame("frame_pos", align_to_vector(idx, frame_size, spritesheet_size))
set_region_view()
set_three_stooges()
)
var aa_preset:MenuButton = align_all.get_node("preset")
var aapre_pop:PopupMenu = aa_preset.get_popup()
aapre_pop.index_pressed.connect(func(idx: int):
var cur_anim = spritesheet_animations[selected_animation]
if cur_anim.frames.size() < 1: return
for cur_frame in cur_anim.frames:
if cur_frame == null: continue
cur_frame.frame_pos = align_to_vector(idx, cur_frame.size, spritesheet_size)
set_region_view()
set_three_stooges()
)
var oskin_prev:CheckBox = oskin.get_node("prev")
var oskin_next:CheckBox = oskin.get_node("next")
oskin_prev.toggled.connect(func(on:bool):
rg_oskin_prev_char.visible = on
)
oskin_next.toggled.connect(func(on:bool):
rg_oskin_next_char.visible = on
)
var load = menu.get_node("Load")
load.load_image.connect(func(path):
image_path = path
init_form_image()
)
load.load_xml.connect(func(path):
data_path = path
init_form_xml()
)
var save = menu.get_node("Save")
save.pressed.connect(func():
var xml = spritesheet_parser.spritesheet_to_xml(spritesheet_animations, spritesheet_size, image_path)
save.save(xml)
)
fuck_with_frames_tree()
fuck_with_anims_tree()
init_form_image()
init_form_xml()
func init_form_xml() -> void:
spritesheet_parser.parse_spritesheet(data_path)
spritesheet_size = spritesheet_parser.max_dimensions
spritesheet_animations = []
spritesheet_frames = 0
for animation in spritesheet_parser.spritesheet:
var frames = spritesheet_parser.spritesheet[animation]
for fr_ame in frames:
fr_ame.frame_pos = -fr_ame.frame_pos
fr_ame.erase("frame_size")
spritesheet_frames = max(frames.size(), spritesheet_frames)
spritesheet_animations.append({
name = animation,
frames = frames
})
for animation in spritesheet_animations:
animation.frames.resize(spritesheet_frames)
var ct:Range = frame_count.get_node("value")
ct.value = spritesheet_frames
set_vector(sprite_size, spritesheet_size)
set_frames_tree()
set_anims_tree()
func init_form_image() -> void:
process_image = SpritesheetParser.load_image(image_path)
preview_image = ImageTexture.create_from_image(process_image)
fuck_with_region_view()
func align_to_vector(idx:int, cs:Vector2i, ps:Vector2i) -> Vector2i:
var vector = Vector2i.ZERO
match idx:
1, 4, 7:
vector.x = (ps.x / 2) - (cs.x / 2)
2, 5, 8:
vector.x = ps.x - cs.x
match idx:
3, 4, 5:
vector.y = (ps.y / 2) - (cs.y / 2)
6, 7, 8:
vector.y = ps.y - cs.y
return vector
func link_range_to_callable(obj:BoxContainer, callable:Callable, value) -> void:
var input:Range = obj.get_node("value")
input.value = value
input.value_changed.connect(callable)
func set_vector(obj:BoxContainer, vector:Vector2) -> void:
var x:Range = obj.get_node("value_w")
var y:Range = obj.get_node("value_h")
x.value = vector.x
y.value = vector.y
func get_vector(obj:BoxContainer) -> Vector2:
var x:Range = obj.get_node("value_w")
var y:Range = obj.get_node("value_h")
return Vector2(x.value, y.value)
func link_pos_to_callable(obj:BoxContainer, callable:Callable, value:Vector2i) -> void:
var x:Range = obj.get_node("value_w")
var y:Range = obj.get_node("value_h")
x.value = value.x
y.value = value.y
x.value_changed.connect(callable)
y.value_changed.connect(callable)
func link_pos_to_callable_e(obj:BoxContainer, callable:Callable) -> void:
var x:Range = obj.get_node("value_w")
var y:Range = obj.get_node("value_h")
x.value_changed.connect(callable)
y.value_changed.connect(callable)
var dont_change_internal = false
func fuck_with_anims_tree() -> void:
var tree:Tree = anims_tree.get_node("Tree")
var add_new_name:LineEdit = anims_tree.get_node("AddNew/name")
var add_new_switch:Button = anims_tree.get_node("AddNew/switch")
var tree_root = tree.create_item()
tree.button_clicked.connect(func(item:TreeItem, column:int, id:int, _mbi):
var item_index = item.get_index()
if column == 0:
if id == 0:
spritesheet_animations.remove_at(item_index)
if selected_animation == item_index:
selected_animation = max(item_index - 1, 0)
if selected_animation > -1:
tree.set_selected(tree_root.get_child(selected_animation), 0)
set_anims_tree()
set_frames_tree()
)
tree.item_selected.connect(func():
if dont_change_internal:
dont_change_internal = false
return
var item = tree.get_selected()
selected_animation = item.get_index()
set_frames_tree()
)
add_new_switch.pressed.connect(func():
var text = add_new_name.text
if text.length() < 1:
return
for anim in spritesheet_animations:
if anim.name == text: return
var frames = []
frames.resize(spritesheet_frames)
spritesheet_animations.append({
name = text,
frames = frames
})
set_anims_tree()
add_new_name.text = ""
)
func set_anims_tree() -> void:
var tree:Tree = anims_tree.get_node("Tree")
var tree_root = tree.get_root()
for child in tree_root.get_children():
child.free()
for animation in spritesheet_animations:
var child = tree.create_item(tree_root)
child.set_cell_mode(0, TreeItem.CELL_MODE_STRING)
child.set_editable(0, false)
child.set_text(0, animation.name)
child.add_button(0, close_icon, 0)
dont_change_internal = true
tree.set_selected(tree_root.get_child(selected_animation), 0)
func fuck_with_frames_tree() -> void:
var tree:Tree = frames_tree.get_node("Tree")
var tree_root = tree.create_item()
tree_root.set_cell_mode(0, TreeItem.CELL_MODE_STRING)
tree_root.set_editable(0, false)
tree_root.set_text(0, "No animation selected")
tree.button_clicked.connect(func(item:TreeItem, column:int, id:int, _mbi):
var item_index = item.get_index()
var cur_anim = spritesheet_animations[selected_animation]
if item_index >= cur_anim.frames.size(): return
if column == 1:
var frame = cur_anim.frames[item_index]
var duplicate = Input.is_action_pressed("mod_enable")
if id == 0:
if item_index + 1 >= cur_anim.frames.size(): return
var next_frame = cur_anim.frames[item_index + 1]
var placeholder
if next_frame != null and not duplicate:
placeholder = next_frame.duplicate(false)
cur_anim.frames[item_index + 1] = frame
if next_frame != null and not duplicate:
cur_anim.frames[item_index] = placeholder
if id == 1:
if item_index - 1 < 0: return
var prev_frame = cur_anim.frames[item_index - 1]
var placeholder = prev_frame.duplicate(false)
cur_anim.frames[item_index - 1] = frame
cur_anim.frames[item_index] = placeholder
set_frames_tree()
)
tree.item_edited.connect(func():
var text = tree_root.get_text(0)
if text.length() < 1:
tree_root.set_text(0, spritesheet_animations[selected_animation].name)
return
for anim in spritesheet_animations:
if anim.name == text:
tree_root.set_text(0, spritesheet_animations[selected_animation].name)
return
spritesheet_animations[selected_animation].name = text
set_anims_tree()
)
tree.item_selected.connect(func():
var item = tree.get_selected()
selected_frame = item.get_index()
set_region_view()
set_three_stooges()
)
func set_frames_tree() -> void:
var tree:Tree = frames_tree.get_node("Tree")
var tree_root = tree.get_root()
tree_root.set_editable(0, false)
tree_root.set_text(0, "No animation selected")
for child in tree_root.get_children():
child.free()
if spritesheet_animations.size() <= selected_animation:
return
var cur_anim = spritesheet_animations[selected_animation]
tree_root.set_editable(0, true)
tree_root.set_text(0, cur_anim.name)
var frames = cur_anim.frames
for frame in spritesheet_frames:
var child = tree.create_item(tree_root)
child.set_cell_mode(0, TreeItem.CELL_MODE_STRING)
child.set_editable(0, false)
child.set_text(0, "Frame #" + str(frame + 1))
child.set_cell_mode(1, TreeItem.CELL_MODE_STRING)
child.set_editable(1, false)
child.set_text(1, "640x480")
child.set_text_alignment(1, HORIZONTAL_ALIGNMENT_RIGHT)
child.add_button(1, arrow_down_icon, 0)
child.add_button(1, arrow_up_icon, 1)
if frame >= frames.size() - 1:
child.set_button_disabled(1, 0, true)
if frame <= 0:
child.set_button_disabled(1, 1, true)
if frames.size() <= frame or frames[frame] == null:
child.set_text(1, "Empty")
child.set_button_disabled(1, 1, true)
child.set_button_disabled(1, 0, true)
else:
child.set_text(1, str(frames[frame].size.x) + "x" + str(frames[frame].size.y))
tree.set_selected(tree_root.get_child(selected_frame), 0)
set_region_view()
func update_current_frame_child() -> void:
var tree:Tree = frames_tree.get_node("Tree")
var tree_root = tree.get_root()
var current_frame = tree_root.get_child(selected_frame)
if spritesheet_animations.size() <= selected_animation:
return
var frames = spritesheet_animations[selected_animation].frames
var frame = selected_frame
if current_frame == null: return
if frames.size() <= frame or frames[frame] == null:
current_frame.set_text(1, "Empty")
else:
current_frame.set_text(1, str(frames[frame].size.x) + "x" + str(frames[frame].size.y))
func fuck_with_region_view() -> void:
var frame:ReferenceRect = region_viewport.get_node("ReferenceRect")
var character:TextureRect = frame.get_node("Character")
character.texture.atlas = preview_image
rg_oskin_prev_char.texture.atlas = preview_image
rg_oskin_next_char.texture.atlas = preview_image
func set_region_view() -> void:
var frame:ReferenceRect = region_viewport.get_node("ReferenceRect")
var character:TextureRect = frame.get_node("Character")
var character_frame:ReferenceRect = frame.get_node("ReferenceRect")
var atlas:AtlasTexture = character.texture
if spritesheet_animations.size() <= selected_animation:
rg_oskin_prev_char.position = Vector2.ZERO
rg_oskin_prev_char.texture.region = Rect2(0,0,1,1)
rg_oskin_next_char.position = Vector2.ZERO
rg_oskin_next_char.texture.region = Rect2(0,0,1,1)
character.position = Vector2.ZERO
character_frame.position = Vector2.ZERO
character_frame.size = Vector2.ZERO
atlas.region = Rect2(0,0,1,1)
return
var cur_anim = spritesheet_animations[selected_animation]
if cur_anim.frames.size() < selected_frame or cur_anim.frames[selected_frame] == null:
character.position = Vector2.ZERO
character_frame.position = Vector2.ZERO
character_frame.size = Vector2.ZERO
atlas.region = Rect2(0,0,1,1)
return
var cur_frame = cur_anim.frames[selected_frame]
if selected_frame - 1 < 0 or cur_anim.frames[selected_frame - 1] == null:
rg_oskin_prev_char.position = Vector2.ZERO
rg_oskin_prev_char.texture.region = Rect2(0,0,1,1)
else:
var prev_frame = cur_anim.frames[selected_frame - 1]
rg_oskin_prev_char.position = prev_frame.frame_pos
rg_oskin_prev_char.texture.region = Rect2(prev_frame.pos, prev_frame.size)
if selected_frame + 1 >= cur_anim.frames.size() or cur_anim.frames[selected_frame + 1] == null:
rg_oskin_next_char.position = Vector2.ZERO
rg_oskin_next_char.texture.region = Rect2(0,0,1,1)
else:
var next_frame = cur_anim.frames[selected_frame + 1]
rg_oskin_next_char.position = next_frame.frame_pos
rg_oskin_next_char.texture.region = Rect2(next_frame.pos, next_frame.size)
character.position = cur_frame.frame_pos
character_frame.position = cur_frame.frame_pos
character_frame.size = cur_frame.size
atlas.region = Rect2(cur_frame.pos, cur_frame.size)
frame.size = spritesheet_size
frame.position = (region_viewport.size / 2) - Vector2i(frame.size / 2)
var ts_dont_change_internal = false
func set_three_stooges() -> void:
var character:TextureRect = region_viewport.get_node("ReferenceRect/Character")
var atlas:AtlasTexture = character.texture
ts_dont_change_internal = true
set_vector(region_pos, atlas.region.position)
set_vector(region_size, atlas.region.size)
set_vector(sprite_offset, character.position)
ts_dont_change_internal = false
func get_property_on_current_frame(prop:String):
var cur_anim = spritesheet_animations[selected_animation]
if cur_anim.frames.size() < 1: return null
var cur_frame = cur_anim.frames[selected_frame]
if cur_frame == null: return null
return cur_frame[prop]
func set_property_on_current_frame(prop:String, value:Variant):
var cur_anim = spritesheet_animations[selected_animation]
if cur_anim.frames.size() < 1: return
var cur_frame = cur_anim.frames[selected_frame]
if cur_frame == null:
cur_anim.frames[selected_frame] = {
pos = Vector2.ZERO,
size = Vector2.ONE,
frame_pos = Vector2.ZERO
}
cur_frame = cur_anim.frames[selected_frame]
cur_frame[prop] = value

35
scripts/xmle/load.gd Normal file
View file

@ -0,0 +1,35 @@
extends MenuButton
signal load_xml(path: String)
signal load_image(path: String)
@onready var root = get_tree().root
func _ready() -> void:
var popup = self.get_popup()
popup.index_pressed.connect(func(idx: int):
if idx < 0: return
var file_dialog = FileDialog.new()
file_dialog.use_native_dialog = true
file_dialog.file_mode = FileDialog.FILE_MODE_OPEN_FILE
if idx == 0:
file_dialog.add_filter("*.xml", "Sparrow spritesheet")
elif idx == 1:
file_dialog.add_filter("*.png", "Image")
file_dialog.access = FileDialog.ACCESS_FILESYSTEM
file_dialog.current_path = OS.get_data_dir().path_join("FunkPanion/")
file_dialog.file_selected.connect(func(path_string: String):
var localized = path_string.simplify_path().replace(OS.get_data_dir().path_join("FunkPanion/"), "user://")
if idx == 0:
load_xml.emit(localized)
elif idx == 1:
load_image.emit(localized)
file_dialog.queue_free()
)
file_dialog.canceled.connect(func(path_string: String):
root.remove_child(file_dialog)
file_dialog.queue_free()
)
root.add_child(file_dialog)
file_dialog.popup()
)

22
scripts/xmle/save.gd Normal file
View file

@ -0,0 +1,22 @@
extends Button
@onready var root = get_tree().root
func save(content:String) -> void:
var file_dialog = FileDialog.new()
file_dialog.use_native_dialog = true
file_dialog.file_mode = FileDialog.FILE_MODE_SAVE_FILE
file_dialog.add_filter("*.xml", "Sparrow spritesheet")
file_dialog.access = FileDialog.ACCESS_FILESYSTEM
file_dialog.current_path = OS.get_data_dir().path_join("FunkPanion/")
file_dialog.file_selected.connect(func(path_string: String):
var file = FileAccess.open(path_string, FileAccess.WRITE)
file.store_string(content)
file_dialog.queue_free()
)
file_dialog.canceled.connect(func(path_string: String):
root.remove_child(file_dialog)
file_dialog.queue_free()
)
root.add_child(file_dialog)
file_dialog.popup()

View file

@ -0,0 +1,17 @@
extends Node
var main_window
# Called when the node enters the scene tree for the first time.
func _enter_tree() -> void:
main_window = get_tree().root
main_window.borderless = false
main_window.always_on_top = false
main_window.transparent = false
main_window.min_size = Vector2i(800, 600)
main_window.size = Vector2i(800, 600)
main_window.title = "FP XML Tuner"
ProjectSettings.set_setting("display/window/subwindows/embed_subwindows", false)
func _on_exit_pressed() -> void:
get_tree().change_scene_to_file("res://scenes/main.tscn")

View file

@ -0,0 +1,17 @@
extends Node
var main_window
# Called when the node enters the scene tree for the first time.
func _enter_tree() -> void:
main_window = get_tree().root
main_window.borderless = false
main_window.always_on_top = false
main_window.transparent = false
main_window.min_size = Vector2i(480, 270)
main_window.size = Vector2i(480, 270)
main_window.title = "Image Atlas Wizard"
ProjectSettings.set_setting("display/window/subwindows/embed_subwindows", false)
func _on_exit_pressed() -> void:
get_tree().change_scene_to_file("res://scenes/main.tscn")