mirror of
https://github.com/tonytins/CozyPixelStudio.git
synced 2025-06-25 22:34:43 -04:00
Created a "UI" folder in src
And a Timeline folder in UI
This commit is contained in:
parent
8d5a673543
commit
c35e4b0613
51 changed files with 1444 additions and 1443 deletions
108
src/UI/BrushButton.gd
Normal file
108
src/UI/BrushButton.gd
Normal file
|
@ -0,0 +1,108 @@
|
|||
extends BaseButton
|
||||
|
||||
|
||||
signal brush_selected
|
||||
|
||||
export var brush_type = 0 # Global.Brush_Types.PIXEL
|
||||
export var custom_brush_index := -3
|
||||
var random_brushes := []
|
||||
|
||||
|
||||
func _on_BrushButton_pressed() -> void:
|
||||
# Delete the brush on middle mouse press
|
||||
if Input.is_action_just_released("middle_mouse"):
|
||||
_on_DeleteButton_pressed()
|
||||
return
|
||||
|
||||
# Change left brush
|
||||
if Global.brush_type_window_position == "left":
|
||||
Global.current_left_brush_type = brush_type
|
||||
Global.custom_left_brush_index = custom_brush_index
|
||||
if custom_brush_index > -1: # Custom brush
|
||||
if Global.current_left_tool == "Pencil":
|
||||
Global.left_color_interpolation_container.visible = true
|
||||
# if hint_tooltip == "":
|
||||
# Global.left_brush_type_label.text = tr("Custom brush")
|
||||
# else:
|
||||
# Global.left_brush_type_label.text = tr("Brush:") + " %s" % hint_tooltip
|
||||
elif custom_brush_index == -3: # Pixel brush
|
||||
Global.left_color_interpolation_container.visible = false
|
||||
# Global.left_brush_type_label.text = tr("Brush: Pixel")
|
||||
elif custom_brush_index == -2: # Circle brush
|
||||
Global.left_color_interpolation_container.visible = false
|
||||
# Global.left_brush_type_label.text = tr("Brush: Circle")
|
||||
elif custom_brush_index == -1: # Filled Circle brush
|
||||
Global.left_color_interpolation_container.visible = false
|
||||
# Global.left_brush_type_label.text = tr("Brush: Filled Circle")
|
||||
|
||||
Global.update_left_custom_brush()
|
||||
emit_signal("brush_selected")
|
||||
|
||||
else: # Change right brush
|
||||
Global.current_right_brush_type = brush_type
|
||||
Global.custom_right_brush_index = custom_brush_index
|
||||
if custom_brush_index > -1:
|
||||
if Global.current_right_tool == "Pencil":
|
||||
Global.right_color_interpolation_container.visible = true
|
||||
# if hint_tooltip == "":
|
||||
# Global.right_brush_type_label.text = tr("Custom brush")
|
||||
# else:
|
||||
# Global.right_brush_type_label.text = tr("Brush:") + " %s" % hint_tooltip
|
||||
elif custom_brush_index == -3: # Pixel brush
|
||||
Global.right_color_interpolation_container.visible = false
|
||||
# Global.right_brush_type_label.text = tr("Brush: Pixel")
|
||||
elif custom_brush_index == -2: # Circle brush
|
||||
Global.right_color_interpolation_container.visible = false
|
||||
# Global.right_brush_type_label.text = tr("Brush: Circle")
|
||||
elif custom_brush_index == -1: # Filled Circle brush
|
||||
Global.right_color_interpolation_container.visible = false
|
||||
# Global.right_brush_type_label.text = tr("Brush: Filled Circle")
|
||||
|
||||
Global.update_right_custom_brush()
|
||||
emit_signal("brush_selected")
|
||||
|
||||
|
||||
func _on_DeleteButton_pressed() -> void:
|
||||
if brush_type == Global.Brush_Types.CUSTOM:
|
||||
if Global.custom_left_brush_index == custom_brush_index:
|
||||
Global.custom_left_brush_index = -3
|
||||
Global.current_left_brush_type = Global.Brush_Types.PIXEL
|
||||
# Global.left_brush_type_label.text = "Brush: Pixel"
|
||||
Global.update_left_custom_brush()
|
||||
if Global.custom_right_brush_index == custom_brush_index:
|
||||
Global.custom_right_brush_index = -3
|
||||
Global.current_right_brush_type = Global.Brush_Types.PIXEL
|
||||
# Global.right_brush_type_label.text = "Brush: Pixel"
|
||||
Global.update_right_custom_brush()
|
||||
|
||||
var project_brush_index = custom_brush_index - Global.brushes_from_files
|
||||
Global.undos += 1
|
||||
Global.undo_redo.create_action("Delete Custom Brush")
|
||||
for i in range(project_brush_index, Global.project_brush_container.get_child_count()):
|
||||
var bb = Global.project_brush_container.get_child(i)
|
||||
if Global.custom_left_brush_index == bb.custom_brush_index:
|
||||
Global.custom_left_brush_index -= 1
|
||||
if Global.custom_right_brush_index == bb.custom_brush_index:
|
||||
Global.custom_right_brush_index -= 1
|
||||
|
||||
Global.undo_redo.add_do_property(bb, "custom_brush_index", bb.custom_brush_index - 1)
|
||||
Global.undo_redo.add_undo_property(bb, "custom_brush_index", bb.custom_brush_index)
|
||||
|
||||
var custom_brushes: Array = Global.custom_brushes.duplicate()
|
||||
custom_brushes.remove(custom_brush_index)
|
||||
|
||||
Global.undo_redo.add_do_property(Global, "custom_brushes", custom_brushes)
|
||||
Global.undo_redo.add_undo_property(Global, "custom_brushes", Global.custom_brushes)
|
||||
Global.undo_redo.add_do_method(Global, "redo_custom_brush", self)
|
||||
Global.undo_redo.add_undo_method(Global, "undo_custom_brush", self)
|
||||
Global.undo_redo.commit_action()
|
||||
|
||||
|
||||
func _on_BrushButton_mouse_entered() -> void:
|
||||
if brush_type == Global.Brush_Types.CUSTOM:
|
||||
$DeleteButton.visible = true
|
||||
|
||||
|
||||
func _on_BrushButton_mouse_exited() -> void:
|
||||
if brush_type == Global.Brush_Types.CUSTOM:
|
||||
$DeleteButton.visible = false
|
59
src/UI/BrushButton.tscn
Normal file
59
src/UI/BrushButton.tscn
Normal file
File diff suppressed because one or more lines are too long
122
src/UI/Dialogs/AboutDialog.gd
Normal file
122
src/UI/Dialogs/AboutDialog.gd
Normal file
|
@ -0,0 +1,122 @@
|
|||
extends WindowDialog
|
||||
|
||||
onready var credits = $AboutUI/Credits
|
||||
onready var groups : Tree = $AboutUI/Credits/Groups
|
||||
onready var developer_container = $AboutUI/Credits/Developers
|
||||
onready var contributors_container = $AboutUI/Credits/Contributors
|
||||
onready var donors_container = $AboutUI/Credits/Donors
|
||||
onready var translators_container = $AboutUI/Credits/Translators
|
||||
|
||||
onready var developers : Tree = $AboutUI/Credits/Developers/DeveloperTree
|
||||
onready var contributors : Tree = $AboutUI/Credits/Contributors/ContributorTree
|
||||
onready var donors : Tree = $AboutUI/Credits/Donors/DonorTree
|
||||
onready var translators : Tree = $AboutUI/Credits/Translators/TranslatorTree
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
var contributor_root := contributors.create_item()
|
||||
contributors.create_item(contributor_root).set_text(0, " Hugo Locurcio (Calinou)")
|
||||
contributors.create_item(contributor_root).set_text(0, " CheetoHead (greusser)")
|
||||
contributors.create_item(contributor_root).set_text(0, " Michael Alexsander (YeldhamDev)")
|
||||
contributors.create_item(contributor_root).set_text(0, " Schweini07")
|
||||
contributors.create_item(contributor_root).set_text(0, " Martin Zabinski")
|
||||
contributors.create_item(contributor_root).set_text(0, " azagaya")
|
||||
contributors.create_item(contributor_root).set_text(0, " Andreev Andrei")
|
||||
contributors.create_item(contributor_root).set_text(0, " Martin Novák (novhack)")
|
||||
contributors.create_item(contributor_root).set_text(0, " Marco Galli (Gaarco)")
|
||||
contributors.create_item(contributor_root).set_text(0, " Subhang Nanduri (SbNanduri)")
|
||||
contributors.create_item(contributor_root).set_text(0, " danielnaoexiste")
|
||||
contributors.create_item(contributor_root).set_text(0, " Noah Burck (haonkrub)")
|
||||
contributors.create_item(contributor_root).set_text(0, " Darshan Phaldesai (luiq54)")
|
||||
contributors.create_item(contributor_root).set_text(0, " Matheus Pesegoginski (MatheusPese)")
|
||||
contributors.create_item(contributor_root).set_text(0, " sapient_cogbag")
|
||||
contributors.create_item(contributor_root).set_text(0, " Kinwailo")
|
||||
contributors.create_item(contributor_root).set_text(0, " Igor Santarek (jegor377)")
|
||||
contributors.create_item(contributor_root).set_text(0, " Dávid Gábor BODOR (dragonfi)")
|
||||
|
||||
var donors_root := donors.create_item()
|
||||
donors.create_item(donors_root).set_text(0, " pcmxms")
|
||||
donors.create_item(donors_root).set_text(0, " Mike King")
|
||||
|
||||
|
||||
func _on_AboutDialog_about_to_show() -> void:
|
||||
var current_version : String = ProjectSettings.get_setting("application/config/Version")
|
||||
window_title = tr("About Pixelorama") + " " + current_version
|
||||
|
||||
var groups_root := groups.create_item()
|
||||
var developers_button := groups.create_item(groups_root)
|
||||
var contributors_button := groups.create_item(groups_root)
|
||||
var donors_button := groups.create_item(groups_root)
|
||||
var translators_button := groups.create_item(groups_root)
|
||||
|
||||
developers_button.set_text(0, " " + tr("Developers"))
|
||||
# We use metadata to avoid being affected by translations
|
||||
developers_button.set_metadata(0, "Developers")
|
||||
developers_button.select(0)
|
||||
contributors_button.set_text(0, " " + tr("Contributors"))
|
||||
contributors_button.set_metadata(0, "Contributors")
|
||||
donors_button.set_text(0, " " + tr("Donors"))
|
||||
donors_button.set_metadata(0, "Donors")
|
||||
translators_button.set_text(0, " " + tr("Translators"))
|
||||
translators_button.set_metadata(0, "Translators")
|
||||
|
||||
var dev_root := developers.create_item()
|
||||
developers.create_item(dev_root).set_text(0, " Manolis Papadeas (Overloaded) - " + tr("Lead Programmer"))
|
||||
developers.create_item(dev_root).set_text(0, " John Nikitakis (Erevos) - " + tr("UI Designer"))
|
||||
|
||||
# Translators
|
||||
var translators_root := translators.create_item()
|
||||
translators.create_item(translators_root).set_text(0, " Manolis Papadeas (Overloaded) - " + tr("Greek"))
|
||||
translators.create_item(translators_root).set_text(0, " Xenofon Konitsas (huskee) - " + tr("Greek"))
|
||||
translators.create_item(translators_root).set_text(0, " Hugo Locurcio (Calinou) - " + tr("French"))
|
||||
translators.create_item(translators_root).set_text(0, " blackjoker77777 - " + tr("French"))
|
||||
translators.create_item(translators_root).set_text(0, " Schweini07 - " + tr("German"))
|
||||
translators.create_item(translators_root).set_text(0, " Martin Zabinski (Martin1991zab) - " + tr("German"))
|
||||
translators.create_item(translators_root).set_text(0, " Dawid Niedźwiedzki (tiritto) - " + tr("Polish"))
|
||||
translators.create_item(translators_root).set_text(0, " Serhiy Dmytryshyn (dies) - " + tr("Polish"))
|
||||
translators.create_item(translators_root).set_text(0, " Michael Alexsander (YeldhamDev) - " + tr("Brazilian Portuguese"))
|
||||
translators.create_item(translators_root).set_text(0, " Cedulio Cezar (ceduliocezar) - " + tr("Brazilian Portuguese"))
|
||||
translators.create_item(translators_root).set_text(0, " Andreev Andrei - " + tr("Russian"))
|
||||
translators.create_item(translators_root).set_text(0, " ax trifonov (ax34) - " + tr("Russian"))
|
||||
translators.create_item(translators_root).set_text(0, " Artem (blinovartem) - " + tr("Russian"))
|
||||
translators.create_item(translators_root).set_text(0, " JunYouIntrovert - " + tr("Chinese Traditional"))
|
||||
translators.create_item(translators_root).set_text(0, " Chenxu Wang - " + tr("Chinese Simplified"))
|
||||
translators.create_item(translators_root).set_text(0, " Marco Galli (Gaarco) - " + tr("Italian"))
|
||||
translators.create_item(translators_root).set_text(0, " StarFang208 - " + tr("Italian"))
|
||||
translators.create_item(translators_root).set_text(0, " azagaya - " + tr("Spanish"))
|
||||
translators.create_item(translators_root).set_text(0, " Lilly And (KatieAnd) - " + tr("Spanish"))
|
||||
translators.create_item(translators_root).set_text(0, " Agnis Aldiņš (NeZvers) - " + tr("Latvian"))
|
||||
translators.create_item(translators_root).set_text(0, " Teashrock - " + tr("Esperanto"))
|
||||
|
||||
|
||||
func _on_AboutDialog_popup_hide() -> void:
|
||||
groups.clear()
|
||||
developers.clear()
|
||||
|
||||
|
||||
func _on_Groups_item_selected() -> void:
|
||||
for child in credits.get_children():
|
||||
if child != groups:
|
||||
child.visible = false
|
||||
|
||||
var selected : String = groups.get_selected().get_metadata(0)
|
||||
if "Developers" in selected:
|
||||
developer_container.visible = true
|
||||
elif "Contributors" in selected:
|
||||
contributors_container.visible = true
|
||||
elif "Donors" in selected:
|
||||
donors_container.visible = true
|
||||
elif "Translators" in selected:
|
||||
translators_container.visible = true
|
||||
|
||||
|
||||
func _on_Website_pressed() -> void:
|
||||
OS.shell_open("https://www.orama-interactive.com/pixelorama")
|
||||
|
||||
|
||||
func _on_GitHub_pressed() -> void:
|
||||
OS.shell_open("https://github.com/Orama-Interactive/Pixelorama")
|
||||
|
||||
|
||||
func _on_Donate_pressed() -> void:
|
||||
OS.shell_open("https://www.patreon.com/OramaInteractive")
|
209
src/UI/Dialogs/AboutDialog.tscn
Normal file
209
src/UI/Dialogs/AboutDialog.tscn
Normal file
|
@ -0,0 +1,209 @@
|
|||
[gd_scene load_steps=6 format=2]
|
||||
|
||||
[ext_resource path="res://src/UI/Dialogs/AboutDialog.gd" type="Script" id=1]
|
||||
[ext_resource path="res://Assets/Graphics/icon_64x64.png" type="Texture" id=2]
|
||||
[ext_resource path="res://Assets/Fonts/Roboto-Italic.tres" type="DynamicFont" id=3]
|
||||
[ext_resource path="res://Assets/Graphics/orama_64x64.png" type="Texture" id=4]
|
||||
[ext_resource path="res://Assets/Fonts/Roboto-Small.tres" type="DynamicFont" id=5]
|
||||
|
||||
|
||||
|
||||
[node name="AboutDialog" type="WindowDialog"]
|
||||
margin_right = 512.0
|
||||
margin_bottom = 288.0
|
||||
rect_min_size = Vector2( 512, 288 )
|
||||
window_title = "About Pixelorama"
|
||||
resizable = true
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="AboutUI" type="VBoxContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = 12.0
|
||||
margin_top = 4.0
|
||||
margin_right = -12.0
|
||||
margin_bottom = -8.0
|
||||
alignment = 1
|
||||
|
||||
[node name="IconsButtons" type="HBoxContainer" parent="AboutUI"]
|
||||
margin_right = 488.0
|
||||
margin_bottom = 64.0
|
||||
|
||||
[node name="PixeloramaLogo" type="TextureRect" parent="AboutUI/IconsButtons"]
|
||||
margin_right = 64.0
|
||||
margin_bottom = 64.0
|
||||
texture = ExtResource( 2 )
|
||||
|
||||
[node name="SloganAndLinks" type="CenterContainer" parent="AboutUI/IconsButtons"]
|
||||
margin_left = 68.0
|
||||
margin_right = 420.0
|
||||
margin_bottom = 64.0
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="AboutUI/IconsButtons/SloganAndLinks"]
|
||||
margin_left = 64.0
|
||||
margin_top = 12.0
|
||||
margin_right = 288.0
|
||||
margin_bottom = 51.0
|
||||
|
||||
[node name="Pixelorama" type="Label" parent="AboutUI/IconsButtons/SloganAndLinks/VBoxContainer"]
|
||||
margin_right = 224.0
|
||||
margin_bottom = 15.0
|
||||
custom_fonts/font = ExtResource( 3 )
|
||||
text = "Pixelorama - Pixelate your dreams!"
|
||||
align = 1
|
||||
|
||||
[node name="LinkButtons" type="HBoxContainer" parent="AboutUI/IconsButtons/SloganAndLinks/VBoxContainer"]
|
||||
margin_top = 19.0
|
||||
margin_right = 224.0
|
||||
margin_bottom = 39.0
|
||||
|
||||
[node name="Website" type="Button" parent="AboutUI/IconsButtons/SloganAndLinks/VBoxContainer/LinkButtons"]
|
||||
margin_right = 65.0
|
||||
margin_bottom = 20.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Website"
|
||||
|
||||
[node name="GitHub" type="Button" parent="AboutUI/IconsButtons/SloganAndLinks/VBoxContainer/LinkButtons"]
|
||||
margin_left = 69.0
|
||||
margin_right = 162.0
|
||||
margin_bottom = 20.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "GitHub Repo"
|
||||
|
||||
[node name="Donate" type="Button" parent="AboutUI/IconsButtons/SloganAndLinks/VBoxContainer/LinkButtons"]
|
||||
margin_left = 166.0
|
||||
margin_right = 224.0
|
||||
margin_bottom = 20.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Donate"
|
||||
|
||||
[node name="OramaLogo" type="TextureRect" parent="AboutUI/IconsButtons"]
|
||||
margin_left = 424.0
|
||||
margin_right = 488.0
|
||||
margin_bottom = 64.0
|
||||
texture = ExtResource( 4 )
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="AboutUI"]
|
||||
margin_top = 68.0
|
||||
margin_right = 488.0
|
||||
margin_bottom = 72.0
|
||||
|
||||
[node name="Credits" type="HSplitContainer" parent="AboutUI"]
|
||||
margin_top = 76.0
|
||||
margin_right = 488.0
|
||||
margin_bottom = 233.0
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="Groups" type="Tree" parent="AboutUI/Credits"]
|
||||
margin_right = 120.0
|
||||
margin_bottom = 157.0
|
||||
rect_min_size = Vector2( 120, 120 )
|
||||
custom_constants/item_margin = -2
|
||||
hide_root = true
|
||||
|
||||
[node name="Developers" type="VBoxContainer" parent="AboutUI/Credits"]
|
||||
margin_left = 132.0
|
||||
margin_right = 488.0
|
||||
margin_bottom = 157.0
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="Label" type="Label" parent="AboutUI/Credits/Developers"]
|
||||
margin_right = 356.0
|
||||
margin_bottom = 14.0
|
||||
text = "Development Team"
|
||||
|
||||
[node name="DeveloperTree" type="Tree" parent="AboutUI/Credits/Developers"]
|
||||
margin_top = 18.0
|
||||
margin_right = 356.0
|
||||
margin_bottom = 157.0
|
||||
size_flags_vertical = 3
|
||||
custom_constants/item_margin = -2
|
||||
custom_constants/button_margin = 2
|
||||
hide_root = true
|
||||
|
||||
[node name="Contributors" type="VBoxContainer" parent="AboutUI/Credits"]
|
||||
visible = false
|
||||
margin_left = 254.0
|
||||
margin_right = 496.0
|
||||
margin_bottom = 126.0
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="Label" type="Label" parent="AboutUI/Credits/Contributors"]
|
||||
margin_right = 242.0
|
||||
margin_bottom = 14.0
|
||||
text = "GitHub Contributors"
|
||||
|
||||
[node name="ContributorTree" type="Tree" parent="AboutUI/Credits/Contributors"]
|
||||
margin_top = 18.0
|
||||
margin_right = 242.0
|
||||
margin_bottom = 126.0
|
||||
size_flags_vertical = 3
|
||||
custom_constants/item_margin = -2
|
||||
hide_root = true
|
||||
|
||||
[node name="Donors" type="VBoxContainer" parent="AboutUI/Credits"]
|
||||
visible = false
|
||||
margin_left = 254.0
|
||||
margin_right = 496.0
|
||||
margin_bottom = 126.0
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="Label" type="Label" parent="AboutUI/Credits/Donors"]
|
||||
margin_right = 242.0
|
||||
margin_bottom = 14.0
|
||||
text = "Donors"
|
||||
|
||||
[node name="DonorTree" type="Tree" parent="AboutUI/Credits/Donors"]
|
||||
margin_top = 18.0
|
||||
margin_right = 242.0
|
||||
margin_bottom = 126.0
|
||||
size_flags_vertical = 3
|
||||
custom_constants/item_margin = -2
|
||||
hide_root = true
|
||||
|
||||
[node name="Translators" type="VBoxContainer" parent="AboutUI/Credits"]
|
||||
visible = false
|
||||
margin_left = 254.0
|
||||
margin_right = 496.0
|
||||
margin_bottom = 126.0
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="Label" type="Label" parent="AboutUI/Credits/Translators"]
|
||||
margin_right = 242.0
|
||||
margin_bottom = 14.0
|
||||
text = "Translators"
|
||||
|
||||
[node name="TranslatorTree" type="Tree" parent="AboutUI/Credits/Translators"]
|
||||
margin_top = 18.0
|
||||
margin_right = 242.0
|
||||
margin_bottom = 126.0
|
||||
size_flags_vertical = 3
|
||||
custom_constants/item_margin = -2
|
||||
hide_root = true
|
||||
|
||||
[node name="HSeparator2" type="HSeparator" parent="AboutUI"]
|
||||
margin_top = 237.0
|
||||
margin_right = 488.0
|
||||
margin_bottom = 241.0
|
||||
|
||||
[node name="MadeBy" type="Label" parent="AboutUI"]
|
||||
margin_top = 245.0
|
||||
margin_right = 488.0
|
||||
margin_bottom = 259.0
|
||||
text = "Developed by Orama Interactive"
|
||||
align = 1
|
||||
|
||||
[node name="Copyright" type="Label" parent="AboutUI"]
|
||||
margin_top = 263.0
|
||||
margin_right = 488.0
|
||||
margin_bottom = 276.0
|
||||
custom_fonts/font = ExtResource( 5 )
|
||||
text = "Copyright 2019-2020 Orama Interactive"
|
||||
align = 1
|
||||
[connection signal="about_to_show" from="." to="." method="_on_AboutDialog_about_to_show"]
|
||||
[connection signal="popup_hide" from="." to="." method="_on_AboutDialog_popup_hide"]
|
||||
[connection signal="pressed" from="AboutUI/IconsButtons/SloganAndLinks/VBoxContainer/LinkButtons/Website" to="." method="_on_Website_pressed"]
|
||||
[connection signal="pressed" from="AboutUI/IconsButtons/SloganAndLinks/VBoxContainer/LinkButtons/GitHub" to="." method="_on_GitHub_pressed"]
|
||||
[connection signal="pressed" from="AboutUI/IconsButtons/SloganAndLinks/VBoxContainer/LinkButtons/Donate" to="." method="_on_Donate_pressed"]
|
||||
[connection signal="item_selected" from="AboutUI/Credits/Groups" to="." method="_on_Groups_item_selected"]
|
133
src/UI/Dialogs/CreateNewImage.gd
Normal file
133
src/UI/Dialogs/CreateNewImage.gd
Normal file
|
@ -0,0 +1,133 @@
|
|||
extends ConfirmationDialog
|
||||
|
||||
onready var templates_options = $VBoxContainer/OptionsContainer/TemplatesOptions
|
||||
onready var ratio_box = $VBoxContainer/OptionsContainer/RatioCheckBox
|
||||
onready var width_value = $VBoxContainer/OptionsContainer/WidthValue
|
||||
onready var height_value = $VBoxContainer/OptionsContainer/HeightValue
|
||||
onready var fill_color_node = $VBoxContainer/OptionsContainer/FillColor
|
||||
|
||||
onready var size_value = Vector2()
|
||||
|
||||
# Template Id identifier
|
||||
enum Templates {
|
||||
TDefault = 0,
|
||||
T16 = 1,
|
||||
T32 = 2,
|
||||
T64 = 3,
|
||||
T128 = 4,
|
||||
GB = 5,
|
||||
GBA = 6,
|
||||
NES_NTSC = 7,
|
||||
NES_PAL = 8,
|
||||
SNES_NTSC = 9,
|
||||
SNES_PAL = 10
|
||||
}
|
||||
# Template actual value, without Default because we get it from Global
|
||||
var TResolutions = {
|
||||
Templates.T16: Vector2(16,16),
|
||||
Templates.T32: Vector2(32,32),
|
||||
Templates.T64: Vector2(64,64),
|
||||
Templates.T128: Vector2(128,128),
|
||||
|
||||
Templates.GB: Vector2(160,144),
|
||||
Templates.GBA: Vector2(240,160),
|
||||
Templates.NES_NTSC: Vector2(256,224),
|
||||
Templates.NES_PAL: Vector2(256,240),
|
||||
Templates.SNES_NTSC: Vector2(512,448),
|
||||
Templates.SNES_PAL: Vector2(512,480),
|
||||
}
|
||||
|
||||
var TStrings ={
|
||||
Templates.T16: "",
|
||||
Templates.T32: "",
|
||||
Templates.T64: "",
|
||||
Templates.T128: "",
|
||||
|
||||
Templates.GB: "GB",
|
||||
Templates.GBA: "GBA",
|
||||
Templates.NES_NTSC: "NES (NTSC)",
|
||||
Templates.NES_PAL: "NES (PAL)",
|
||||
Templates.SNES_NTSC: "SNES (NTSC)",
|
||||
Templates.SNES_PAL: "SNES (PAL)"
|
||||
}
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
ratio_box.connect("pressed", self, "_on_RatioCheckBox_toggled", [ratio_box.pressed])
|
||||
templates_options.connect("item_selected", self, "_on_TemplatesOptions_item_selected")
|
||||
|
||||
_CreateOptionList()
|
||||
|
||||
|
||||
func _CreateOptionList() -> void:
|
||||
for i in Templates.values():
|
||||
if i > 0:
|
||||
if TStrings[i] != "":
|
||||
templates_options.add_item("{width}x{height} - {name}".format({"width":TResolutions[i].x, "height":TResolutions[i].y, "name":TStrings[i]}), i)
|
||||
else:
|
||||
templates_options.add_item("{width}x{height}".format({"width":TResolutions[i].x, "height":TResolutions[i].y}), i)
|
||||
|
||||
|
||||
func _on_CreateNewImage_confirmed() -> void:
|
||||
var width : int = width_value.value
|
||||
var height : int = height_value.value
|
||||
var fill_color : Color = fill_color_node.color
|
||||
Global.clear_canvases()
|
||||
Global.layers.clear()
|
||||
# Store [Layer name (0), Layer visibility boolean (1), Layer lock boolean (2), Frame container (3),
|
||||
# will new frames be linked boolean (4), Array of linked frames (5)]
|
||||
Global.layers.append([tr("Layer") + " 0", true, false, HBoxContainer.new(), false, []])
|
||||
Global.canvas = load("res://src/Canvas.tscn").instance()
|
||||
Global.canvas.size = Vector2(width, height).floor()
|
||||
|
||||
Global.canvases.append(Global.canvas)
|
||||
Global.canvas_parent.add_child(Global.canvas)
|
||||
Global.current_layer = 0
|
||||
Global.canvases = Global.canvases # To trigger Global.canvases_changed()
|
||||
Global.current_frame = 0
|
||||
Global.layers = Global.layers # To trigger Global.layers_changed()
|
||||
Global.project_has_changed = false
|
||||
if fill_color.a > 0:
|
||||
Global.canvas.layers[0][0].fill(fill_color)
|
||||
Global.canvas.layers[0][0].lock()
|
||||
Global.canvas.update_texture(0)
|
||||
|
||||
|
||||
func _on_CreateNewImage_about_to_show() -> void:
|
||||
width_value.value = Global.default_image_width
|
||||
height_value.value = Global.default_image_height
|
||||
fill_color_node.color = Global.default_fill_color
|
||||
templates_options.selected = Templates.TDefault
|
||||
ratio_box.pressed = false
|
||||
for spin_box in [width_value, height_value]:
|
||||
if spin_box.is_connected("value_changed", self, "_on_SizeValue_value_changed"):
|
||||
spin_box.disconnect("value_changed", self, "_on_SizeValue_value_changed")
|
||||
|
||||
|
||||
var aspect_ratio: float
|
||||
|
||||
func _on_RatioCheckBox_toggled(_button_pressed: bool) -> void:
|
||||
aspect_ratio = width_value.value / height_value.value
|
||||
for spin_box in [width_value, height_value]:
|
||||
if spin_box.is_connected("value_changed", self, "_on_SizeValue_value_changed"):
|
||||
spin_box.disconnect("value_changed", self, "_on_SizeValue_value_changed")
|
||||
else:
|
||||
spin_box.connect("value_changed", self, "_on_SizeValue_value_changed")
|
||||
|
||||
|
||||
func _on_SizeValue_value_changed(value: float) -> void:
|
||||
if width_value.value == value:
|
||||
height_value.value = width_value.value / aspect_ratio
|
||||
if height_value.value == value:
|
||||
width_value.value = height_value.value * aspect_ratio
|
||||
|
||||
|
||||
func _on_TemplatesOptions_item_selected(id: int) -> void:
|
||||
if id != Templates.TDefault:
|
||||
size_value = TResolutions[id]
|
||||
else:
|
||||
width_value.value = Global.default_image_width
|
||||
height_value.value = Global.default_image_height
|
||||
|
||||
width_value.value = size_value.x
|
||||
height_value.value = size_value.y
|
124
src/UI/Dialogs/CreateNewImage.tscn
Normal file
124
src/UI/Dialogs/CreateNewImage.tscn
Normal file
|
@ -0,0 +1,124 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://src/UI/Dialogs/CreateNewImage.gd" type="Script" id=1]
|
||||
|
||||
|
||||
|
||||
[node name="CreateNewImage" type="ConfirmationDialog"]
|
||||
margin_right = 300.0
|
||||
margin_bottom = 200.0
|
||||
rect_min_size = Vector2( 375, 200 )
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
margin_left = 8.0
|
||||
margin_top = 8.0
|
||||
margin_right = 367.0
|
||||
margin_bottom = 164.0
|
||||
size_flags_horizontal = 0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="ImageSize" type="Label" parent="VBoxContainer"]
|
||||
margin_right = 359.0
|
||||
margin_bottom = 14.0
|
||||
text = "Image Size"
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="VBoxContainer"]
|
||||
margin_top = 18.0
|
||||
margin_right = 359.0
|
||||
margin_bottom = 22.0
|
||||
|
||||
[node name="OptionsContainer" type="GridContainer" parent="VBoxContainer"]
|
||||
margin_top = 26.0
|
||||
margin_right = 359.0
|
||||
margin_bottom = 154.0
|
||||
custom_constants/vseparation = 4
|
||||
custom_constants/hseparation = 2
|
||||
columns = 2
|
||||
|
||||
[node name="TemplatesLabel" type="Label" parent="VBoxContainer/OptionsContainer"]
|
||||
margin_top = 3.0
|
||||
margin_right = 112.0
|
||||
margin_bottom = 17.0
|
||||
text = "Templates:"
|
||||
|
||||
[node name="TemplatesOptions" type="OptionButton" parent="VBoxContainer/OptionsContainer"]
|
||||
margin_left = 114.0
|
||||
margin_right = 189.0
|
||||
margin_bottom = 20.0
|
||||
mouse_default_cursor_shape = 2
|
||||
toggle_mode = false
|
||||
text = "Default"
|
||||
items = [ "Default", null, false, 0, null ]
|
||||
selected = 0
|
||||
|
||||
[node name="RatioLabel" type="Label" parent="VBoxContainer/OptionsContainer"]
|
||||
margin_top = 29.0
|
||||
margin_right = 112.0
|
||||
margin_bottom = 43.0
|
||||
text = "Lock aspect ratio:"
|
||||
|
||||
[node name="RatioCheckBox" type="CheckBox" parent="VBoxContainer/OptionsContainer"]
|
||||
margin_left = 114.0
|
||||
margin_top = 24.0
|
||||
margin_right = 189.0
|
||||
margin_bottom = 48.0
|
||||
mouse_default_cursor_shape = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="WidthLabel" type="Label" parent="VBoxContainer/OptionsContainer"]
|
||||
margin_top = 57.0
|
||||
margin_right = 112.0
|
||||
margin_bottom = 71.0
|
||||
text = "Width:"
|
||||
|
||||
[node name="WidthValue" type="SpinBox" parent="VBoxContainer/OptionsContainer"]
|
||||
margin_left = 114.0
|
||||
margin_top = 52.0
|
||||
margin_right = 189.0
|
||||
margin_bottom = 76.0
|
||||
mouse_default_cursor_shape = 2
|
||||
min_value = 1.0
|
||||
max_value = 16384.0
|
||||
value = 64.0
|
||||
suffix = "px"
|
||||
|
||||
[node name="Height" type="Label" parent="VBoxContainer/OptionsContainer"]
|
||||
margin_top = 85.0
|
||||
margin_right = 112.0
|
||||
margin_bottom = 99.0
|
||||
text = "Height:"
|
||||
|
||||
[node name="HeightValue" type="SpinBox" parent="VBoxContainer/OptionsContainer"]
|
||||
margin_left = 114.0
|
||||
margin_top = 80.0
|
||||
margin_right = 189.0
|
||||
margin_bottom = 104.0
|
||||
mouse_default_cursor_shape = 2
|
||||
min_value = 1.0
|
||||
max_value = 16384.0
|
||||
value = 64.0
|
||||
suffix = "px"
|
||||
|
||||
[node name="FillColorLabel" type="Label" parent="VBoxContainer/OptionsContainer"]
|
||||
margin_top = 111.0
|
||||
margin_right = 112.0
|
||||
margin_bottom = 125.0
|
||||
text = "Fill with color:"
|
||||
|
||||
[node name="FillColor" type="ColorPickerButton" parent="VBoxContainer/OptionsContainer"]
|
||||
margin_left = 114.0
|
||||
margin_top = 108.0
|
||||
margin_right = 189.0
|
||||
margin_bottom = 128.0
|
||||
rect_min_size = Vector2( 64, 20 )
|
||||
color = Color( 0, 0, 0, 0 )
|
||||
[connection signal="about_to_show" from="." to="." method="_on_CreateNewImage_about_to_show"]
|
||||
[connection signal="confirmed" from="." to="." method="_on_CreateNewImage_confirmed"]
|
629
src/UI/Dialogs/ExportDialog.gd
Normal file
629
src/UI/Dialogs/ExportDialog.gd
Normal file
|
@ -0,0 +1,629 @@
|
|||
extends AcceptDialog
|
||||
|
||||
enum ExportTab { FRAME = 0, SPRITESHEET = 1, ANIMATION = 2 }
|
||||
var current_tab : int = ExportTab.FRAME
|
||||
|
||||
# All canvases and their layers processed/blended into images
|
||||
var processed_images = [] # Image[]
|
||||
|
||||
# Frame options
|
||||
var frame_number := 0
|
||||
|
||||
# Spritesheet options
|
||||
enum Orientation { ROWS = 0, COLUMNS = 1 }
|
||||
var orientation : int = Orientation.ROWS
|
||||
# How many rows/columns before new line is added
|
||||
var lines_count := 1
|
||||
|
||||
# Animation options
|
||||
enum AnimationType { MULTIPLE_FILES = 0, ANIMATED = 1 }
|
||||
var animation_type : int = AnimationType.MULTIPLE_FILES
|
||||
var background_color : Color = Color.white
|
||||
enum AnimationDirection { FORWARD = 0, BACKWARDS = 1, PING_PONG = 2 }
|
||||
var direction : int = AnimationDirection.FORWARD
|
||||
|
||||
# Options
|
||||
var resize := 100
|
||||
var interpolation := 0 # Image.Interpolation
|
||||
var new_dir_for_each_frame_tag : bool = true # you don't need to store this after export
|
||||
|
||||
# Export directory path and export file name
|
||||
var directory_path := ""
|
||||
var file_name := ""
|
||||
var file_format : int = FileFormat.PNG
|
||||
enum FileFormat { PNG = 0, GIF = 1}
|
||||
|
||||
var file_exists_alert = "File %s already exists. Overwrite?"
|
||||
|
||||
# Store all settings after export, enables a quick re-export with same settings
|
||||
var was_exported : bool = false
|
||||
var exported_tab : int
|
||||
var exported_frame_number : int
|
||||
var exported_orientation : int
|
||||
var exported_lines_count : int
|
||||
var exported_animation_type : int
|
||||
var exported_background_color : Color
|
||||
var exported_direction : int
|
||||
var exported_resize : int
|
||||
var exported_interpolation : int
|
||||
var exported_directory_path : String
|
||||
var exported_file_name : String
|
||||
var exported_file_format : int
|
||||
|
||||
# Export coroutine signal
|
||||
signal resume_export_function()
|
||||
var stop_export = false
|
||||
|
||||
var animated_preview_current_frame := 0
|
||||
var animated_preview_frames = []
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
$VBoxContainer/Tabs.add_tab("Frame")
|
||||
$VBoxContainer/Tabs.add_tab("Spritesheet")
|
||||
$VBoxContainer/Tabs.add_tab("Animation")
|
||||
if OS.get_name() == "Windows":
|
||||
add_button("Cancel", true, "cancel")
|
||||
$Popups/FileExistsAlert.add_button("Cancel Export", true, "cancel")
|
||||
else:
|
||||
add_button("Cancel", false, "cancel")
|
||||
$Popups/FileExistsAlert.add_button("Cancel Export", false, "cancel")
|
||||
|
||||
# Disable GIF export for unsupported platforms
|
||||
if not $GifExporter.is_platform_supported():
|
||||
$VBoxContainer/AnimationOptions/AnimationType.selected = AnimationType.MULTIPLE_FILES
|
||||
$VBoxContainer/AnimationOptions/AnimationType.disabled = true
|
||||
|
||||
|
||||
func show_tab() -> void:
|
||||
$VBoxContainer/FrameOptions.hide()
|
||||
$VBoxContainer/SpritesheetOptions.hide()
|
||||
$VBoxContainer/AnimationOptions.hide()
|
||||
|
||||
match current_tab:
|
||||
ExportTab.FRAME:
|
||||
file_format = FileFormat.PNG
|
||||
$VBoxContainer/File/FileFormat.selected = FileFormat.PNG
|
||||
$FrameTimer.stop()
|
||||
if not was_exported:
|
||||
frame_number = Global.current_frame + 1
|
||||
$VBoxContainer/FrameOptions/FrameNumber/FrameNumber.max_value = Global.canvases.size() + 1
|
||||
$VBoxContainer/FrameOptions/FrameNumber/FrameNumber.value = frame_number
|
||||
process_frame()
|
||||
$VBoxContainer/FrameOptions.show()
|
||||
ExportTab.SPRITESHEET:
|
||||
file_format = FileFormat.PNG
|
||||
$VBoxContainer/File/FileFormat.selected = FileFormat.PNG
|
||||
$FrameTimer.stop()
|
||||
if not was_exported:
|
||||
orientation = Orientation.ROWS
|
||||
lines_count = int(ceil(sqrt(Global.canvases.size())))
|
||||
$VBoxContainer/SpritesheetOptions/Orientation/Orientation.selected = orientation
|
||||
$VBoxContainer/SpritesheetOptions/Orientation/LinesCount.max_value = Global.canvases.size()
|
||||
$VBoxContainer/SpritesheetOptions/Orientation/LinesCount.value = lines_count
|
||||
$VBoxContainer/SpritesheetOptions/Orientation/LinesCountLabel.text = "Columns:"
|
||||
process_spritesheet()
|
||||
$VBoxContainer/SpritesheetOptions.show()
|
||||
ExportTab.ANIMATION:
|
||||
set_file_format_selector()
|
||||
process_animation()
|
||||
$VBoxContainer/AnimationOptions/AnimationType.selected = animation_type
|
||||
$VBoxContainer/AnimationOptions/AnimatedOptions/BackgroundColor.color = background_color
|
||||
$VBoxContainer/AnimationOptions/AnimatedOptions/Direction.selected = direction
|
||||
$VBoxContainer/AnimationOptions.show()
|
||||
set_preview()
|
||||
$VBoxContainer/Tabs.current_tab = current_tab
|
||||
|
||||
|
||||
func external_export() -> void:
|
||||
restore_previous_export_settings()
|
||||
match current_tab:
|
||||
ExportTab.FRAME:
|
||||
process_frame()
|
||||
ExportTab.SPRITESHEET:
|
||||
process_spritesheet()
|
||||
ExportTab.ANIMATION:
|
||||
process_animation()
|
||||
export_processed_images(true)
|
||||
|
||||
|
||||
func process_frame() -> void:
|
||||
var canvas = Global.canvases[frame_number - 1]
|
||||
var image := Image.new()
|
||||
image.create(canvas.size.x, canvas.size.y, false, Image.FORMAT_RGBA8)
|
||||
blend_layers(image, canvas)
|
||||
processed_images.clear()
|
||||
processed_images.append(image)
|
||||
|
||||
|
||||
func process_spritesheet() -> void:
|
||||
# If rows mode selected calculate columns count and vice versa
|
||||
var spritesheet_columns = lines_count if orientation == Orientation.ROWS else frames_divided_by_spritesheet_lines()
|
||||
var spritesheet_rows = lines_count if orientation == Orientation.COLUMNS else frames_divided_by_spritesheet_lines()
|
||||
|
||||
var width = Global.canvas.size.x * spritesheet_columns
|
||||
var height = Global.canvas.size.y * spritesheet_rows
|
||||
|
||||
var whole_image := Image.new()
|
||||
whole_image.create(width, height, false, Image.FORMAT_RGBA8)
|
||||
whole_image.lock()
|
||||
var origin := Vector2.ZERO
|
||||
var hh := 0
|
||||
var vv := 0
|
||||
for canvas in Global.canvases:
|
||||
if orientation == Orientation.ROWS:
|
||||
if vv < spritesheet_columns:
|
||||
origin.x = canvas.size.x * vv
|
||||
vv += 1
|
||||
else:
|
||||
hh += 1
|
||||
origin.x = 0
|
||||
vv = 1
|
||||
origin.y = canvas.size.y * hh
|
||||
else:
|
||||
if hh < spritesheet_rows:
|
||||
origin.y = canvas.size.y * hh
|
||||
hh += 1
|
||||
else:
|
||||
vv += 1
|
||||
origin.y = 0
|
||||
hh = 1
|
||||
origin.x = canvas.size.x * vv
|
||||
blend_layers(whole_image, canvas, origin)
|
||||
|
||||
processed_images.clear()
|
||||
processed_images.append(whole_image)
|
||||
|
||||
|
||||
func process_animation() -> void:
|
||||
processed_images.clear()
|
||||
for canvas in Global.canvases:
|
||||
var image := Image.new()
|
||||
image.create(canvas.size.x, canvas.size.y, false, Image.FORMAT_RGBA8)
|
||||
blend_layers(image, canvas)
|
||||
processed_images.append(image)
|
||||
|
||||
|
||||
func set_preview() -> void:
|
||||
remove_previews()
|
||||
if processed_images.size() == 1 and current_tab != ExportTab.ANIMATION:
|
||||
$VBoxContainer/PreviewScroll/Previews.columns = 1
|
||||
add_image_preview(processed_images[0])
|
||||
else:
|
||||
match animation_type:
|
||||
AnimationType.MULTIPLE_FILES:
|
||||
$VBoxContainer/PreviewScroll/Previews.columns = ceil(sqrt(processed_images.size()))
|
||||
for i in range(processed_images.size()):
|
||||
add_image_preview(processed_images[i], i + 1)
|
||||
AnimationType.ANIMATED:
|
||||
$VBoxContainer/PreviewScroll/Previews.columns = 1
|
||||
add_animated_preview()
|
||||
|
||||
|
||||
func add_image_preview(image: Image, canvas_number: int = -1) -> void:
|
||||
var container = create_preview_container()
|
||||
var preview = create_preview_rect()
|
||||
preview.texture = ImageTexture.new()
|
||||
preview.texture.create_from_image(image, 0)
|
||||
container.add_child(preview)
|
||||
|
||||
if canvas_number != -1:
|
||||
var label = Label.new()
|
||||
label.align = Label.ALIGN_CENTER
|
||||
label.text = String(canvas_number)
|
||||
container.add_child(label)
|
||||
|
||||
$VBoxContainer/PreviewScroll/Previews.add_child(container)
|
||||
|
||||
|
||||
func add_animated_preview() -> void:
|
||||
animated_preview_current_frame = processed_images.size() - 1 if direction == AnimationDirection.BACKWARDS else 0
|
||||
animated_preview_frames = []
|
||||
|
||||
for processed_image in processed_images:
|
||||
var texture = ImageTexture.new()
|
||||
texture.create_from_image(processed_image, 0)
|
||||
animated_preview_frames.push_back(texture)
|
||||
|
||||
var container = create_preview_container()
|
||||
container.name = "PreviewContainer"
|
||||
var preview = create_preview_rect()
|
||||
preview.name = "Preview"
|
||||
preview.texture = animated_preview_frames[animated_preview_current_frame]
|
||||
container.add_child(preview)
|
||||
|
||||
$VBoxContainer/PreviewScroll/Previews.add_child(container)
|
||||
$FrameTimer.start()
|
||||
|
||||
|
||||
func create_preview_container() -> VBoxContainer:
|
||||
var container = VBoxContainer.new()
|
||||
container.size_flags_horizontal = SIZE_EXPAND_FILL
|
||||
container.size_flags_vertical = SIZE_EXPAND_FILL
|
||||
container.rect_min_size = Vector2(0, 128)
|
||||
return container
|
||||
|
||||
|
||||
func create_preview_rect() -> TextureRect:
|
||||
var preview = TextureRect.new()
|
||||
preview.expand = true
|
||||
preview.size_flags_horizontal = SIZE_EXPAND_FILL
|
||||
preview.size_flags_vertical = SIZE_EXPAND_FILL
|
||||
preview.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
|
||||
return preview
|
||||
|
||||
|
||||
func remove_previews() -> void:
|
||||
for child in $VBoxContainer/PreviewScroll/Previews.get_children():
|
||||
child.free()
|
||||
|
||||
|
||||
func get_proccessed_image_animation_tag_and_start_id(processed_image_id : int) -> Array:
|
||||
var result_animation_tag_and_start_id = null
|
||||
for animation_tag in Global.animation_tags:
|
||||
# Check if processed image is in frame tag and assign frame tag and start id if yes
|
||||
# Then stop
|
||||
if (processed_image_id + 1) >= animation_tag[2] and (processed_image_id + 1) <= animation_tag[3]:
|
||||
result_animation_tag_and_start_id = [animation_tag[0], animation_tag[2]]
|
||||
break
|
||||
return result_animation_tag_and_start_id
|
||||
|
||||
|
||||
func export_processed_images(ignore_overwrites : bool) -> void:
|
||||
# Stop export if directory path or file name are not valid
|
||||
var dir = Directory.new()
|
||||
if not dir.dir_exists(directory_path) or not file_name.is_valid_filename():
|
||||
$Popups/PathValidationAlert.popup_centered()
|
||||
return
|
||||
|
||||
# Check export paths
|
||||
var export_paths = []
|
||||
for i in range(processed_images.size()):
|
||||
stop_export = false
|
||||
var multiple_files := true if (current_tab == ExportTab.ANIMATION && animation_type == AnimationType.MULTIPLE_FILES) else false
|
||||
var export_path = create_export_path(multiple_files, i + 1)
|
||||
# If user want to create new directory for each animation tag then check if directories exist and create them if not
|
||||
if multiple_files and new_dir_for_each_frame_tag:
|
||||
var frame_tag_directory := Directory.new()
|
||||
if not frame_tag_directory.dir_exists(export_path.get_base_dir()):
|
||||
frame_tag_directory.open(directory_path)
|
||||
frame_tag_directory.make_dir(export_path.get_base_dir().get_file())
|
||||
# Check if the file already exists
|
||||
var fileCheck = File.new()
|
||||
if fileCheck.file_exists(export_path):
|
||||
# Ask user if he want's to overwrite the file
|
||||
if not was_exported or (was_exported and not ignore_overwrites):
|
||||
# Overwrite existing file?
|
||||
$Popups/FileExistsAlert.dialog_text = file_exists_alert % export_path
|
||||
$Popups/FileExistsAlert.popup_centered()
|
||||
# Stops the function until the user decides if he want's to overwrite
|
||||
yield(self, "resume_export_function")
|
||||
if stop_export:
|
||||
# User decided to stop export
|
||||
return
|
||||
export_paths.append(export_path)
|
||||
# Only get one export path if single file animated image is exported
|
||||
if current_tab == ExportTab.ANIMATION && animation_type == AnimationType.ANIMATED:
|
||||
break
|
||||
|
||||
# Scale images that are to export
|
||||
scale_processed_images()
|
||||
|
||||
if current_tab == ExportTab.ANIMATION && animation_type == AnimationType.ANIMATED:
|
||||
var frame_delay_in_ms = Global.animation_timer.wait_time * 100
|
||||
|
||||
$GifExporter.begin_export(export_paths[0], processed_images[0].get_width(), processed_images[0].get_height(), frame_delay_in_ms, 0)
|
||||
match direction:
|
||||
AnimationDirection.FORWARD:
|
||||
for i in range(processed_images.size()):
|
||||
$GifExporter.write_frame(processed_images[i], background_color, frame_delay_in_ms)
|
||||
AnimationDirection.BACKWARDS:
|
||||
for i in range(processed_images.size() - 1, -1, -1):
|
||||
$GifExporter.write_frame(processed_images[i], background_color, frame_delay_in_ms)
|
||||
AnimationDirection.PING_PONG:
|
||||
for i in range(0, processed_images.size()):
|
||||
$GifExporter.write_frame(processed_images[i], background_color, frame_delay_in_ms)
|
||||
for i in range(processed_images.size() - 2, 0, -1):
|
||||
$GifExporter.write_frame(processed_images[i], background_color, frame_delay_in_ms)
|
||||
$GifExporter.end_export()
|
||||
else:
|
||||
for i in range(processed_images.size()):
|
||||
var err = processed_images[i].save_png(export_paths[i])
|
||||
if err != OK:
|
||||
OS.alert("Can't save file")
|
||||
|
||||
# Store settings for quick export and when the dialog is opened again
|
||||
was_exported = true
|
||||
store_export_settings()
|
||||
Global.file_menu.get_popup().set_item_text(6, tr("Export") + " %s" % (file_name + file_format_string(file_format)))
|
||||
Global.notification_label("File(s) exported")
|
||||
hide()
|
||||
|
||||
|
||||
# Blends canvas layers into passed image starting from the origin position
|
||||
func blend_layers(image: Image, canvas: Canvas, origin: Vector2 = Vector2(0, 0)) -> void:
|
||||
image.lock()
|
||||
var layer_i := 0
|
||||
for layer in canvas.layers:
|
||||
if Global.layers[layer_i][1]:
|
||||
var layer_image := Image.new()
|
||||
layer_image.copy_from(layer[0])
|
||||
layer_image.lock()
|
||||
if layer[2] < 1: # If we have layer transparency
|
||||
for xx in layer_image.get_size().x:
|
||||
for yy in layer_image.get_size().y:
|
||||
var pixel_color := layer_image.get_pixel(xx, yy)
|
||||
var alpha : float = pixel_color.a * layer[2]
|
||||
layer_image.set_pixel(xx, yy, Color(pixel_color.r, pixel_color.g, pixel_color.b, alpha))
|
||||
canvas.blend_rect(image, layer_image, Rect2(canvas.position, canvas.size), origin)
|
||||
layer_i += 1
|
||||
image.unlock()
|
||||
|
||||
|
||||
func scale_processed_images() -> void:
|
||||
for processed_image in processed_images:
|
||||
if resize != 100:
|
||||
processed_image.unlock()
|
||||
processed_image.resize(processed_image.get_size().x * resize / 100, processed_image.get_size().y * resize / 100, interpolation)
|
||||
|
||||
|
||||
func create_export_path(multifile: bool, frame: int = 0) -> String:
|
||||
var path = file_name
|
||||
# Only append frame number when there are multiple files exported
|
||||
if multifile:
|
||||
var frame_tag_and_start_id = get_proccessed_image_animation_tag_and_start_id(frame - 1)
|
||||
# Check if exported frame is in frame tag
|
||||
if frame_tag_and_start_id != null:
|
||||
var frame_tag = frame_tag_and_start_id[0]
|
||||
var start_id = frame_tag_and_start_id[1]
|
||||
# Remove unallowed characters in frame tag directory
|
||||
var regex := RegEx.new()
|
||||
regex.compile("[^a-zA-Z0-9_]+")
|
||||
var frame_tag_dir = regex.sub(frame_tag, "", true)
|
||||
if new_dir_for_each_frame_tag:
|
||||
# Add frame tag if frame has one
|
||||
# (frame - start_id + 1) Makes frames id to start from 1 in each frame tag directory
|
||||
path += "_" + frame_tag_dir + "_" + String(frame - start_id + 1)
|
||||
return directory_path.plus_file(frame_tag_dir).plus_file(path + file_format_string(file_format))
|
||||
else:
|
||||
# Add frame tag if frame has one
|
||||
# (frame - start_id + 1) Makes frames id to start from 1 in each frame tag
|
||||
path += "_" + frame_tag_dir + "_" + String(frame - start_id + 1)
|
||||
else:
|
||||
path += "_" + String(frame)
|
||||
|
||||
return directory_path.plus_file(path + file_format_string(file_format))
|
||||
|
||||
|
||||
func frames_divided_by_spritesheet_lines() -> int:
|
||||
return int(ceil(Global.canvases.size() / float(lines_count)))
|
||||
|
||||
|
||||
func file_format_string(format_enum : int) -> String:
|
||||
match format_enum:
|
||||
0: # PNG
|
||||
return '.png'
|
||||
1: # GIF
|
||||
return '.gif'
|
||||
_:
|
||||
return ''
|
||||
|
||||
|
||||
func set_file_format_selector() -> void:
|
||||
$VBoxContainer/AnimationOptions/MultipleAnimationsDirectories.visible = false
|
||||
match animation_type:
|
||||
AnimationType.MULTIPLE_FILES:
|
||||
file_format = FileFormat.PNG
|
||||
$VBoxContainer/File/FileFormat.selected = FileFormat.PNG
|
||||
$FrameTimer.stop()
|
||||
$VBoxContainer/AnimationOptions/AnimatedOptions.hide()
|
||||
$VBoxContainer/AnimationOptions/MultipleAnimationsDirectories.pressed = new_dir_for_each_frame_tag
|
||||
$VBoxContainer/AnimationOptions/MultipleAnimationsDirectories.visible = true
|
||||
AnimationType.ANIMATED:
|
||||
file_format = FileFormat.GIF
|
||||
$VBoxContainer/File/FileFormat.selected = FileFormat.GIF
|
||||
$FrameTimer.wait_time = Global.animation_timer.wait_time
|
||||
$VBoxContainer/AnimationOptions/AnimatedOptions.show()
|
||||
|
||||
|
||||
func store_export_settings() -> void:
|
||||
exported_tab = current_tab
|
||||
exported_frame_number = frame_number
|
||||
exported_orientation = orientation
|
||||
exported_lines_count = lines_count
|
||||
exported_animation_type = animation_type
|
||||
exported_background_color = background_color
|
||||
exported_direction = direction
|
||||
exported_resize = resize
|
||||
exported_interpolation = interpolation
|
||||
exported_directory_path = directory_path
|
||||
exported_file_name = file_name
|
||||
exported_file_format = file_format
|
||||
|
||||
|
||||
# Fill the dialog with previous export settings
|
||||
func restore_previous_export_settings() -> void:
|
||||
current_tab = exported_tab
|
||||
frame_number = exported_frame_number if exported_frame_number <= Global.canvases.size() else Global.canvases.size()
|
||||
orientation = exported_orientation
|
||||
lines_count = exported_lines_count
|
||||
animation_type = exported_animation_type
|
||||
background_color = exported_background_color
|
||||
direction = exported_direction
|
||||
resize = exported_resize
|
||||
interpolation = exported_interpolation
|
||||
directory_path = exported_directory_path
|
||||
file_name = exported_file_name
|
||||
file_format = exported_file_format
|
||||
|
||||
|
||||
func _on_ExportDialog_about_to_show() -> void:
|
||||
# If export already occured - fill the dialog with previous export settings
|
||||
if was_exported:
|
||||
restore_previous_export_settings()
|
||||
|
||||
if directory_path.empty():
|
||||
directory_path = OS.get_system_dir(OS.SYSTEM_DIR_DESKTOP)
|
||||
|
||||
# If export already occured - sets gui to show previous settings
|
||||
$VBoxContainer/Options/Resize.value = resize
|
||||
$VBoxContainer/Options/Interpolation.selected = interpolation
|
||||
$VBoxContainer/Path/PathLineEdit.text = directory_path
|
||||
$VBoxContainer/File/FileLineEdit.text = file_name
|
||||
$VBoxContainer/File/FileFormat.selected = file_format
|
||||
show_tab()
|
||||
|
||||
for child in $Popups.get_children(): # Set the theme for the popups
|
||||
child.theme = Global.control.theme
|
||||
|
||||
file_exists_alert = tr("File %s already exists. Overwrite?") # Update translation
|
||||
#$VBoxContainer/Tabs.set_tab_title(0, "Frame")
|
||||
|
||||
|
||||
func _on_Tabs_tab_clicked(tab : int) -> void:
|
||||
current_tab = tab
|
||||
show_tab()
|
||||
|
||||
|
||||
func _on_Frame_value_changed(value: float) -> void:
|
||||
frame_number = value
|
||||
process_frame()
|
||||
set_preview()
|
||||
|
||||
|
||||
func _on_Orientation_item_selected(id : int) -> void:
|
||||
orientation = id
|
||||
if orientation == Orientation.ROWS:
|
||||
$VBoxContainer/SpritesheetOptions/Orientation/LinesCountLabel.text = "Columns:"
|
||||
else:
|
||||
$VBoxContainer/SpritesheetOptions/Orientation/LinesCountLabel.text = "Rows:"
|
||||
$VBoxContainer/SpritesheetOptions/Orientation/LinesCount.value = frames_divided_by_spritesheet_lines()
|
||||
process_spritesheet()
|
||||
set_preview()
|
||||
|
||||
|
||||
func _on_LinesCount_value_changed(value : float) -> void:
|
||||
lines_count = value
|
||||
process_spritesheet()
|
||||
set_preview()
|
||||
|
||||
|
||||
func _on_AnimationType_item_selected(id : int) -> void:
|
||||
animation_type = id
|
||||
set_file_format_selector()
|
||||
set_preview()
|
||||
|
||||
|
||||
func _on_BackgroundColor_color_changed(color : Color) -> void:
|
||||
background_color = color
|
||||
|
||||
|
||||
func _on_Direction_item_selected(id : int) -> void:
|
||||
direction = id
|
||||
match id:
|
||||
AnimationDirection.FORWARD:
|
||||
animated_preview_current_frame = 0
|
||||
AnimationDirection.BACKWARDS:
|
||||
animated_preview_current_frame = processed_images.size() - 1
|
||||
AnimationDirection.PING_PONG:
|
||||
animated_preview_current_frame = 0
|
||||
pingpong_direction = AnimationDirection.FORWARD
|
||||
|
||||
|
||||
func _on_Resize_value_changed(value : float) -> void:
|
||||
resize = value
|
||||
|
||||
|
||||
func _on_Interpolation_item_selected(id: int) -> void:
|
||||
interpolation = id
|
||||
|
||||
|
||||
func _on_ExportDialog_confirmed() -> void:
|
||||
export_processed_images(false)
|
||||
|
||||
|
||||
func _on_ExportDialog_custom_action(action : String) -> void:
|
||||
if action == "cancel":
|
||||
hide()
|
||||
|
||||
|
||||
func _on_PathButton_pressed() -> void:
|
||||
$Popups/PathDialog.popup_centered()
|
||||
|
||||
|
||||
func _on_PathLineEdit_text_changed(new_text : String) -> void:
|
||||
directory_path = new_text
|
||||
|
||||
|
||||
func _on_FileLineEdit_text_changed(new_text : String) -> void:
|
||||
file_name = new_text
|
||||
|
||||
|
||||
func _on_FileDialog_dir_selected(dir : String) -> void:
|
||||
$VBoxContainer/Path/PathLineEdit.text = dir
|
||||
directory_path = dir
|
||||
|
||||
|
||||
func _on_FileFormat_item_selected(id : int) -> void:
|
||||
file_format = id
|
||||
|
||||
|
||||
func _on_FileExistsAlert_confirmed() -> void:
|
||||
# Overwrite existing file
|
||||
$Popups/FileExistsAlert.dialog_text = file_exists_alert
|
||||
stop_export = false
|
||||
emit_signal("resume_export_function")
|
||||
|
||||
|
||||
func _on_FileExistsAlert_custom_action(action : String) -> void:
|
||||
if action == "cancel":
|
||||
# Cancel export
|
||||
$Popups/FileExistsAlert.dialog_text = file_exists_alert
|
||||
stop_export = true
|
||||
emit_signal("resume_export_function")
|
||||
$Popups/FileExistsAlert.hide()
|
||||
|
||||
|
||||
var pingpong_direction = AnimationDirection.FORWARD
|
||||
func _on_FrameTimer_timeout() -> void:
|
||||
$VBoxContainer/PreviewScroll/Previews/PreviewContainer/Preview.texture = animated_preview_frames[animated_preview_current_frame]
|
||||
|
||||
match direction:
|
||||
AnimationDirection.FORWARD:
|
||||
if animated_preview_current_frame == animated_preview_frames.size() - 1:
|
||||
animated_preview_current_frame = 0
|
||||
else:
|
||||
animated_preview_current_frame += 1
|
||||
|
||||
AnimationDirection.BACKWARDS:
|
||||
if animated_preview_current_frame == 0:
|
||||
animated_preview_current_frame = processed_images.size() - 1
|
||||
else:
|
||||
animated_preview_current_frame -= 1
|
||||
|
||||
AnimationDirection.PING_PONG:
|
||||
match pingpong_direction:
|
||||
AnimationDirection.FORWARD:
|
||||
if animated_preview_current_frame == animated_preview_frames.size() - 1:
|
||||
pingpong_direction = AnimationDirection.BACKWARDS
|
||||
animated_preview_current_frame -= 1
|
||||
if animated_preview_current_frame <= 0:
|
||||
animated_preview_current_frame = 0
|
||||
else:
|
||||
animated_preview_current_frame += 1
|
||||
AnimationDirection.BACKWARDS:
|
||||
if animated_preview_current_frame == 0:
|
||||
animated_preview_current_frame += 1
|
||||
if animated_preview_current_frame >= animated_preview_frames.size() - 1:
|
||||
animated_preview_current_frame = 0
|
||||
pingpong_direction = AnimationDirection.FORWARD
|
||||
else:
|
||||
animated_preview_current_frame -= 1
|
||||
|
||||
|
||||
func _on_ExportDialog_popup_hide() -> void:
|
||||
$FrameTimer.stop()
|
||||
|
||||
|
||||
func _on_MultipleAnimationsDirectories_toggled(button_pressed : bool) -> void:
|
||||
new_dir_for_each_frame_tag = button_pressed
|
390
src/UI/Dialogs/ExportDialog.tscn
Normal file
390
src/UI/Dialogs/ExportDialog.tscn
Normal file
|
@ -0,0 +1,390 @@
|
|||
[gd_scene load_steps=3 format=2]
|
||||
|
||||
[ext_resource path="res://src/UI/Dialogs/ExportDialog.gd" type="Script" id=1]
|
||||
[ext_resource path="res://addons/godot-gifexporter/src/GifExporter.gd" type="Script" id=2]
|
||||
|
||||
|
||||
|
||||
[node name="ExportDialog" type="AcceptDialog"]
|
||||
margin_right = 532.0
|
||||
margin_bottom = 530.0
|
||||
rect_min_size = Vector2( 456, 530 )
|
||||
window_title = "Export..."
|
||||
resizable = true
|
||||
dialog_hide_on_ok = false
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
margin_left = 8.0
|
||||
margin_top = 8.0
|
||||
margin_right = 524.0
|
||||
margin_bottom = 494.0
|
||||
rect_min_size = Vector2( 330, 0 )
|
||||
size_flags_vertical = 3
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Tabs" type="Tabs" parent="VBoxContainer"]
|
||||
margin_right = 516.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_vertical = 0
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="VBoxContainer"]
|
||||
margin_top = 28.0
|
||||
margin_right = 516.0
|
||||
margin_bottom = 32.0
|
||||
|
||||
[node name="PreviewLabel" type="Label" parent="VBoxContainer"]
|
||||
margin_top = 36.0
|
||||
margin_right = 516.0
|
||||
margin_bottom = 50.0
|
||||
text = "Preview:"
|
||||
|
||||
[node name="PreviewScroll" type="ScrollContainer" parent="VBoxContainer"]
|
||||
margin_top = 54.0
|
||||
margin_right = 516.0
|
||||
margin_bottom = 274.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="Previews" type="GridContainer" parent="VBoxContainer/PreviewScroll"]
|
||||
margin_right = 516.0
|
||||
margin_bottom = 220.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
columns = 3
|
||||
|
||||
[node name="FrameOptions" type="VBoxContainer" parent="VBoxContainer"]
|
||||
margin_top = 278.0
|
||||
margin_right = 516.0
|
||||
margin_bottom = 302.0
|
||||
|
||||
[node name="FrameNumber" type="HBoxContainer" parent="VBoxContainer/FrameOptions"]
|
||||
margin_right = 516.0
|
||||
margin_bottom = 24.0
|
||||
|
||||
[node name="FrameNumberLabel" type="Label" parent="VBoxContainer/FrameOptions/FrameNumber"]
|
||||
margin_top = 5.0
|
||||
margin_right = 44.0
|
||||
margin_bottom = 19.0
|
||||
text = "Frame:"
|
||||
|
||||
[node name="FrameNumber" type="SpinBox" parent="VBoxContainer/FrameOptions/FrameNumber"]
|
||||
margin_left = 48.0
|
||||
margin_right = 516.0
|
||||
margin_bottom = 24.0
|
||||
rect_min_size = Vector2( 100, 0 )
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
min_value = 1.0
|
||||
page = 1.0
|
||||
value = 1.0
|
||||
rounded = true
|
||||
align = 2
|
||||
|
||||
[node name="SpritesheetOptions" type="VBoxContainer" parent="VBoxContainer"]
|
||||
margin_top = 306.0
|
||||
margin_right = 516.0
|
||||
margin_bottom = 330.0
|
||||
|
||||
[node name="Orientation" type="HBoxContainer" parent="VBoxContainer/SpritesheetOptions"]
|
||||
margin_right = 516.0
|
||||
margin_bottom = 24.0
|
||||
alignment = 1
|
||||
|
||||
[node name="OrientationLabel" type="Label" parent="VBoxContainer/SpritesheetOptions/Orientation"]
|
||||
margin_top = 5.0
|
||||
margin_right = 77.0
|
||||
margin_bottom = 19.0
|
||||
text = "Orientation:"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Orientation" type="OptionButton" parent="VBoxContainer/SpritesheetOptions/Orientation"]
|
||||
margin_left = 81.0
|
||||
margin_right = 264.0
|
||||
margin_bottom = 24.0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Rows"
|
||||
items = [ "Rows", null, false, 0, null, "Columns", null, false, 1, null ]
|
||||
selected = 0
|
||||
|
||||
[node name="LinesCountLabel" type="Label" parent="VBoxContainer/SpritesheetOptions/Orientation"]
|
||||
margin_left = 268.0
|
||||
margin_top = 5.0
|
||||
margin_right = 328.0
|
||||
margin_bottom = 19.0
|
||||
text = "Columns:"
|
||||
|
||||
[node name="LinesCount" type="SpinBox" parent="VBoxContainer/SpritesheetOptions/Orientation"]
|
||||
margin_left = 332.0
|
||||
margin_right = 516.0
|
||||
margin_bottom = 24.0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
min_value = 1.0
|
||||
max_value = 1000.0
|
||||
value = 1.0
|
||||
align = 2
|
||||
|
||||
[node name="AnimationOptions" type="VBoxContainer" parent="VBoxContainer"]
|
||||
margin_top = 334.0
|
||||
margin_right = 516.0
|
||||
margin_bottom = 386.0
|
||||
|
||||
[node name="AnimationType" type="OptionButton" parent="VBoxContainer/AnimationOptions"]
|
||||
margin_right = 516.0
|
||||
margin_bottom = 24.0
|
||||
rect_min_size = Vector2( 0, 24 )
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "All frames as multiple files"
|
||||
items = [ "All frames as multiple files", null, false, 0, null, "All frames as a single file animation", null, false, 1, null ]
|
||||
selected = 0
|
||||
|
||||
[node name="MultipleAnimationsDirectories" type="CheckBox" parent="VBoxContainer/AnimationOptions"]
|
||||
visible = false
|
||||
margin_top = 28.0
|
||||
margin_right = 516.0
|
||||
margin_bottom = 52.0
|
||||
hint_tooltip = "Creates multiple files but every file is stored in different directory that corresponds to its frame tag"
|
||||
text = "Create new directory for each frame tag"
|
||||
|
||||
[node name="AnimatedOptions" type="HBoxContainer" parent="VBoxContainer/AnimationOptions"]
|
||||
margin_top = 28.0
|
||||
margin_right = 516.0
|
||||
margin_bottom = 52.0
|
||||
rect_min_size = Vector2( 0, 24 )
|
||||
|
||||
[node name="BackgroundColorLabel" type="Label" parent="VBoxContainer/AnimationOptions/AnimatedOptions"]
|
||||
margin_top = 5.0
|
||||
margin_right = 78.0
|
||||
margin_bottom = 19.0
|
||||
text = "Background:"
|
||||
valign = 1
|
||||
|
||||
[node name="BackgroundColor" type="ColorPickerButton" parent="VBoxContainer/AnimationOptions/AnimatedOptions"]
|
||||
margin_left = 82.0
|
||||
margin_right = 263.0
|
||||
margin_bottom = 24.0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 7
|
||||
color = Color( 1, 1, 1, 1 )
|
||||
edit_alpha = false
|
||||
|
||||
[node name="DirectionLabel" type="Label" parent="VBoxContainer/AnimationOptions/AnimatedOptions"]
|
||||
margin_left = 267.0
|
||||
margin_top = 5.0
|
||||
margin_right = 330.0
|
||||
margin_bottom = 19.0
|
||||
text = "Direction:"
|
||||
|
||||
[node name="Direction" type="OptionButton" parent="VBoxContainer/AnimationOptions/AnimatedOptions"]
|
||||
margin_left = 334.0
|
||||
margin_right = 516.0
|
||||
margin_bottom = 24.0
|
||||
rect_min_size = Vector2( 100, 0 )
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Forward"
|
||||
items = [ "Forward", null, false, 0, null, "Backwards", null, false, 1, null, "Ping-Pong", null, false, 2, null ]
|
||||
selected = 0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="HSeparator2" type="HSeparator" parent="VBoxContainer"]
|
||||
margin_top = 390.0
|
||||
margin_right = 516.0
|
||||
margin_bottom = 394.0
|
||||
|
||||
[node name="Options" type="HBoxContainer" parent="VBoxContainer"]
|
||||
margin_top = 398.0
|
||||
margin_right = 516.0
|
||||
margin_bottom = 422.0
|
||||
|
||||
[node name="ResizeLabel" type="Label" parent="VBoxContainer/Options"]
|
||||
margin_top = 5.0
|
||||
margin_right = 46.0
|
||||
margin_bottom = 19.0
|
||||
rect_min_size = Vector2( 30, 0 )
|
||||
text = "Resize:"
|
||||
align = 2
|
||||
|
||||
[node name="Resize" type="SpinBox" parent="VBoxContainer/Options"]
|
||||
margin_left = 50.0
|
||||
margin_right = 235.0
|
||||
margin_bottom = 24.0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
min_value = 10.0
|
||||
max_value = 1000.0
|
||||
step = 100.0
|
||||
value = 100.0
|
||||
align = 2
|
||||
suffix = "%"
|
||||
|
||||
[node name="InterpolationLabel" type="Label" parent="VBoxContainer/Options"]
|
||||
margin_left = 239.0
|
||||
margin_top = 5.0
|
||||
margin_right = 326.0
|
||||
margin_bottom = 19.0
|
||||
rect_min_size = Vector2( 30, 0 )
|
||||
text = "Interpolation:"
|
||||
align = 2
|
||||
|
||||
[node name="Interpolation" type="OptionButton" parent="VBoxContainer/Options"]
|
||||
margin_left = 330.0
|
||||
margin_right = 516.0
|
||||
margin_bottom = 24.0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Nearest"
|
||||
align = 2
|
||||
items = [ "Nearest", null, false, 0, null, "Bilinear", null, false, 1, null, "Cubic", null, false, 2, null, "Trilinear", null, false, 3, null, "Lanczos", null, false, 4, null ]
|
||||
selected = 0
|
||||
|
||||
[node name="HSeparator3" type="HSeparator" parent="VBoxContainer"]
|
||||
margin_top = 426.0
|
||||
margin_right = 516.0
|
||||
margin_bottom = 430.0
|
||||
|
||||
[node name="Path" type="HBoxContainer" parent="VBoxContainer"]
|
||||
margin_top = 434.0
|
||||
margin_right = 516.0
|
||||
margin_bottom = 458.0
|
||||
|
||||
[node name="Label" type="Label" parent="VBoxContainer/Path"]
|
||||
margin_top = 5.0
|
||||
margin_right = 32.0
|
||||
margin_bottom = 19.0
|
||||
rect_min_size = Vector2( 30, 0 )
|
||||
text = "Path:"
|
||||
|
||||
[node name="PathLineEdit" type="LineEdit" parent="VBoxContainer/Path"]
|
||||
margin_left = 36.0
|
||||
margin_right = 453.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_horizontal = 3
|
||||
align = 2
|
||||
|
||||
[node name="PathButton" type="Button" parent="VBoxContainer/Path"]
|
||||
margin_left = 457.0
|
||||
margin_right = 516.0
|
||||
margin_bottom = 24.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Browse"
|
||||
|
||||
[node name="File" type="HBoxContainer" parent="VBoxContainer"]
|
||||
margin_top = 462.0
|
||||
margin_right = 516.0
|
||||
margin_bottom = 486.0
|
||||
|
||||
[node name="Label" type="Label" parent="VBoxContainer/File"]
|
||||
margin_top = 5.0
|
||||
margin_right = 30.0
|
||||
margin_bottom = 19.0
|
||||
rect_min_size = Vector2( 30, 0 )
|
||||
text = "File:"
|
||||
|
||||
[node name="FileLineEdit" type="LineEdit" parent="VBoxContainer/File"]
|
||||
margin_left = 34.0
|
||||
margin_right = 376.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_horizontal = 3
|
||||
align = 2
|
||||
|
||||
[node name="FileFormat" type="OptionButton" parent="VBoxContainer/File"]
|
||||
margin_left = 380.0
|
||||
margin_right = 516.0
|
||||
margin_bottom = 24.0
|
||||
rect_min_size = Vector2( 130, 0 )
|
||||
mouse_default_cursor_shape = 8
|
||||
disabled = true
|
||||
text = ".png; PNG Image"
|
||||
items = [ ".png; PNG Image", null, false, 0, null, ".gif; GIF Image", null, false, 1, null ]
|
||||
selected = 0
|
||||
|
||||
[node name="Popups" type="Node" parent="."]
|
||||
|
||||
[node name="PathDialog" type="FileDialog" parent="Popups"]
|
||||
margin_left = 8.0
|
||||
margin_top = 8.0
|
||||
margin_right = 448.0
|
||||
margin_bottom = 494.0
|
||||
rect_min_size = Vector2( 440, 300 )
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 0
|
||||
window_title = "Otwórz katalog"
|
||||
resizable = true
|
||||
mode = 2
|
||||
access = 2
|
||||
current_dir = "E:/Projekty/Godot/Pixelorama"
|
||||
current_path = "E:/Projekty/Godot/Pixelorama/"
|
||||
|
||||
[node name="PathValidationAlert" type="AcceptDialog" parent="Popups"]
|
||||
margin_left = 8.0
|
||||
margin_top = 180.0
|
||||
margin_right = 448.0
|
||||
margin_bottom = 280.0
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 0
|
||||
window_title = "Alarm!"
|
||||
resizable = true
|
||||
dialog_text = "Directory path or file name is not valid!"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="FileExistsAlert" type="AcceptDialog" parent="Popups"]
|
||||
margin_left = 8.0
|
||||
margin_top = 180.0
|
||||
margin_right = 448.0
|
||||
margin_bottom = 280.0
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 0
|
||||
window_title = "Alarm!"
|
||||
resizable = true
|
||||
dialog_text = "File %s already exists. Overwrite?"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="FrameTimer" type="Timer" parent="."]
|
||||
__meta__ = {
|
||||
"_editor_description_": "Timer to advance animation frames in animation preview."
|
||||
}
|
||||
|
||||
[node name="GifExporter" type="Node" parent="."]
|
||||
script = ExtResource( 2 )
|
||||
__meta__ = {
|
||||
"_editor_description_": ""
|
||||
}
|
||||
[connection signal="about_to_show" from="." to="." method="_on_ExportDialog_about_to_show"]
|
||||
[connection signal="confirmed" from="." to="." method="_on_ExportDialog_confirmed"]
|
||||
[connection signal="custom_action" from="." to="." method="_on_ExportDialog_custom_action"]
|
||||
[connection signal="popup_hide" from="." to="." method="_on_ExportDialog_popup_hide"]
|
||||
[connection signal="tab_clicked" from="VBoxContainer/Tabs" to="." method="_on_Tabs_tab_clicked"]
|
||||
[connection signal="value_changed" from="VBoxContainer/FrameOptions/FrameNumber/FrameNumber" to="." method="_on_Frame_value_changed"]
|
||||
[connection signal="item_selected" from="VBoxContainer/SpritesheetOptions/Orientation/Orientation" to="." method="_on_Orientation_item_selected"]
|
||||
[connection signal="value_changed" from="VBoxContainer/SpritesheetOptions/Orientation/LinesCount" to="." method="_on_LinesCount_value_changed"]
|
||||
[connection signal="item_selected" from="VBoxContainer/AnimationOptions/AnimationType" to="." method="_on_AnimationType_item_selected"]
|
||||
[connection signal="toggled" from="VBoxContainer/AnimationOptions/MultipleAnimationsDirectories" to="." method="_on_MultipleAnimationsDirectories_toggled"]
|
||||
[connection signal="color_changed" from="VBoxContainer/AnimationOptions/AnimatedOptions/BackgroundColor" to="." method="_on_BackgroundColor_color_changed"]
|
||||
[connection signal="item_selected" from="VBoxContainer/AnimationOptions/AnimatedOptions/Direction" to="." method="_on_Direction_item_selected"]
|
||||
[connection signal="value_changed" from="VBoxContainer/Options/Resize" to="." method="_on_Resize_value_changed"]
|
||||
[connection signal="item_selected" from="VBoxContainer/Options/Interpolation" to="." method="_on_Interpolation_item_selected"]
|
||||
[connection signal="text_changed" from="VBoxContainer/Path/PathLineEdit" to="." method="_on_PathLineEdit_text_changed"]
|
||||
[connection signal="pressed" from="VBoxContainer/Path/PathButton" to="." method="_on_PathButton_pressed"]
|
||||
[connection signal="text_changed" from="VBoxContainer/File/FileLineEdit" to="." method="_on_FileLineEdit_text_changed"]
|
||||
[connection signal="item_selected" from="VBoxContainer/File/FileFormat" to="." method="_on_FileFormat_item_selected"]
|
||||
[connection signal="dir_selected" from="Popups/PathDialog" to="." method="_on_FileDialog_dir_selected"]
|
||||
[connection signal="confirmed" from="Popups/FileExistsAlert" to="." method="_on_FileExistsAlert_confirmed"]
|
||||
[connection signal="custom_action" from="Popups/FileExistsAlert" to="." method="_on_FileExistsAlert_custom_action"]
|
||||
[connection signal="timeout" from="FrameTimer" to="." method="_on_FrameTimer_timeout"]
|
134
src/UI/Dialogs/FrameTagDialog.gd
Normal file
134
src/UI/Dialogs/FrameTagDialog.gd
Normal file
|
@ -0,0 +1,134 @@
|
|||
extends AcceptDialog
|
||||
|
||||
|
||||
var current_tag_id := 0
|
||||
var tag_vboxes := []
|
||||
var delete_tag_button : Button
|
||||
|
||||
onready var main_vbox_cont : VBoxContainer = $VBoxContainer/ScrollContainer/VBoxTagContainer
|
||||
onready var add_tag_button : TextureButton = $VBoxContainer/ScrollContainer/VBoxTagContainer/AddTag
|
||||
onready var options_dialog = $TagOptions
|
||||
|
||||
|
||||
func _on_FrameTagDialog_about_to_show() -> void:
|
||||
Global.can_draw = false
|
||||
for vbox in tag_vboxes:
|
||||
vbox.queue_free()
|
||||
tag_vboxes.clear()
|
||||
|
||||
var i := 0
|
||||
for tag in Global.animation_tags:
|
||||
var vbox_cont := VBoxContainer.new()
|
||||
var hbox_cont := HBoxContainer.new()
|
||||
var tag_label := Label.new()
|
||||
if tag[2] == tag[3]:
|
||||
tag_label.text = "Tag %s (Frame %s)" % [i + 1, tag[2]]
|
||||
else:
|
||||
tag_label.text = "Tag %s (Frames %s-%s)" % [i + 1, tag[2], tag[3]]
|
||||
hbox_cont.add_child(tag_label)
|
||||
|
||||
var edit_button := Button.new()
|
||||
edit_button.text = "Edit"
|
||||
edit_button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
|
||||
edit_button.connect("pressed", self, "_on_EditButton_pressed", [i])
|
||||
hbox_cont.add_child(edit_button)
|
||||
vbox_cont.add_child(hbox_cont)
|
||||
|
||||
var name_label := Label.new()
|
||||
name_label.text = tag[0]
|
||||
name_label.modulate = tag[1]
|
||||
vbox_cont.add_child(name_label)
|
||||
|
||||
var hsep := HSeparator.new()
|
||||
hsep.size_flags_horizontal = SIZE_EXPAND_FILL
|
||||
vbox_cont.add_child(hsep)
|
||||
|
||||
main_vbox_cont.add_child(vbox_cont)
|
||||
tag_vboxes.append(vbox_cont)
|
||||
|
||||
i += 1
|
||||
|
||||
add_tag_button.visible = true
|
||||
main_vbox_cont.move_child(add_tag_button, main_vbox_cont.get_child_count() - 1)
|
||||
|
||||
|
||||
func _on_FrameTagDialog_popup_hide() -> void:
|
||||
Global.can_draw = true
|
||||
|
||||
|
||||
func _on_AddTag_pressed() -> void:
|
||||
options_dialog.popup_centered()
|
||||
current_tag_id = Global.animation_tags.size()
|
||||
options_dialog.get_node("GridContainer/FromSpinBox").value = Global.current_frame + 1
|
||||
options_dialog.get_node("GridContainer/ToSpinBox").value = Global.current_frame + 1
|
||||
|
||||
|
||||
func _on_EditButton_pressed(_tag_id : int) -> void:
|
||||
options_dialog.popup_centered()
|
||||
current_tag_id = _tag_id
|
||||
options_dialog.get_node("GridContainer/NameLineEdit").text = Global.animation_tags[_tag_id][0]
|
||||
options_dialog.get_node("GridContainer/ColorPickerButton").color = Global.animation_tags[_tag_id][1]
|
||||
options_dialog.get_node("GridContainer/FromSpinBox").value = Global.animation_tags[_tag_id][2]
|
||||
options_dialog.get_node("GridContainer/ToSpinBox").value = Global.animation_tags[_tag_id][3]
|
||||
if !delete_tag_button:
|
||||
delete_tag_button = options_dialog.add_button("Delete Tag", true, "delete_tag")
|
||||
else:
|
||||
delete_tag_button.visible = true
|
||||
|
||||
|
||||
func _on_TagOptions_confirmed() -> void:
|
||||
var tag_name : String = options_dialog.get_node("GridContainer/NameLineEdit").text
|
||||
var tag_color : Color = options_dialog.get_node("GridContainer/ColorPickerButton").color
|
||||
var tag_from : int = options_dialog.get_node("GridContainer/FromSpinBox").value
|
||||
var tag_to : int = options_dialog.get_node("GridContainer/ToSpinBox").value
|
||||
|
||||
if tag_to > Global.canvases.size():
|
||||
tag_to = Global.canvases.size()
|
||||
|
||||
if tag_from > tag_to:
|
||||
tag_from = tag_to
|
||||
|
||||
var new_animation_tags := Global.animation_tags.duplicate(true)
|
||||
if current_tag_id == Global.animation_tags.size():
|
||||
new_animation_tags.append([tag_name, tag_color, tag_from, tag_to])
|
||||
else:
|
||||
new_animation_tags[current_tag_id][0] = tag_name
|
||||
new_animation_tags[current_tag_id][1] = tag_color
|
||||
new_animation_tags[current_tag_id][2] = tag_from
|
||||
new_animation_tags[current_tag_id][3] = tag_to
|
||||
|
||||
# Handle Undo/Redo
|
||||
Global.undos += 1
|
||||
Global.undo_redo.create_action("Modify Frame Tag")
|
||||
Global.undo_redo.add_do_method(Global, "general_redo")
|
||||
Global.undo_redo.add_undo_method(Global, "general_undo")
|
||||
Global.undo_redo.add_do_property(Global, "animation_tags", new_animation_tags)
|
||||
Global.undo_redo.add_undo_property(Global, "animation_tags", Global.animation_tags)
|
||||
Global.undo_redo.commit_action()
|
||||
_on_FrameTagDialog_about_to_show()
|
||||
|
||||
|
||||
func _on_TagOptions_custom_action(action : String) -> void:
|
||||
if action == "delete_tag":
|
||||
var new_animation_tags := Global.animation_tags.duplicate(true)
|
||||
new_animation_tags.remove(current_tag_id)
|
||||
# Handle Undo/Redo
|
||||
Global.undos += 1
|
||||
Global.undo_redo.create_action("Delete Frame Tag")
|
||||
Global.undo_redo.add_do_method(Global, "general_redo")
|
||||
Global.undo_redo.add_undo_method(Global, "general_undo")
|
||||
Global.undo_redo.add_do_property(Global, "animation_tags", new_animation_tags)
|
||||
Global.undo_redo.add_undo_property(Global, "animation_tags", Global.animation_tags)
|
||||
Global.undo_redo.commit_action()
|
||||
|
||||
options_dialog.hide()
|
||||
_on_FrameTagDialog_about_to_show()
|
||||
|
||||
|
||||
func _on_TagOptions_popup_hide() -> void:
|
||||
if delete_tag_button:
|
||||
delete_tag_button.visible = false
|
||||
|
||||
|
||||
func _on_PlayOnlyTags_toggled(button_pressed : bool) -> void:
|
||||
Global.play_only_tags = button_pressed
|
170
src/UI/Dialogs/FrameTagDialog.tscn
Normal file
170
src/UI/Dialogs/FrameTagDialog.tscn
Normal file
|
@ -0,0 +1,170 @@
|
|||
[gd_scene load_steps=3 format=2]
|
||||
|
||||
[ext_resource path="res://src/UI/Dialogs/FrameTagDialog.gd" type="Script" id=1]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/new_frame.png" type="Texture" id=2]
|
||||
|
||||
|
||||
|
||||
[node name="FrameTagDialog" type="AcceptDialog"]
|
||||
margin_right = 83.0
|
||||
margin_bottom = 58.0
|
||||
rect_min_size = Vector2( 400, 200 )
|
||||
window_title = "Frame Tag Properties"
|
||||
resizable = true
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = 8.0
|
||||
margin_top = 8.0
|
||||
margin_right = -8.0
|
||||
margin_bottom = -36.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer"]
|
||||
margin_right = 384.0
|
||||
margin_bottom = 128.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="VBoxTagContainer" type="VBoxContainer" parent="VBoxContainer/ScrollContainer"]
|
||||
margin_right = 384.0
|
||||
margin_bottom = 28.0
|
||||
size_flags_horizontal = 3
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="VBoxContainer/ScrollContainer/VBoxTagContainer"]
|
||||
margin_right = 384.0
|
||||
margin_bottom = 4.0
|
||||
size_flags_horizontal = 3
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="AddTag" type="Button" parent="VBoxContainer/ScrollContainer/VBoxTagContainer" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_top = 8.0
|
||||
margin_right = 20.0
|
||||
margin_bottom = 28.0
|
||||
rect_min_size = Vector2( 20, 0 )
|
||||
hint_tooltip = "Add a new frame tag"
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 0
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="VBoxContainer/ScrollContainer/VBoxTagContainer/AddTag"]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = -6.0
|
||||
margin_top = -6.0
|
||||
margin_right = 6.0
|
||||
margin_bottom = 6.0
|
||||
texture = ExtResource( 2 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="PlayOnlyTags" type="CheckBox" parent="VBoxContainer"]
|
||||
margin_top = 132.0
|
||||
margin_right = 333.0
|
||||
margin_bottom = 156.0
|
||||
hint_tooltip = "If it's selected, the animation plays only on the frames that have the same tag.
|
||||
If it's not, the animation will play for all frames, ignoring tags."
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 0
|
||||
pressed = true
|
||||
text = "Animation plays only on frames of the same tag"
|
||||
|
||||
[node name="TagOptions" type="ConfirmationDialog" parent="."]
|
||||
margin_left = 8.0
|
||||
margin_top = 8.0
|
||||
margin_right = 392.0
|
||||
margin_bottom = 164.0
|
||||
|
||||
[node name="GridContainer" type="GridContainer" parent="TagOptions"]
|
||||
margin_left = 8.0
|
||||
margin_top = 8.0
|
||||
margin_right = 376.0
|
||||
margin_bottom = 120.0
|
||||
custom_constants/vseparation = 8
|
||||
custom_constants/hseparation = 8
|
||||
columns = 4
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="NameLabel" type="Label" parent="TagOptions/GridContainer"]
|
||||
margin_top = 5.0
|
||||
margin_right = 42.0
|
||||
margin_bottom = 19.0
|
||||
text = "Name:"
|
||||
|
||||
[node name="NameLineEdit" type="LineEdit" parent="TagOptions/GridContainer"]
|
||||
margin_left = 50.0
|
||||
margin_right = 124.0
|
||||
margin_bottom = 24.0
|
||||
caret_blink = true
|
||||
caret_blink_speed = 0.5
|
||||
|
||||
[node name="ColorLabel" type="Label" parent="TagOptions/GridContainer"]
|
||||
margin_left = 132.0
|
||||
margin_top = 5.0
|
||||
margin_right = 169.0
|
||||
margin_bottom = 19.0
|
||||
text = "Color:"
|
||||
|
||||
[node name="ColorPickerButton" type="ColorPickerButton" parent="TagOptions/GridContainer"]
|
||||
margin_left = 177.0
|
||||
margin_right = 251.0
|
||||
margin_bottom = 24.0
|
||||
mouse_default_cursor_shape = 2
|
||||
color = Color( 1, 0, 0, 1 )
|
||||
|
||||
[node name="FromLabel" type="Label" parent="TagOptions/GridContainer"]
|
||||
margin_top = 37.0
|
||||
margin_right = 42.0
|
||||
margin_bottom = 51.0
|
||||
text = "From:"
|
||||
|
||||
[node name="FromSpinBox" type="SpinBox" parent="TagOptions/GridContainer"]
|
||||
margin_left = 50.0
|
||||
margin_top = 32.0
|
||||
margin_right = 124.0
|
||||
margin_bottom = 56.0
|
||||
mouse_default_cursor_shape = 2
|
||||
min_value = 1.0
|
||||
value = 1.0
|
||||
|
||||
[node name="ToLabel" type="Label" parent="TagOptions/GridContainer"]
|
||||
margin_left = 132.0
|
||||
margin_top = 37.0
|
||||
margin_right = 169.0
|
||||
margin_bottom = 51.0
|
||||
text = "To:"
|
||||
|
||||
[node name="ToSpinBox" type="SpinBox" parent="TagOptions/GridContainer"]
|
||||
margin_left = 177.0
|
||||
margin_top = 32.0
|
||||
margin_right = 251.0
|
||||
margin_bottom = 56.0
|
||||
mouse_default_cursor_shape = 2
|
||||
min_value = 1.0
|
||||
value = 1.0
|
||||
[connection signal="about_to_show" from="." to="." method="_on_FrameTagDialog_about_to_show"]
|
||||
[connection signal="popup_hide" from="." to="." method="_on_FrameTagDialog_popup_hide"]
|
||||
[connection signal="pressed" from="VBoxContainer/ScrollContainer/VBoxTagContainer/AddTag" to="." method="_on_AddTag_pressed"]
|
||||
[connection signal="toggled" from="VBoxContainer/PlayOnlyTags" to="." method="_on_PlayOnlyTags_toggled"]
|
||||
[connection signal="confirmed" from="TagOptions" to="." method="_on_TagOptions_confirmed"]
|
||||
[connection signal="custom_action" from="TagOptions" to="." method="_on_TagOptions_custom_action"]
|
||||
[connection signal="popup_hide" from="TagOptions" to="." method="_on_TagOptions_popup_hide"]
|
100
src/UI/Dialogs/HSVDialog.gd
Normal file
100
src/UI/Dialogs/HSVDialog.gd
Normal file
|
@ -0,0 +1,100 @@
|
|||
extends WindowDialog
|
||||
|
||||
var current_layer : Image
|
||||
var preview_image : Image
|
||||
var preview_texture : ImageTexture
|
||||
|
||||
onready var hue_slider = $MarginContainer/VBoxContainer/HBoxContainer/Sliders/Hue
|
||||
onready var sat_slider = $MarginContainer/VBoxContainer/HBoxContainer/Sliders/Saturation
|
||||
onready var val_slider = $MarginContainer/VBoxContainer/HBoxContainer/Sliders/Value
|
||||
|
||||
onready var hue_spinbox = $MarginContainer/VBoxContainer/HBoxContainer/TextBoxes/Hue
|
||||
onready var sat_spinbox = $MarginContainer/VBoxContainer/HBoxContainer/TextBoxes/Saturation
|
||||
onready var val_spinbox = $MarginContainer/VBoxContainer/HBoxContainer/TextBoxes/Value
|
||||
|
||||
onready var preview = $MarginContainer/VBoxContainer/TextureRect
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
current_layer = Image.new()
|
||||
preview_image = Image.new()
|
||||
preview_texture = ImageTexture.new()
|
||||
preview_texture.flags = 0
|
||||
|
||||
|
||||
func _on_HSVDialog_about_to_show() -> void:
|
||||
current_layer = Global.canvas.layers[Global.current_layer][0]
|
||||
preview_image.copy_from(current_layer)
|
||||
update_preview()
|
||||
|
||||
|
||||
func _on_Cancel_pressed() -> void:
|
||||
visible = false
|
||||
reset()
|
||||
|
||||
|
||||
func _on_Apply_pressed() -> void:
|
||||
Global.canvas.handle_undo("Draw")
|
||||
Global.canvas.adjust_hsv(current_layer,0,hue_slider.value)
|
||||
Global.canvas.adjust_hsv(current_layer,1,sat_slider.value)
|
||||
Global.canvas.adjust_hsv(current_layer,2,val_slider.value)
|
||||
Global.canvas.update_texture(Global.current_layer)
|
||||
Global.canvas.handle_redo("Draw")
|
||||
reset()
|
||||
visible = false
|
||||
|
||||
|
||||
func reset() -> void:
|
||||
disconnect_signals()
|
||||
hue_slider.value = 0
|
||||
sat_slider.value = 0
|
||||
val_slider.value = 0
|
||||
hue_spinbox.value = 0
|
||||
sat_spinbox.value = 0
|
||||
val_spinbox.value = 0
|
||||
reconnect_signals()
|
||||
|
||||
|
||||
func update_preview() -> void:
|
||||
preview_image.copy_from(current_layer)
|
||||
Global.canvas.adjust_hsv(preview_image,0,hue_slider.value)
|
||||
Global.canvas.adjust_hsv(preview_image,1,sat_slider.value)
|
||||
Global.canvas.adjust_hsv(preview_image,2,val_slider.value)
|
||||
preview_texture.create_from_image(preview_image, 0)
|
||||
preview.texture = preview_texture
|
||||
|
||||
|
||||
func disconnect_signals() -> void:
|
||||
hue_slider.disconnect("value_changed",self,"_on_Hue_value_changed")
|
||||
sat_slider.disconnect("value_changed",self,"_on_Saturation_value_changed")
|
||||
val_slider.disconnect("value_changed",self,"_on_Value_value_changed")
|
||||
hue_spinbox.disconnect("value_changed",self,"_on_Hue_value_changed")
|
||||
sat_spinbox.disconnect("value_changed",self,"_on_Saturation_value_changed")
|
||||
val_spinbox.disconnect("value_changed",self,"_on_Value_value_changed")
|
||||
|
||||
|
||||
func reconnect_signals() -> void:
|
||||
hue_slider.connect("value_changed",self,"_on_Hue_value_changed")
|
||||
sat_slider.connect("value_changed",self,"_on_Saturation_value_changed")
|
||||
val_slider.connect("value_changed",self,"_on_Value_value_changed")
|
||||
hue_spinbox.connect("value_changed",self,"_on_Hue_value_changed")
|
||||
sat_spinbox.connect("value_changed",self,"_on_Saturation_value_changed")
|
||||
val_spinbox.connect("value_changed",self,"_on_Value_value_changed")
|
||||
|
||||
|
||||
func _on_Hue_value_changed(value : float) -> void:
|
||||
hue_spinbox.value = value
|
||||
hue_slider.value = value
|
||||
update_preview()
|
||||
|
||||
|
||||
func _on_Saturation_value_changed(value : float) -> void:
|
||||
sat_spinbox.value = value
|
||||
sat_slider.value = value
|
||||
update_preview()
|
||||
|
||||
|
||||
func _on_Value_value_changed(value : float) -> void:
|
||||
val_spinbox.value = value
|
||||
val_slider.value = value
|
||||
update_preview()
|
168
src/UI/Dialogs/HSVDialog.tscn
Normal file
168
src/UI/Dialogs/HSVDialog.tscn
Normal file
|
@ -0,0 +1,168 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://src/UI/Dialogs/HSVDialog.gd" type="Script" id=1]
|
||||
|
||||
|
||||
|
||||
[node name="HSVDialog" type="WindowDialog"]
|
||||
margin_left = 1.0
|
||||
margin_top = -1.0
|
||||
margin_right = 464.0
|
||||
margin_bottom = 318.0
|
||||
window_title = "Adjust HSV"
|
||||
resizable = true
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
custom_constants/margin_right = 5
|
||||
custom_constants/margin_top = 5
|
||||
custom_constants/margin_left = 5
|
||||
custom_constants/margin_bottom = 5
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
|
||||
margin_left = 5.0
|
||||
margin_top = 5.0
|
||||
margin_right = 458.0
|
||||
margin_bottom = 314.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer"]
|
||||
margin_right = 453.0
|
||||
margin_bottom = 197.0
|
||||
size_flags_vertical = 3
|
||||
expand = true
|
||||
stretch_mode = 6
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
|
||||
margin_top = 201.0
|
||||
margin_right = 453.0
|
||||
margin_bottom = 285.0
|
||||
custom_constants/separation = 10
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Names" type="VBoxContainer" parent="MarginContainer/VBoxContainer/HBoxContainer"]
|
||||
margin_right = 82.0
|
||||
margin_bottom = 84.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_stretch_ratio = 0.9
|
||||
custom_constants/separation = 8
|
||||
|
||||
[node name="Hue" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer/Names"]
|
||||
margin_right = 82.0
|
||||
margin_bottom = 14.0
|
||||
text = "Hue"
|
||||
align = 2
|
||||
|
||||
[node name="Saturation" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer/Names"]
|
||||
margin_top = 22.0
|
||||
margin_right = 82.0
|
||||
margin_bottom = 36.0
|
||||
text = "Saturation"
|
||||
align = 2
|
||||
|
||||
[node name="Value" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer/Names"]
|
||||
margin_top = 44.0
|
||||
margin_right = 82.0
|
||||
margin_bottom = 58.0
|
||||
text = "Value"
|
||||
align = 2
|
||||
|
||||
[node name="Sliders" type="VBoxContainer" parent="MarginContainer/VBoxContainer/HBoxContainer"]
|
||||
margin_left = 92.0
|
||||
margin_right = 368.0
|
||||
margin_bottom = 84.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_stretch_ratio = 3.0
|
||||
custom_constants/separation = 7
|
||||
|
||||
[node name="Hue" type="HSlider" parent="MarginContainer/VBoxContainer/HBoxContainer/Sliders"]
|
||||
margin_right = 276.0
|
||||
margin_bottom = 16.0
|
||||
mouse_default_cursor_shape = 2
|
||||
min_value = -180.0
|
||||
max_value = 180.0
|
||||
|
||||
[node name="Saturation" type="HSlider" parent="MarginContainer/VBoxContainer/HBoxContainer/Sliders"]
|
||||
margin_top = 23.0
|
||||
margin_right = 276.0
|
||||
margin_bottom = 39.0
|
||||
mouse_default_cursor_shape = 2
|
||||
min_value = -100.0
|
||||
|
||||
[node name="Value" type="HSlider" parent="MarginContainer/VBoxContainer/HBoxContainer/Sliders"]
|
||||
margin_top = 46.0
|
||||
margin_right = 276.0
|
||||
margin_bottom = 62.0
|
||||
mouse_default_cursor_shape = 2
|
||||
min_value = -100.0
|
||||
|
||||
[node name="TextBoxes" type="VBoxContainer" parent="MarginContainer/VBoxContainer/HBoxContainer"]
|
||||
margin_left = 378.0
|
||||
margin_right = 452.0
|
||||
margin_bottom = 84.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_stretch_ratio = 0.0
|
||||
custom_constants/separation = 6
|
||||
|
||||
[node name="Hue" type="SpinBox" parent="MarginContainer/VBoxContainer/HBoxContainer/TextBoxes"]
|
||||
margin_right = 74.0
|
||||
margin_bottom = 24.0
|
||||
mouse_default_cursor_shape = 1
|
||||
min_value = -180.0
|
||||
max_value = 180.0
|
||||
|
||||
[node name="Saturation" type="SpinBox" parent="MarginContainer/VBoxContainer/HBoxContainer/TextBoxes"]
|
||||
margin_top = 30.0
|
||||
margin_right = 74.0
|
||||
margin_bottom = 54.0
|
||||
mouse_default_cursor_shape = 1
|
||||
min_value = -100.0
|
||||
|
||||
[node name="Value" type="SpinBox" parent="MarginContainer/VBoxContainer/HBoxContainer/TextBoxes"]
|
||||
margin_top = 60.0
|
||||
margin_right = 74.0
|
||||
margin_bottom = 84.0
|
||||
mouse_default_cursor_shape = 1
|
||||
min_value = -100.0
|
||||
|
||||
[node name="HBoxContainer2" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
|
||||
margin_top = 289.0
|
||||
margin_right = 453.0
|
||||
margin_bottom = 309.0
|
||||
custom_constants/separation = 16
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Apply" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer2"]
|
||||
margin_right = 218.0
|
||||
margin_bottom = 20.0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Apply"
|
||||
|
||||
[node name="Cancel" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer2"]
|
||||
margin_left = 234.0
|
||||
margin_right = 453.0
|
||||
margin_bottom = 20.0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Cancel"
|
||||
[connection signal="about_to_show" from="." to="." method="_on_HSVDialog_about_to_show"]
|
||||
[connection signal="value_changed" from="MarginContainer/VBoxContainer/HBoxContainer/Sliders/Hue" to="." method="_on_Hue_value_changed"]
|
||||
[connection signal="value_changed" from="MarginContainer/VBoxContainer/HBoxContainer/Sliders/Saturation" to="." method="_on_Saturation_value_changed"]
|
||||
[connection signal="value_changed" from="MarginContainer/VBoxContainer/HBoxContainer/Sliders/Value" to="." method="_on_Value_value_changed"]
|
||||
[connection signal="value_changed" from="MarginContainer/VBoxContainer/HBoxContainer/TextBoxes/Hue" to="." method="_on_Hue_value_changed"]
|
||||
[connection signal="value_changed" from="MarginContainer/VBoxContainer/HBoxContainer/TextBoxes/Saturation" to="." method="_on_Saturation_value_changed"]
|
||||
[connection signal="value_changed" from="MarginContainer/VBoxContainer/HBoxContainer/TextBoxes/Value" to="." method="_on_Value_value_changed"]
|
||||
[connection signal="pressed" from="MarginContainer/VBoxContainer/HBoxContainer2/Apply" to="." method="_on_Apply_pressed"]
|
||||
[connection signal="pressed" from="MarginContainer/VBoxContainer/HBoxContainer2/Cancel" to="." method="_on_Cancel_pressed"]
|
146
src/UI/Dialogs/ImportSprites.gd
Normal file
146
src/UI/Dialogs/ImportSprites.gd
Normal file
|
@ -0,0 +1,146 @@
|
|||
extends FileDialog
|
||||
|
||||
var new_frame := true
|
||||
var import_spritesheet := false
|
||||
var spritesheet_horizontal := 1
|
||||
var spritesheet_vertical := 1
|
||||
|
||||
func _ready() -> void:
|
||||
var children := []
|
||||
for i in range(get_child_count()):
|
||||
if i > 7:
|
||||
children.append(get_child(i))
|
||||
|
||||
for child in children:
|
||||
remove_child(child)
|
||||
get_vbox().add_child(child)
|
||||
|
||||
|
||||
func _on_ImportAsNewFrame_pressed() -> void:
|
||||
new_frame = !new_frame
|
||||
|
||||
|
||||
func _on_ImportSpritesheet_pressed() -> void:
|
||||
import_spritesheet = !import_spritesheet
|
||||
var spritesheet_container = Global.find_node_by_name(self, "Spritesheet")
|
||||
spritesheet_container.visible = import_spritesheet
|
||||
|
||||
|
||||
func _on_HorizontalFrames_value_changed(value) -> void:
|
||||
spritesheet_horizontal = value
|
||||
|
||||
|
||||
func _on_VerticalFrames_value_changed(value) -> void:
|
||||
spritesheet_vertical = value
|
||||
|
||||
|
||||
func _on_ImportSprites_files_selected(paths : PoolStringArray) -> void:
|
||||
Global.control.opensprite_file_selected = true
|
||||
if !new_frame: # If we're not adding a new frame, delete the previous
|
||||
Global.clear_canvases()
|
||||
|
||||
var first_path : String = paths[0]
|
||||
var i : int = Global.canvases.size()
|
||||
if !import_spritesheet:
|
||||
# Find the biggest image and let it handle the camera zoom options
|
||||
var max_size : Vector2
|
||||
var biggest_canvas : Canvas
|
||||
for path in paths:
|
||||
var image := Image.new()
|
||||
var err := image.load(path)
|
||||
if err != OK: # An error occured
|
||||
var file_name : String = path.get_file()
|
||||
Global.error_dialog.set_text(tr("Can't load file '%s'.\nError code: %s") % [file_name, str(err)])
|
||||
Global.error_dialog.popup_centered()
|
||||
continue
|
||||
|
||||
var canvas : Canvas = load("res://src/Canvas.tscn").instance()
|
||||
canvas.size = image.get_size()
|
||||
image.convert(Image.FORMAT_RGBA8)
|
||||
image.lock()
|
||||
var tex := ImageTexture.new()
|
||||
tex.create_from_image(image, 0)
|
||||
# Store [Image, ImageTexture, Opacity]
|
||||
canvas.layers.append([image, tex, 1])
|
||||
|
||||
for _i in range(1, Global.layers.size()):
|
||||
var empty_sprite := Image.new()
|
||||
empty_sprite.create(canvas.size.x, canvas.size.y, false, Image.FORMAT_RGBA8)
|
||||
empty_sprite.fill(Color(0, 0, 0, 0))
|
||||
empty_sprite.lock()
|
||||
|
||||
var empty_tex := ImageTexture.new()
|
||||
empty_tex.create_from_image(empty_sprite, 0)
|
||||
|
||||
# Store [Image, ImageTexture, Opacity]
|
||||
canvas.layers.append([empty_sprite, empty_tex, 1])
|
||||
|
||||
canvas.frame = i
|
||||
Global.canvases.append(canvas)
|
||||
Global.canvas_parent.add_child(canvas)
|
||||
canvas.visible = false
|
||||
if path == paths[0]: # If it's the first file
|
||||
max_size = canvas.size
|
||||
biggest_canvas = canvas
|
||||
else:
|
||||
if canvas.size > max_size:
|
||||
biggest_canvas = canvas
|
||||
|
||||
i += 1
|
||||
|
||||
if biggest_canvas:
|
||||
biggest_canvas.camera_zoom()
|
||||
|
||||
else:
|
||||
var image := Image.new()
|
||||
var err := image.load(first_path)
|
||||
if err != OK: # An error occured
|
||||
var file_name : String = first_path.get_file()
|
||||
Global.error_dialog.set_text(tr("Can't load file '%s'.\nError code: %s") % [file_name, str(err)])
|
||||
Global.error_dialog.popup_centered()
|
||||
return
|
||||
|
||||
spritesheet_horizontal = min(spritesheet_horizontal, image.get_size().x)
|
||||
spritesheet_vertical = min(spritesheet_vertical, image.get_size().y)
|
||||
var frame_width := image.get_size().x / spritesheet_horizontal
|
||||
var frame_height := image.get_size().y / spritesheet_vertical
|
||||
for yy in range(spritesheet_vertical):
|
||||
for xx in range(spritesheet_horizontal):
|
||||
var canvas : Canvas = load("res://src/Canvas.tscn").instance()
|
||||
var cropped_image := Image.new()
|
||||
cropped_image = image.get_rect(Rect2(frame_width * xx, frame_height * yy, frame_width, frame_height))
|
||||
canvas.size = cropped_image.get_size()
|
||||
cropped_image.convert(Image.FORMAT_RGBA8)
|
||||
cropped_image.lock()
|
||||
var tex := ImageTexture.new()
|
||||
tex.create_from_image(cropped_image, 0)
|
||||
# Store [Image, ImageTexture, Opacity]
|
||||
canvas.layers.append([cropped_image, tex, 1])
|
||||
for _i in range(1, Global.layers.size()):
|
||||
var empty_sprite := Image.new()
|
||||
empty_sprite.create(canvas.size.x, canvas.size.y, false, Image.FORMAT_RGBA8)
|
||||
empty_sprite.fill(Color(0, 0, 0, 0))
|
||||
empty_sprite.lock()
|
||||
|
||||
var empty_tex := ImageTexture.new()
|
||||
empty_tex.create_from_image(empty_sprite, 0)
|
||||
|
||||
# Store [Image, ImageTexture, Opacity]
|
||||
canvas.layers.append([empty_sprite, empty_tex, 1])
|
||||
|
||||
canvas.frame = i
|
||||
Global.canvases.append(canvas)
|
||||
Global.canvas_parent.add_child(canvas)
|
||||
canvas.visible = false
|
||||
|
||||
i += 1
|
||||
|
||||
Global.canvases[Global.canvases.size() - 1].camera_zoom()
|
||||
|
||||
Global.canvases = Global.canvases # Just to call Global.canvases_changed
|
||||
Global.current_frame = i - 1
|
||||
Global.canvas = Global.canvases[Global.canvases.size() - 1]
|
||||
Global.canvas.visible = true
|
||||
|
||||
Global.window_title = first_path.get_file() + " (" + tr("imported") + ") - Pixelorama"
|
||||
|
78
src/UI/Dialogs/ImportSprites.tscn
Normal file
78
src/UI/Dialogs/ImportSprites.tscn
Normal file
|
@ -0,0 +1,78 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://src/UI/Dialogs/ImportSprites.gd" type="Script" id=1]
|
||||
|
||||
|
||||
|
||||
[node name="ImportSprites" type="FileDialog"]
|
||||
margin_right = 515.0
|
||||
margin_bottom = 348.0
|
||||
window_title = "Open File(s)"
|
||||
resizable = true
|
||||
mode = 1
|
||||
access = 2
|
||||
filters = PoolStringArray( "*.bmp ; BMP Image", "*.hdr ; Radiance HDR Image", "*.jpg,*.jpeg ; JPEG Image", "*.png ; PNG Image", "*.svg ; SVG Image", "*.tga ; TGA Image", "*.webp ; WebP Image" )
|
||||
current_dir = "C:/Users/Overloaded/Dropbox/Orama Founding Members/εταιρικα αρχεια/Godot Projects/Pixelorama"
|
||||
current_path = "C:/Users/Overloaded/Dropbox/Orama Founding Members/εταιρικα αρχεια/Godot Projects/Pixelorama/"
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="HBoxContainer2" type="HBoxContainer" parent="."]
|
||||
margin_left = 8.0
|
||||
margin_top = 8.0
|
||||
margin_right = 507.0
|
||||
margin_bottom = 312.0
|
||||
|
||||
[node name="ImportAsNewFrame" type="CheckBox" parent="HBoxContainer2"]
|
||||
margin_right = 161.0
|
||||
margin_bottom = 304.0
|
||||
mouse_default_cursor_shape = 2
|
||||
pressed = true
|
||||
text = "Import as new frame"
|
||||
|
||||
[node name="ImportSpritesheet" type="CheckBox" parent="HBoxContainer2"]
|
||||
margin_left = 165.0
|
||||
margin_right = 343.0
|
||||
margin_bottom = 304.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Import as a spritesheet"
|
||||
|
||||
[node name="Spritesheet" type="HBoxContainer" parent="."]
|
||||
visible = false
|
||||
margin_left = 8.0
|
||||
margin_top = 8.0
|
||||
margin_right = 507.0
|
||||
margin_bottom = 312.0
|
||||
|
||||
[node name="Label" type="Label" parent="Spritesheet"]
|
||||
margin_top = 1.0
|
||||
margin_right = 101.0
|
||||
margin_bottom = 16.0
|
||||
text = "Horizontal frames:"
|
||||
|
||||
[node name="HorizontalFrames" type="SpinBox" parent="Spritesheet"]
|
||||
margin_left = 105.0
|
||||
margin_right = 159.0
|
||||
margin_bottom = 17.0
|
||||
mouse_default_cursor_shape = 2
|
||||
min_value = 1.0
|
||||
value = 1.0
|
||||
|
||||
[node name="Label2" type="Label" parent="Spritesheet"]
|
||||
margin_left = 163.0
|
||||
margin_top = 1.0
|
||||
margin_right = 248.0
|
||||
margin_bottom = 16.0
|
||||
text = "Vertical frames:"
|
||||
|
||||
[node name="VerticalFrames" type="SpinBox" parent="Spritesheet"]
|
||||
margin_left = 252.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 17.0
|
||||
mouse_default_cursor_shape = 2
|
||||
min_value = 1.0
|
||||
value = 1.0
|
||||
[connection signal="files_selected" from="." to="." method="_on_ImportSprites_files_selected"]
|
||||
[connection signal="pressed" from="HBoxContainer2/ImportAsNewFrame" to="." method="_on_ImportAsNewFrame_pressed"]
|
||||
[connection signal="pressed" from="HBoxContainer2/ImportSpritesheet" to="." method="_on_ImportSpritesheet_pressed"]
|
||||
[connection signal="value_changed" from="Spritesheet/HorizontalFrames" to="." method="_on_HorizontalFrames_value_changed"]
|
||||
[connection signal="value_changed" from="Spritesheet/VerticalFrames" to="." method="_on_VerticalFrames_value_changed"]
|
7
src/UI/Dialogs/NoProjectEditedOrCreatedAlertDialog.tscn
Normal file
7
src/UI/Dialogs/NoProjectEditedOrCreatedAlertDialog.tscn
Normal file
|
@ -0,0 +1,7 @@
|
|||
[gd_scene format=2]
|
||||
|
||||
[node name="NoProjectEditedOrCreatedAlertDialog" type="AcceptDialog"]
|
||||
dialog_text = "You haven't saved or opened any project in Pixelorama yet!"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
7
src/UI/Dialogs/OpenLastProjectAlertDialog.tscn
Normal file
7
src/UI/Dialogs/OpenLastProjectAlertDialog.tscn
Normal file
|
@ -0,0 +1,7 @@
|
|||
[gd_scene format=2]
|
||||
|
||||
[node name="OpenLastProjectAlertDialog" type="AcceptDialog"]
|
||||
margin_right = 209.0
|
||||
margin_bottom = 58.0
|
||||
window_title = "Alarm!"
|
||||
dialog_text = "Cannot find last project file."
|
146
src/UI/Dialogs/OutlineDialog.gd
Normal file
146
src/UI/Dialogs/OutlineDialog.gd
Normal file
|
@ -0,0 +1,146 @@
|
|||
extends ConfirmationDialog
|
||||
|
||||
func _ready() -> void:
|
||||
$OptionsContainer/OutlineColor.get_picker().presets_visible = false
|
||||
|
||||
|
||||
func _on_OutlineDialog_confirmed() -> void:
|
||||
var outline_color : Color = $OptionsContainer/OutlineColor.color
|
||||
var thickness : int = $OptionsContainer/ThickValue.value
|
||||
var diagonal : bool = $OptionsContainer/DiagonalCheckBox.pressed
|
||||
var inside_image : bool = $OptionsContainer/InsideImageCheckBox.pressed
|
||||
|
||||
var image : Image = Global.canvas.layers[Global.current_layer][0]
|
||||
if image.is_invisible():
|
||||
return
|
||||
var new_image := Image.new()
|
||||
new_image.copy_from(image)
|
||||
new_image.lock()
|
||||
|
||||
Global.canvas.handle_undo("Draw")
|
||||
for xx in image.get_size().x:
|
||||
for yy in image.get_size().y:
|
||||
var pos = Vector2(xx, yy)
|
||||
var current_pixel := image.get_pixelv(pos)
|
||||
if current_pixel.a == 0:
|
||||
continue
|
||||
|
||||
for i in range(1, thickness + 1):
|
||||
if inside_image:
|
||||
var outline_pos : Vector2 = pos + Vector2.LEFT # Left
|
||||
if outline_pos.x < 0 || image.get_pixelv(outline_pos).a == 0:
|
||||
var new_pos : Vector2 = pos + Vector2.RIGHT * (i - 1)
|
||||
if new_pos.x < Global.canvas.size.x:
|
||||
var new_pixel = image.get_pixelv(new_pos)
|
||||
if new_pixel.a > 0:
|
||||
new_image.set_pixelv(new_pos, outline_color)
|
||||
|
||||
outline_pos = pos + Vector2.RIGHT # Right
|
||||
if outline_pos.x >= Global.canvas.size.x || image.get_pixelv(outline_pos).a == 0:
|
||||
var new_pos : Vector2 = pos + Vector2.LEFT * (i - 1)
|
||||
if new_pos.x >= 0:
|
||||
var new_pixel = image.get_pixelv(new_pos)
|
||||
if new_pixel.a > 0:
|
||||
new_image.set_pixelv(new_pos, outline_color)
|
||||
|
||||
outline_pos = pos + Vector2.UP # Up
|
||||
if outline_pos.y < 0 || image.get_pixelv(outline_pos).a == 0:
|
||||
var new_pos : Vector2 = pos + Vector2.DOWN * (i - 1)
|
||||
if new_pos.y < Global.canvas.size.y:
|
||||
var new_pixel = image.get_pixelv(new_pos)
|
||||
if new_pixel.a > 0:
|
||||
new_image.set_pixelv(new_pos, outline_color)
|
||||
|
||||
outline_pos = pos + Vector2.DOWN # Down
|
||||
if outline_pos.y >= Global.canvas.size.y || image.get_pixelv(outline_pos).a == 0:
|
||||
var new_pos : Vector2 = pos + Vector2.UP * (i - 1)
|
||||
if new_pos.y >= 0:
|
||||
var new_pixel = image.get_pixelv(new_pos)
|
||||
if new_pixel.a > 0:
|
||||
new_image.set_pixelv(new_pos, outline_color)
|
||||
|
||||
if diagonal:
|
||||
outline_pos = pos + (Vector2.LEFT + Vector2.UP) # Top left
|
||||
if (outline_pos.x < 0 && outline_pos.y < 0) || image.get_pixelv(outline_pos).a == 0:
|
||||
var new_pos : Vector2 = pos + (Vector2.RIGHT + Vector2.DOWN) * (i - 1)
|
||||
if new_pos.x < Global.canvas.size.x && new_pos.y < Global.canvas.size.y:
|
||||
var new_pixel = image.get_pixelv(new_pos)
|
||||
if new_pixel.a > 0:
|
||||
new_image.set_pixelv(new_pos, outline_color)
|
||||
|
||||
outline_pos = pos + (Vector2.LEFT + Vector2.DOWN) # Bottom left
|
||||
if (outline_pos.x < 0 && outline_pos.y >= Global.canvas.size.y) || image.get_pixelv(outline_pos).a == 0:
|
||||
var new_pos : Vector2 = pos + (Vector2.RIGHT + Vector2.UP) * (i - 1)
|
||||
if new_pos.x < Global.canvas.size.x && new_pos.y >= 0:
|
||||
var new_pixel = image.get_pixelv(new_pos)
|
||||
if new_pixel.a > 0:
|
||||
new_image.set_pixelv(new_pos, outline_color)
|
||||
|
||||
outline_pos = pos + (Vector2.RIGHT + Vector2.UP) # Top right
|
||||
if (outline_pos.x >= Global.canvas.size.x && outline_pos.y < 0) || image.get_pixelv(outline_pos).a == 0:
|
||||
var new_pos : Vector2 = pos + (Vector2.LEFT + Vector2.DOWN) * (i - 1)
|
||||
if new_pos.x >= 0 && new_pos.y < Global.canvas.size.y:
|
||||
var new_pixel = image.get_pixelv(new_pos)
|
||||
if new_pixel.a > 0:
|
||||
new_image.set_pixelv(new_pos, outline_color)
|
||||
|
||||
outline_pos = pos + (Vector2.RIGHT + Vector2.DOWN) # Bottom right
|
||||
if (outline_pos.x >= Global.canvas.size.x && outline_pos.y >= Global.canvas.size.y) || image.get_pixelv(outline_pos).a == 0:
|
||||
var new_pos : Vector2 = pos + (Vector2.LEFT + Vector2.UP) * (i - 1)
|
||||
if new_pos.x >= 0 && new_pos.y >= 0:
|
||||
var new_pixel = image.get_pixelv(new_pos)
|
||||
if new_pixel.a > 0:
|
||||
new_image.set_pixelv(new_pos, outline_color)
|
||||
|
||||
else:
|
||||
var new_pos : Vector2 = pos + Vector2.LEFT * i # Left
|
||||
if new_pos.x >= 0:
|
||||
var new_pixel = image.get_pixelv(new_pos)
|
||||
if new_pixel.a == 0:
|
||||
new_image.set_pixelv(new_pos, outline_color)
|
||||
|
||||
new_pos = pos + Vector2.RIGHT * i # Right
|
||||
if new_pos.x < Global.canvas.size.x:
|
||||
var new_pixel = image.get_pixelv(new_pos)
|
||||
if new_pixel.a == 0:
|
||||
new_image.set_pixelv(new_pos, outline_color)
|
||||
|
||||
new_pos = pos + Vector2.UP * i # Up
|
||||
if new_pos.y >= 0:
|
||||
var new_pixel = image.get_pixelv(new_pos)
|
||||
if new_pixel.a == 0:
|
||||
new_image.set_pixelv(new_pos, outline_color)
|
||||
|
||||
new_pos = pos + Vector2.DOWN * i # Down
|
||||
if new_pos.y < Global.canvas.size.y:
|
||||
var new_pixel = image.get_pixelv(new_pos)
|
||||
if new_pixel.a == 0:
|
||||
new_image.set_pixelv(new_pos, outline_color)
|
||||
|
||||
if diagonal:
|
||||
new_pos = pos + (Vector2.LEFT + Vector2.UP) * i # Top left
|
||||
if new_pos.x >= 0 && new_pos.y >= 0:
|
||||
var new_pixel = image.get_pixelv(new_pos)
|
||||
if new_pixel.a == 0:
|
||||
new_image.set_pixelv(new_pos, outline_color)
|
||||
|
||||
new_pos = pos + (Vector2.LEFT + Vector2.DOWN) * i # Bottom left
|
||||
if new_pos.x >= 0 && new_pos.y < Global.canvas.size.y:
|
||||
var new_pixel = image.get_pixelv(new_pos)
|
||||
if new_pixel.a == 0:
|
||||
new_image.set_pixelv(new_pos, outline_color)
|
||||
|
||||
new_pos = pos + (Vector2.RIGHT + Vector2.UP) * i # Top right
|
||||
if new_pos.x < Global.canvas.size.x && new_pos.y >= 0:
|
||||
var new_pixel = image.get_pixelv(new_pos)
|
||||
if new_pixel.a == 0:
|
||||
new_image.set_pixelv(new_pos, outline_color)
|
||||
|
||||
new_pos = pos + (Vector2.RIGHT + Vector2.DOWN) * i # Bottom right
|
||||
if new_pos.x < Global.canvas.size.x && new_pos.y < Global.canvas.size.y:
|
||||
var new_pixel = image.get_pixelv(new_pos)
|
||||
if new_pixel.a == 0:
|
||||
new_image.set_pixelv(new_pos, outline_color)
|
||||
|
||||
image.copy_from(new_image)
|
||||
Global.canvas.handle_redo("Draw")
|
70
src/UI/Dialogs/OutlineDialog.tscn
Normal file
70
src/UI/Dialogs/OutlineDialog.tscn
Normal file
|
@ -0,0 +1,70 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://src/UI/Dialogs/OutlineDialog.gd" type="Script" id=1]
|
||||
|
||||
|
||||
|
||||
[node name="OutlineDialog" type="ConfirmationDialog"]
|
||||
visible = true
|
||||
margin_right = 200.0
|
||||
margin_bottom = 70.0
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="OptionsContainer" type="GridContainer" parent="."]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = -121.0
|
||||
margin_top = -52.0
|
||||
margin_right = 121.0
|
||||
margin_bottom = 24.0
|
||||
custom_constants/vseparation = 4
|
||||
custom_constants/hseparation = 4
|
||||
columns = 2
|
||||
|
||||
[node name="ThickLabel" type="Label" parent="OptionsContainer"]
|
||||
margin_top = 5.0
|
||||
margin_right = 90.0
|
||||
margin_bottom = 19.0
|
||||
text = "Thickness:"
|
||||
|
||||
[node name="ThickValue" type="SpinBox" parent="OptionsContainer"]
|
||||
margin_left = 94.0
|
||||
margin_right = 242.0
|
||||
margin_bottom = 24.0
|
||||
mouse_default_cursor_shape = 2
|
||||
min_value = 1.0
|
||||
max_value = 16384.0
|
||||
value = 1.0
|
||||
suffix = "px"
|
||||
|
||||
[node name="OutlineColorLabel" type="Label" parent="OptionsContainer"]
|
||||
margin_top = 31.0
|
||||
margin_right = 90.0
|
||||
margin_bottom = 45.0
|
||||
text = "Fill with color:"
|
||||
|
||||
[node name="OutlineColor" type="ColorPickerButton" parent="OptionsContainer"]
|
||||
margin_left = 94.0
|
||||
margin_top = 28.0
|
||||
margin_right = 242.0
|
||||
margin_bottom = 48.0
|
||||
rect_min_size = Vector2( 64, 20 )
|
||||
color = Color( 1, 0, 0, 1 )
|
||||
|
||||
[node name="DiagonalCheckBox" type="CheckBox" parent="OptionsContainer"]
|
||||
margin_top = 52.0
|
||||
margin_right = 90.0
|
||||
margin_bottom = 76.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Diagonal"
|
||||
|
||||
[node name="InsideImageCheckBox" type="CheckBox" parent="OptionsContainer"]
|
||||
margin_left = 94.0
|
||||
margin_top = 52.0
|
||||
margin_right = 242.0
|
||||
margin_bottom = 76.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Place inside image"
|
||||
[connection signal="confirmed" from="." to="." method="_on_OutlineDialog_confirmed"]
|
555
src/UI/Dialogs/PreferencesDialog.gd
Normal file
555
src/UI/Dialogs/PreferencesDialog.gd
Normal file
|
@ -0,0 +1,555 @@
|
|||
extends AcceptDialog
|
||||
|
||||
onready var tree : Tree = $HSplitContainer/Tree
|
||||
onready var right_side : VBoxContainer = $HSplitContainer/ScrollContainer/VBoxContainer
|
||||
onready var general = $HSplitContainer/ScrollContainer/VBoxContainer/General
|
||||
onready var languages = $HSplitContainer/ScrollContainer/VBoxContainer/Languages
|
||||
onready var themes = $HSplitContainer/ScrollContainer/VBoxContainer/Themes
|
||||
onready var canvas = $HSplitContainer/ScrollContainer/VBoxContainer/Canvas
|
||||
onready var image = $HSplitContainer/ScrollContainer/VBoxContainer/Image
|
||||
onready var shortcuts = $HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts
|
||||
|
||||
onready var open_last_project_button = $HSplitContainer/ScrollContainer/VBoxContainer/General/OpenLastProject
|
||||
onready var smooth_zoom_button = $HSplitContainer/ScrollContainer/VBoxContainer/General/SmoothZoom
|
||||
onready var sensitivity_option = $HSplitContainer/ScrollContainer/VBoxContainer/General/PressureSentivity/PressureSensitivityOptionButton
|
||||
onready var left_tool_icon = $HSplitContainer/ScrollContainer/VBoxContainer/General/GridContainer/LeftToolIconCheckbox
|
||||
onready var right_tool_icon = $HSplitContainer/ScrollContainer/VBoxContainer/General/GridContainer/RightToolIconCheckbox
|
||||
|
||||
onready var default_width_value = $HSplitContainer/ScrollContainer/VBoxContainer/Image/ImageOptions/ImageDefaultWidth
|
||||
onready var default_height_value = $HSplitContainer/ScrollContainer/VBoxContainer/Image/ImageOptions/ImageDefaultHeight
|
||||
onready var default_fill_color = $HSplitContainer/ScrollContainer/VBoxContainer/Image/ImageOptions/DefaultFillColor
|
||||
|
||||
onready var grid_width_value = $HSplitContainer/ScrollContainer/VBoxContainer/Canvas/GridOptions/GridWidthValue
|
||||
onready var grid_height_value = $HSplitContainer/ScrollContainer/VBoxContainer/Canvas/GridOptions/GridHeightValue
|
||||
onready var grid_color = $HSplitContainer/ScrollContainer/VBoxContainer/Canvas/GridOptions/GridColor
|
||||
onready var guide_color = $HSplitContainer/ScrollContainer/VBoxContainer/Canvas/GuideOptions/GuideColor
|
||||
|
||||
onready var checker_size_value = $HSplitContainer/ScrollContainer/VBoxContainer/Canvas/CheckerOptions/CheckerSizeValue
|
||||
onready var checker_color_1 = $HSplitContainer/ScrollContainer/VBoxContainer/Canvas/CheckerOptions/CheckerColor1
|
||||
onready var checker_color_2 = $HSplitContainer/ScrollContainer/VBoxContainer/Canvas/CheckerOptions/CheckerColor2
|
||||
|
||||
# Shortcuts
|
||||
onready var theme_font_color : Color = $Popups/ShortcutSelector/EnteredShortcut.get_color("font_color")
|
||||
var default_shortcuts_preset := {}
|
||||
var custom_shortcuts_preset := {}
|
||||
var action_being_edited := ""
|
||||
var shortcut_already_assigned = false
|
||||
var old_input_event : InputEventKey
|
||||
var new_input_event : InputEventKey
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
# Disable input until the shortcut selector is displayed
|
||||
set_process_input(false)
|
||||
|
||||
# Replace OK with Close since preference changes are being applied immediately, not after OK confirmation
|
||||
get_ok().text = tr("Close")
|
||||
|
||||
for child in languages.get_children():
|
||||
if child is Button:
|
||||
child.connect("pressed", self, "_on_Language_pressed", [child])
|
||||
child.hint_tooltip = child.name
|
||||
|
||||
for child in themes.get_children():
|
||||
if child is Button:
|
||||
child.connect("pressed", self, "_on_Theme_pressed", [child])
|
||||
|
||||
if Global.config_cache.has_section_key("preferences", "theme"):
|
||||
var theme_id = Global.config_cache.get_value("preferences", "theme")
|
||||
change_theme(theme_id)
|
||||
themes.get_child(theme_id).pressed = true
|
||||
else:
|
||||
change_theme(0)
|
||||
themes.get_child(0).pressed = true
|
||||
|
||||
# Set default values for General options
|
||||
if Global.config_cache.has_section_key("preferences", "open_last_project"):
|
||||
Global.open_last_project = Global.config_cache.get_value("preferences", "open_last_project")
|
||||
open_last_project_button.pressed = Global.open_last_project
|
||||
if Global.config_cache.has_section_key("preferences", "smooth_zoom"):
|
||||
Global.smooth_zoom = Global.config_cache.get_value("preferences", "smooth_zoom")
|
||||
smooth_zoom_button.pressed = Global.smooth_zoom
|
||||
if Global.config_cache.has_section_key("preferences", "pressure_sensitivity"):
|
||||
Global.pressure_sensitivity_mode = Global.config_cache.get_value("preferences", "pressure_sensitivity")
|
||||
sensitivity_option.selected = Global.pressure_sensitivity_mode
|
||||
|
||||
if Global.config_cache.has_section_key("preferences", "show_left_tool_icon"):
|
||||
Global.show_left_tool_icon = Global.config_cache.get_value("preferences", "show_left_tool_icon")
|
||||
left_tool_icon.pressed = Global.show_left_tool_icon
|
||||
if Global.config_cache.has_section_key("preferences", "show_right_tool_icon"):
|
||||
Global.show_right_tool_icon = Global.config_cache.get_value("preferences", "show_right_tool_icon")
|
||||
right_tool_icon.pressed = Global.show_right_tool_icon
|
||||
|
||||
# Get autosave settings
|
||||
if Global.config_cache.has_section_key("preferences", "autosave_interval"):
|
||||
var autosave_interval = Global.config_cache.get_value("preferences", "autosave_interval")
|
||||
OpenSave.set_autosave_interval(autosave_interval)
|
||||
general.get_node("AutosaveInterval/AutosaveInterval").value = autosave_interval
|
||||
if Global.config_cache.has_section_key("preferences", "enable_autosave"):
|
||||
var enable_autosave = Global.config_cache.get_value("preferences", "enable_autosave")
|
||||
OpenSave.toggle_autosave(enable_autosave)
|
||||
general.get_node("EnableAutosave").pressed = enable_autosave
|
||||
|
||||
# Set default values for Canvas options
|
||||
if Global.config_cache.has_section_key("preferences", "grid_size"):
|
||||
var grid_size = Global.config_cache.get_value("preferences", "grid_size")
|
||||
Global.grid_width = int(grid_size.x)
|
||||
Global.grid_height = int(grid_size.y)
|
||||
grid_width_value.value = grid_size.x
|
||||
grid_height_value.value = grid_size.y
|
||||
|
||||
if Global.config_cache.has_section_key("preferences", "grid_color"):
|
||||
Global.grid_color = Global.config_cache.get_value("preferences", "grid_color")
|
||||
grid_color.color = Global.grid_color
|
||||
|
||||
if Global.config_cache.has_section_key("preferences", "checker_size"):
|
||||
var checker_size = Global.config_cache.get_value("preferences", "checker_size")
|
||||
Global.checker_size = int(checker_size)
|
||||
checker_size_value.value = checker_size
|
||||
|
||||
if Global.config_cache.has_section_key("preferences", "checker_color_1"):
|
||||
Global.checker_color_1 = Global.config_cache.get_value("preferences", "checker_color_1")
|
||||
checker_color_1.color = Global.checker_color_1
|
||||
|
||||
if Global.config_cache.has_section_key("preferences", "checker_color_2"):
|
||||
Global.checker_color_2 = Global.config_cache.get_value("preferences", "checker_color_2")
|
||||
checker_color_2.color = Global.checker_color_2
|
||||
|
||||
Global.transparent_checker._ready()
|
||||
|
||||
if Global.config_cache.has_section_key("preferences", "guide_color"):
|
||||
Global.guide_color = Global.config_cache.get_value("preferences", "guide_color")
|
||||
for canvas in Global.canvases:
|
||||
for guide in canvas.get_children():
|
||||
if guide is Guide:
|
||||
guide.default_color = Global.guide_color
|
||||
guide_color.color = Global.guide_color
|
||||
|
||||
# Set default values for Image
|
||||
if Global.config_cache.has_section_key("preferences", "default_width"):
|
||||
var default_width = Global.config_cache.get_value("preferences", "default_width")
|
||||
Global.default_image_width = int(default_width)
|
||||
default_width_value.value = Global.default_image_width
|
||||
|
||||
if Global.config_cache.has_section_key("preferences", "default_height"):
|
||||
var default_height = Global.config_cache.get_value("preferences", "default_height")
|
||||
Global.default_image_height = int(default_height)
|
||||
default_height_value.value = Global.default_image_height
|
||||
|
||||
if Global.config_cache.has_section_key("preferences", "default_fill_color"):
|
||||
var fill_color = Global.config_cache.get_value("preferences", "default_fill_color")
|
||||
Global.default_fill_color = fill_color
|
||||
default_fill_color.color = Global.default_fill_color
|
||||
|
||||
guide_color.get_picker().presets_visible = false
|
||||
grid_color.get_picker().presets_visible = false
|
||||
checker_color_1.get_picker().presets_visible = false
|
||||
checker_color_2.get_picker().presets_visible = false
|
||||
default_fill_color.get_picker().presets_visible = false
|
||||
|
||||
# Get default preset for shortcuts from project input map
|
||||
# Buttons in shortcuts selector should be called the same as actions
|
||||
for shortcut_grid_item in shortcuts.get_node("Shortcuts").get_children():
|
||||
if shortcut_grid_item is Button:
|
||||
var input_events = InputMap.get_action_list(shortcut_grid_item.name)
|
||||
if input_events.size() > 1:
|
||||
printerr("Every shortcut action should have just one input event assigned in input map")
|
||||
shortcut_grid_item.text = (input_events[0] as InputEventKey).as_text()
|
||||
shortcut_grid_item.connect("pressed", self, "_on_Shortcut_button_pressed", [shortcut_grid_item])
|
||||
default_shortcuts_preset[shortcut_grid_item.name] = input_events[0]
|
||||
|
||||
# Load custom shortcuts from the config file
|
||||
custom_shortcuts_preset = default_shortcuts_preset.duplicate()
|
||||
for action in default_shortcuts_preset:
|
||||
var saved_input_event = Global.config_cache.get_value("shortcuts", action, 0)
|
||||
if saved_input_event is InputEventKey:
|
||||
custom_shortcuts_preset[action] = saved_input_event
|
||||
|
||||
var shortcuts_preset = Global.config_cache.get_value("shortcuts", "shortcuts_preset", 0)
|
||||
shortcuts.get_node("HBoxContainer/PresetOptionButton").select(shortcuts_preset)
|
||||
_on_PresetOptionButton_item_selected(shortcuts_preset)
|
||||
|
||||
|
||||
func _input(event : InputEvent) -> void:
|
||||
if event is InputEventKey:
|
||||
if event.pressed:
|
||||
if event.scancode == KEY_ESCAPE:
|
||||
$Popups/ShortcutSelector.hide()
|
||||
else:
|
||||
# Check if shortcut was already used
|
||||
for action in InputMap.get_actions():
|
||||
for input_event in InputMap.get_action_list(action):
|
||||
if input_event is InputEventKey:
|
||||
if OS.get_scancode_string(input_event.get_scancode_with_modifiers()) == OS.get_scancode_string(event.get_scancode_with_modifiers()):
|
||||
$Popups/ShortcutSelector/EnteredShortcut.text = tr("Already assigned")
|
||||
$Popups/ShortcutSelector/EnteredShortcut.add_color_override("font_color", Color.crimson)
|
||||
get_tree().set_input_as_handled()
|
||||
shortcut_already_assigned = true
|
||||
return
|
||||
|
||||
# Store new shortcut
|
||||
shortcut_already_assigned = false
|
||||
old_input_event = InputMap.get_action_list(action_being_edited)[0]
|
||||
new_input_event = event
|
||||
$Popups/ShortcutSelector/EnteredShortcut.text = OS.get_scancode_string(event.get_scancode_with_modifiers())
|
||||
$Popups/ShortcutSelector/EnteredShortcut.add_color_override("font_color", theme_font_color)
|
||||
get_tree().set_input_as_handled()
|
||||
|
||||
|
||||
func _on_PreferencesDialog_about_to_show(changed_language := false) -> void:
|
||||
var root := tree.create_item()
|
||||
var general_button := tree.create_item(root)
|
||||
var language_button := tree.create_item(root)
|
||||
var theme_button := tree.create_item(root)
|
||||
var canvas_button := tree.create_item(root)
|
||||
var image_button := tree.create_item(root)
|
||||
var shortcuts_button := tree.create_item(root)
|
||||
|
||||
general_button.set_text(0, " " + tr("General"))
|
||||
# We use metadata to avoid being affected by translations
|
||||
general_button.set_metadata(0, "General")
|
||||
language_button.set_text(0, " " + tr("Language"))
|
||||
language_button.set_metadata(0, "Language")
|
||||
theme_button.set_text(0, " " + tr("Themes"))
|
||||
theme_button.set_metadata(0, "Themes")
|
||||
canvas_button.set_text(0, " " + tr("Canvas"))
|
||||
canvas_button.set_metadata(0, "Canvas")
|
||||
image_button.set_text(0, " " + tr("Image"))
|
||||
image_button.set_metadata(0, "Image")
|
||||
shortcuts_button.set_text(0, " " + tr("Shortcuts"))
|
||||
shortcuts_button.set_metadata(0, "Shortcuts")
|
||||
|
||||
if changed_language:
|
||||
language_button.select(0)
|
||||
else:
|
||||
general_button.select(0)
|
||||
|
||||
|
||||
func _on_PreferencesDialog_popup_hide() -> void:
|
||||
tree.clear()
|
||||
|
||||
|
||||
func _on_Tree_item_selected() -> void:
|
||||
for child in right_side.get_children():
|
||||
child.visible = false
|
||||
var selected : String = tree.get_selected().get_metadata(0)
|
||||
if "General" in selected:
|
||||
general.visible = true
|
||||
elif "Language" in selected:
|
||||
languages.visible = true
|
||||
elif "Themes" in selected:
|
||||
themes.visible = true
|
||||
elif "Canvas" in selected:
|
||||
canvas.visible = true
|
||||
elif "Image" in selected:
|
||||
image.visible = true
|
||||
elif "Shortcuts" in selected:
|
||||
shortcuts.visible = true
|
||||
|
||||
|
||||
func _on_PressureSensitivityOptionButton_item_selected(id : int) -> void:
|
||||
Global.pressure_sensitivity_mode = id
|
||||
Global.config_cache.set_value("preferences", "pressure_sensitivity", id)
|
||||
Global.config_cache.save("user://cache.ini")
|
||||
|
||||
|
||||
func _on_SmoothZoom_pressed() -> void:
|
||||
Global.smooth_zoom = !Global.smooth_zoom
|
||||
Global.config_cache.set_value("preferences", "smooth_zoom", Global.smooth_zoom)
|
||||
Global.config_cache.save("user://cache.ini")
|
||||
|
||||
|
||||
func _on_Language_pressed(button : Button) -> void:
|
||||
var index := 0
|
||||
var i := -1
|
||||
for child in languages.get_children():
|
||||
if child is Button:
|
||||
if child == button:
|
||||
button.pressed = true
|
||||
index = i
|
||||
else:
|
||||
child.pressed = false
|
||||
i += 1
|
||||
if index == -1:
|
||||
TranslationServer.set_locale(OS.get_locale())
|
||||
else:
|
||||
TranslationServer.set_locale(Global.loaded_locales[index])
|
||||
|
||||
if "zh" in TranslationServer.get_locale():
|
||||
Global.control.theme.default_font = preload("res://Assets/Fonts/CJK/NotoSansCJKtc-Regular.tres")
|
||||
else:
|
||||
Global.control.theme.default_font = preload("res://Assets/Fonts/Roboto-Regular.tres")
|
||||
|
||||
Global.config_cache.set_value("preferences", "locale", TranslationServer.get_locale())
|
||||
Global.config_cache.save("user://cache.ini")
|
||||
|
||||
# Update Translations
|
||||
Global.update_hint_tooltips()
|
||||
_on_PreferencesDialog_popup_hide()
|
||||
_on_PreferencesDialog_about_to_show(true)
|
||||
|
||||
|
||||
func _on_Theme_pressed(button : Button) -> void:
|
||||
var index := 0
|
||||
var i := 0
|
||||
for child in themes.get_children():
|
||||
if child is Button:
|
||||
if child == button:
|
||||
button.pressed = true
|
||||
index = i
|
||||
else:
|
||||
child.pressed = false
|
||||
i += 1
|
||||
|
||||
change_theme(index)
|
||||
|
||||
Global.config_cache.set_value("preferences", "theme", index)
|
||||
Global.config_cache.save("user://cache.ini")
|
||||
|
||||
|
||||
func change_theme(ID : int) -> void:
|
||||
var font = Global.control.theme.default_font
|
||||
var main_theme
|
||||
var top_menu_style
|
||||
var ruler_style
|
||||
if ID == 0: # Dark Theme
|
||||
Global.theme_type = "Dark"
|
||||
VisualServer.set_default_clear_color(Color(0.247059, 0.25098, 0.247059))
|
||||
main_theme = preload("res://Assets/themes/dark/theme.tres")
|
||||
top_menu_style = preload("res://Assets/themes/dark/top_menu_style.tres")
|
||||
ruler_style = preload("res://Assets/themes/dark/ruler_style.tres")
|
||||
elif ID == 1: # Gray Theme
|
||||
Global.theme_type = "Dark"
|
||||
VisualServer.set_default_clear_color(Color(0.301961, 0.301961, 0.301961))
|
||||
main_theme = preload("res://Assets/themes/gray/theme.tres")
|
||||
top_menu_style = preload("res://Assets/themes/gray/top_menu_style.tres")
|
||||
ruler_style = preload("res://Assets/themes/dark/ruler_style.tres")
|
||||
elif ID == 2: # Godot's Theme
|
||||
Global.theme_type = "Dark"
|
||||
VisualServer.set_default_clear_color(Color(0.27451, 0.278431, 0.305882))
|
||||
main_theme = preload("res://Assets/themes/godot/theme.tres")
|
||||
top_menu_style = preload("res://Assets/themes/godot/top_menu_style.tres")
|
||||
ruler_style = preload("res://Assets/themes/godot/ruler_style.tres")
|
||||
elif ID == 3: # Gold Theme
|
||||
Global.theme_type = "Gold"
|
||||
VisualServer.set_default_clear_color(Color(0.694118, 0.619608, 0.458824))
|
||||
main_theme = preload("res://Assets/themes/gold/theme.tres")
|
||||
top_menu_style = preload("res://Assets/themes/gold/top_menu_style.tres")
|
||||
ruler_style = preload("res://Assets/themes/gold/ruler_style.tres")
|
||||
elif ID == 4: # Light Theme
|
||||
Global.theme_type = "Light"
|
||||
VisualServer.set_default_clear_color(Color(0.705882, 0.705882, 0.705882))
|
||||
main_theme = preload("res://Assets/themes/light/theme.tres")
|
||||
top_menu_style = preload("res://Assets/themes/light/top_menu_style.tres")
|
||||
ruler_style = preload("res://Assets/themes/light/ruler_style.tres")
|
||||
|
||||
Global.control.theme = main_theme
|
||||
Global.control.theme.default_font = font
|
||||
Global.top_menu_container.add_stylebox_override("panel", top_menu_style)
|
||||
Global.horizontal_ruler.add_stylebox_override("normal", ruler_style)
|
||||
Global.horizontal_ruler.add_stylebox_override("pressed", ruler_style)
|
||||
Global.horizontal_ruler.add_stylebox_override("hover", ruler_style)
|
||||
Global.horizontal_ruler.add_stylebox_override("focus", ruler_style)
|
||||
Global.vertical_ruler.add_stylebox_override("normal", ruler_style)
|
||||
Global.vertical_ruler.add_stylebox_override("pressed", ruler_style)
|
||||
Global.vertical_ruler.add_stylebox_override("hover", ruler_style)
|
||||
Global.vertical_ruler.add_stylebox_override("focus", ruler_style)
|
||||
|
||||
for button in get_tree().get_nodes_in_group("UIButtons"):
|
||||
if button is TextureButton:
|
||||
var last_backslash = button.texture_normal.resource_path.get_base_dir().find_last("/")
|
||||
var button_category = button.texture_normal.resource_path.get_base_dir().right(last_backslash + 1)
|
||||
var normal_file_name = button.texture_normal.resource_path.get_file()
|
||||
button.texture_normal = load("res://Assets/Graphics/%s Themes/%s/%s" % [Global.theme_type, button_category, normal_file_name])
|
||||
if button.texture_pressed:
|
||||
var pressed_file_name = button.texture_pressed.resource_path.get_file()
|
||||
button.texture_pressed = load("res://Assets/Graphics/%s Themes/%s/%s" % [Global.theme_type, button_category, pressed_file_name])
|
||||
if button.texture_hover:
|
||||
var hover_file_name = button.texture_hover.resource_path.get_file()
|
||||
button.texture_hover = load("res://Assets/Graphics/%s Themes/%s/%s" % [Global.theme_type, button_category, hover_file_name])
|
||||
if button.texture_disabled:
|
||||
var disabled_file_name = button.texture_disabled.resource_path.get_file()
|
||||
button.texture_disabled = load("res://Assets/Graphics/%s Themes/%s/%s" % [Global.theme_type, button_category, disabled_file_name])
|
||||
elif button is Button:
|
||||
var theme_type := Global.theme_type
|
||||
if theme_type == "Gold":
|
||||
theme_type = "Light"
|
||||
var texture : TextureRect = button.get_child(0)
|
||||
var last_backslash = texture.texture.resource_path.get_base_dir().find_last("/")
|
||||
var button_category = texture.texture.resource_path.get_base_dir().right(last_backslash + 1)
|
||||
var normal_file_name = texture.texture.resource_path.get_file()
|
||||
texture.texture = load("res://Assets/Graphics/%s Themes/%s/%s" % [theme_type, button_category, normal_file_name])
|
||||
|
||||
# Make sure the frame text gets updated
|
||||
Global.current_frame = Global.current_frame
|
||||
|
||||
$Popups/ShortcutSelector.theme = main_theme
|
||||
|
||||
|
||||
func apply_shortcuts_preset(preset) -> void:
|
||||
for action in preset:
|
||||
var old_input_event : InputEventKey = InputMap.get_action_list(action)[0]
|
||||
set_action_shortcut(action, old_input_event, preset[action])
|
||||
shortcuts.get_node("Shortcuts/" + action).text = OS.get_scancode_string(preset[action].get_scancode_with_modifiers())
|
||||
|
||||
|
||||
func toggle_shortcut_buttons(enabled : bool) -> void:
|
||||
for shortcut_grid_item in shortcuts.get_node("Shortcuts").get_children():
|
||||
if shortcut_grid_item is Button:
|
||||
shortcut_grid_item.disabled = not enabled
|
||||
if shortcut_grid_item.disabled:
|
||||
shortcut_grid_item.mouse_default_cursor_shape = Control.CURSOR_FORBIDDEN
|
||||
else:
|
||||
shortcut_grid_item.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
|
||||
|
||||
|
||||
func set_action_shortcut(action : String, old_input : InputEventKey, new_input : InputEventKey) -> void:
|
||||
InputMap.action_erase_event(action, old_input)
|
||||
InputMap.action_add_event(action, new_input)
|
||||
Global.update_hint_tooltips()
|
||||
# Set shortcut to switch colors button
|
||||
if action == "switch_colors":
|
||||
Global.color_switch_button.shortcut.shortcut = InputMap.get_action_list("switch_colors")[0]
|
||||
|
||||
|
||||
func _on_GridWidthValue_value_changed(value : float) -> void:
|
||||
Global.grid_width = value
|
||||
Global.canvas.update()
|
||||
Global.config_cache.set_value("preferences", "grid_size", Vector2(value, grid_height_value.value))
|
||||
Global.config_cache.save("user://cache.ini")
|
||||
|
||||
|
||||
func _on_GridHeightValue_value_changed(value : float) -> void:
|
||||
Global.grid_height = value
|
||||
Global.canvas.update()
|
||||
Global.config_cache.set_value("preferences", "grid_size", Vector2(grid_width_value.value, value))
|
||||
Global.config_cache.save("user://cache.ini")
|
||||
|
||||
|
||||
func _on_GridColor_color_changed(color : Color) -> void:
|
||||
Global.grid_color = color
|
||||
Global.canvas.update()
|
||||
Global.config_cache.set_value("preferences", "grid_color", color)
|
||||
Global.config_cache.save("user://cache.ini")
|
||||
|
||||
|
||||
func _on_CheckerSize_value_changed(value : float) -> void:
|
||||
Global.checker_size = value
|
||||
Global.transparent_checker._ready()
|
||||
Global.config_cache.set_value("preferences", "checker_size", value)
|
||||
Global.config_cache.save("user://cache.ini")
|
||||
|
||||
|
||||
func _on_CheckerColor1_color_changed(color : Color) -> void:
|
||||
Global.checker_color_1 = color
|
||||
Global.transparent_checker._ready()
|
||||
Global.config_cache.set_value("preferences", "checker_color_1", color)
|
||||
Global.config_cache.save("user://cache.ini")
|
||||
|
||||
|
||||
func _on_CheckerColor2_color_changed(color : Color) -> void:
|
||||
Global.checker_color_2 = color
|
||||
Global.transparent_checker._ready()
|
||||
Global.config_cache.set_value("preferences", "checker_color_2", color)
|
||||
Global.config_cache.save("user://cache.ini")
|
||||
|
||||
|
||||
func _on_GuideColor_color_changed(color : Color) -> void:
|
||||
Global.guide_color = color
|
||||
for canvas in Global.canvases:
|
||||
for guide in canvas.get_children():
|
||||
if guide is Guide:
|
||||
guide.default_color = color
|
||||
Global.config_cache.set_value("preferences", "guide_color", color)
|
||||
Global.config_cache.save("user://cache.ini")
|
||||
|
||||
|
||||
func _on_ImageDefaultWidth_value_changed(value: float) -> void:
|
||||
Global.default_image_width = value
|
||||
Global.config_cache.set_value("preferences", "default_width", value)
|
||||
Global.config_cache.save("user://cache.ini")
|
||||
|
||||
|
||||
func _on_ImageDefaultHeight_value_changed(value: float) -> void:
|
||||
Global.default_image_height = value
|
||||
Global.config_cache.set_value("preferences", "default_height", value)
|
||||
Global.config_cache.save("user://cache.ini")
|
||||
|
||||
|
||||
func _on_DefaultBackground_color_changed(color: Color) -> void:
|
||||
Global.default_fill_color = color
|
||||
Global.config_cache.set_value("preferences", "default_fill_color", color)
|
||||
Global.config_cache.save("user://cache.ini")
|
||||
|
||||
|
||||
func _on_LeftIndicatorCheckbox_toggled(button_pressed : bool) -> void:
|
||||
Global.left_square_indicator_visible = button_pressed
|
||||
|
||||
|
||||
func _on_RightIndicatorCheckbox_toggled(button_pressed : bool) -> void:
|
||||
Global.right_square_indicator_visible = button_pressed
|
||||
|
||||
|
||||
func _on_LeftToolIconCheckbox_toggled(button_pressed : bool) -> void:
|
||||
Global.show_left_tool_icon = button_pressed
|
||||
Global.config_cache.set_value("preferences", "show_left_tool_icon", Global.show_left_tool_icon)
|
||||
Global.config_cache.save("user://cache.ini")
|
||||
|
||||
|
||||
func _on_RightToolIconCheckbox_toggled(button_pressed : bool) -> void:
|
||||
Global.show_right_tool_icon = button_pressed
|
||||
Global.config_cache.set_value("preferences", "show_right_tool_icon", Global.show_right_tool_icon)
|
||||
Global.config_cache.save("user://cache.ini")
|
||||
|
||||
|
||||
func _on_Shortcut_button_pressed(button : Button) -> void:
|
||||
set_process_input(true)
|
||||
action_being_edited = button.name
|
||||
new_input_event = InputMap.get_action_list(button.name)[0]
|
||||
shortcut_already_assigned = true
|
||||
$Popups/ShortcutSelector.popup_centered()
|
||||
|
||||
|
||||
func _on_ShortcutSelector_popup_hide() -> void:
|
||||
set_process_input(false)
|
||||
$Popups/ShortcutSelector/EnteredShortcut.text = ""
|
||||
|
||||
|
||||
func _on_PresetOptionButton_item_selected(id : int) -> void:
|
||||
# Only custom preset which is modifiable
|
||||
toggle_shortcut_buttons(true if id == 1 else false)
|
||||
match id:
|
||||
0:
|
||||
apply_shortcuts_preset(default_shortcuts_preset)
|
||||
1:
|
||||
apply_shortcuts_preset(custom_shortcuts_preset)
|
||||
Global.config_cache.set_value("shortcuts", "shortcuts_preset", id)
|
||||
Global.config_cache.save("user://cache.ini")
|
||||
|
||||
|
||||
func _on_ShortcutSelector_confirmed() -> void:
|
||||
if not shortcut_already_assigned:
|
||||
set_action_shortcut(action_being_edited, old_input_event, new_input_event)
|
||||
custom_shortcuts_preset[action_being_edited] = new_input_event
|
||||
Global.config_cache.set_value("shortcuts", action_being_edited, new_input_event)
|
||||
Global.config_cache.save("user://cache.ini")
|
||||
shortcuts.get_node("Shortcuts/" + action_being_edited).text = OS.get_scancode_string(new_input_event.get_scancode_with_modifiers())
|
||||
$Popups/ShortcutSelector.hide()
|
||||
|
||||
|
||||
func _on_OpenLastProject_pressed() -> void:
|
||||
Global.open_last_project = !Global.open_last_project
|
||||
Global.config_cache.set_value("preferences", "open_last_project", Global.open_last_project)
|
||||
Global.config_cache.save("user://cache.ini")
|
||||
|
||||
|
||||
func _on_EnableAutosave_toggled(button_pressed : bool) -> void:
|
||||
OpenSave.toggle_autosave(button_pressed)
|
||||
Global.config_cache.set_value("preferences", "enable_autosave", button_pressed)
|
||||
Global.config_cache.save("user://cache.ini")
|
||||
|
||||
|
||||
func _on_AutosaveInterval_value_changed(value : float) -> void:
|
||||
OpenSave.set_autosave_interval(value)
|
||||
Global.config_cache.set_value("preferences", "autosave_interval", value)
|
||||
Global.config_cache.save("user://cache.ini")
|
875
src/UI/Dialogs/PreferencesDialog.tscn
Normal file
875
src/UI/Dialogs/PreferencesDialog.tscn
Normal file
|
@ -0,0 +1,875 @@
|
|||
[gd_scene load_steps=4 format=2]
|
||||
|
||||
[ext_resource path="res://src/UI/Dialogs/PreferencesDialog.gd" type="Script" id=1]
|
||||
[ext_resource path="res://Assets/Fonts/Roboto-Regular.tres" type="DynamicFont" id=2]
|
||||
[ext_resource path="res://Assets/Fonts/CJK/NotoSansCJKtc-Regular.tres" type="DynamicFont" id=3]
|
||||
|
||||
|
||||
|
||||
[node name="PreferencesDialog" type="AcceptDialog"]
|
||||
margin_left = -3.0
|
||||
margin_top = 9.0
|
||||
margin_right = 419.0
|
||||
margin_bottom = 1163.0
|
||||
rect_min_size = Vector2( 422, 340 )
|
||||
window_title = "Preferences"
|
||||
resizable = true
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_horizontal_guides_": [ ],
|
||||
"_edit_use_anchors_": false,
|
||||
"_edit_vertical_guides_": [ ]
|
||||
}
|
||||
|
||||
[node name="HSplitContainer" type="HSplitContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = 8.0
|
||||
margin_top = 8.0
|
||||
margin_right = -8.0
|
||||
margin_bottom = -36.0
|
||||
size_flags_horizontal = 3
|
||||
custom_constants/autohide = 0
|
||||
split_offset = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Tree" type="Tree" parent="HSplitContainer"]
|
||||
margin_right = 86.0
|
||||
margin_bottom = 1110.0
|
||||
rect_min_size = Vector2( 85, 0 )
|
||||
custom_constants/item_margin = -2
|
||||
hide_root = true
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="HSplitContainer"]
|
||||
margin_left = 98.0
|
||||
margin_right = 406.0
|
||||
margin_bottom = 1110.0
|
||||
rect_min_size = Vector2( 100, 0 )
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="HSplitContainer/ScrollContainer"]
|
||||
margin_right = 308.0
|
||||
margin_bottom = 1230.0
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="General" type="VBoxContainer" parent="HSplitContainer/ScrollContainer/VBoxContainer"]
|
||||
margin_right = 306.0
|
||||
margin_bottom = 180.0
|
||||
|
||||
[node name="SmoothZoom" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/General"]
|
||||
margin_right = 306.0
|
||||
margin_bottom = 24.0
|
||||
hint_tooltip = "Adds a smoother transition when zooming in or out"
|
||||
mouse_default_cursor_shape = 2
|
||||
pressed = true
|
||||
text = "Smooth Zoom"
|
||||
|
||||
[node name="HSeparator2" type="HSeparator" parent="HSplitContainer/ScrollContainer/VBoxContainer/General"]
|
||||
margin_top = 28.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 32.0
|
||||
|
||||
[node name="GridContainer" type="GridContainer" parent="HSplitContainer/ScrollContainer/VBoxContainer/General"]
|
||||
margin_top = 36.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 88.0
|
||||
custom_constants/vseparation = 4
|
||||
custom_constants/hseparation = 4
|
||||
columns = 2
|
||||
|
||||
[node name="LeftIndicatorCheckbox" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/General/GridContainer"]
|
||||
margin_right = 147.0
|
||||
margin_bottom = 24.0
|
||||
hint_tooltip = "Show left mouse pixel indicator or brush on the canvas when drawing"
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
pressed = true
|
||||
text = "Left pixel indicator"
|
||||
|
||||
[node name="RightIndicatorCheckbox" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/General/GridContainer"]
|
||||
margin_left = 151.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 24.0
|
||||
hint_tooltip = "Show right mouse pixel indicator or brush on the canvas when drawing"
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Right pixel indicator"
|
||||
|
||||
[node name="LeftToolIconCheckbox" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/General/GridContainer"]
|
||||
margin_top = 28.0
|
||||
margin_right = 147.0
|
||||
margin_bottom = 52.0
|
||||
hint_tooltip = "Displays an icon of the selected left tool next to the cursor on the canvas"
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
pressed = true
|
||||
text = "Show left tool icon"
|
||||
|
||||
[node name="RightToolIconCheckbox" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/General/GridContainer"]
|
||||
margin_left = 151.0
|
||||
margin_top = 28.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 52.0
|
||||
hint_tooltip = "Displays an icon of the selected right tool next to the cursor on the canvas"
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
pressed = true
|
||||
text = "Show right tool icon"
|
||||
|
||||
[node name="HSeparator3" type="HSeparator" parent="HSplitContainer/ScrollContainer/VBoxContainer/General"]
|
||||
margin_top = 92.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 96.0
|
||||
|
||||
[node name="PressureSentivity" type="HBoxContainer" parent="HSplitContainer/ScrollContainer/VBoxContainer/General"]
|
||||
visible = false
|
||||
margin_top = 116.0
|
||||
margin_right = 334.0
|
||||
margin_bottom = 136.0
|
||||
|
||||
[node name="PressureSensitivityLabel" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/General/PressureSentivity"]
|
||||
margin_top = 3.0
|
||||
margin_right = 173.0
|
||||
margin_bottom = 17.0
|
||||
text = "Tablet pressure sensitivity:"
|
||||
|
||||
[node name="PressureSensitivityOptionButton" type="OptionButton" parent="HSplitContainer/ScrollContainer/VBoxContainer/General/PressureSentivity"]
|
||||
margin_left = 177.0
|
||||
margin_right = 334.0
|
||||
margin_bottom = 20.0
|
||||
text = "Affect Brush's Alpha"
|
||||
items = [ "None", null, false, 0, null, "Affect Brush's Alpha", null, false, 1, null ]
|
||||
selected = 1
|
||||
|
||||
[node name="OpenLastProject" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/General"]
|
||||
margin_top = 100.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 124.0
|
||||
hint_tooltip = "Opens last opened project on startup"
|
||||
mouse_default_cursor_shape = 2
|
||||
pressed = true
|
||||
text = "Open last project on startup"
|
||||
|
||||
[node name="EnableAutosave" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/General"]
|
||||
margin_top = 128.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 152.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Enable autosave"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="AutosaveInterval" type="HBoxContainer" parent="HSplitContainer/ScrollContainer/VBoxContainer/General"]
|
||||
margin_top = 156.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 180.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="AutosaveIntervalLabel" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/General/AutosaveInterval"]
|
||||
margin_top = 5.0
|
||||
margin_right = 115.0
|
||||
margin_bottom = 19.0
|
||||
text = "Autosave interval:"
|
||||
|
||||
[node name="AutosaveInterval" type="SpinBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/General/AutosaveInterval"]
|
||||
margin_left = 119.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_horizontal = 3
|
||||
min_value = 1.0
|
||||
max_value = 30.0
|
||||
value = 1.0
|
||||
align = 2
|
||||
suffix = "minute(s)"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Languages" type="VBoxContainer" parent="HSplitContainer/ScrollContainer/VBoxContainer"]
|
||||
margin_top = 184.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 576.0
|
||||
|
||||
[node name="System Language" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Languages"]
|
||||
margin_right = 306.0
|
||||
margin_bottom = 24.0
|
||||
mouse_default_cursor_shape = 2
|
||||
pressed = true
|
||||
text = "System Language"
|
||||
|
||||
[node name="German" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Languages"]
|
||||
margin_top = 28.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 52.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Deutsch [de]"
|
||||
|
||||
[node name="Greek" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Languages"]
|
||||
margin_top = 56.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 80.0
|
||||
mouse_default_cursor_shape = 2
|
||||
custom_fonts/font = ExtResource( 2 )
|
||||
text = "Ελληνικά [el]"
|
||||
|
||||
[node name="English" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Languages"]
|
||||
margin_top = 84.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 108.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "English [en]"
|
||||
|
||||
[node name="Esperanto" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Languages"]
|
||||
margin_top = 112.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 136.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Esperanto [eo]"
|
||||
|
||||
[node name="Spanish" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Languages"]
|
||||
margin_top = 140.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 164.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Español [es]"
|
||||
|
||||
[node name="French" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Languages"]
|
||||
margin_top = 168.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 192.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Français [fr]"
|
||||
|
||||
[node name="Italian" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Languages"]
|
||||
margin_top = 196.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 220.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Italiano [it]"
|
||||
|
||||
[node name="Latvian" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Languages"]
|
||||
margin_top = 224.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 248.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Latvian [lv]"
|
||||
|
||||
[node name="Polish" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Languages"]
|
||||
margin_top = 252.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 276.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Polski [pl]"
|
||||
|
||||
[node name="Brazilian Portuguese" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Languages"]
|
||||
margin_top = 280.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 304.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Português Brasileiro [pt_BR]"
|
||||
|
||||
[node name="Russian" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Languages"]
|
||||
margin_top = 308.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 332.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Русский [ru]"
|
||||
|
||||
[node name="Chinese Simplified" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Languages"]
|
||||
margin_top = 336.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 362.0
|
||||
mouse_default_cursor_shape = 2
|
||||
custom_fonts/font = ExtResource( 3 )
|
||||
text = "简体中文 [zh_CN]"
|
||||
|
||||
[node name="Chinese Traditional" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Languages"]
|
||||
margin_top = 366.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 392.0
|
||||
mouse_default_cursor_shape = 2
|
||||
custom_fonts/font = ExtResource( 3 )
|
||||
text = "繁體中文 [zh_TW]"
|
||||
|
||||
[node name="Themes" type="VBoxContainer" parent="HSplitContainer/ScrollContainer/VBoxContainer"]
|
||||
margin_top = 580.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 716.0
|
||||
|
||||
[node name="Dark Theme" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Themes"]
|
||||
margin_right = 306.0
|
||||
margin_bottom = 24.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Dark"
|
||||
|
||||
[node name="Gray Theme" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Themes"]
|
||||
margin_top = 28.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 52.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Gray"
|
||||
|
||||
[node name="Godot\'s Theme" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Themes"]
|
||||
margin_top = 56.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 80.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Godot"
|
||||
|
||||
[node name="Gold Theme" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Themes"]
|
||||
margin_top = 84.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 108.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Gold"
|
||||
|
||||
[node name="Light Theme" type="CheckBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Themes"]
|
||||
margin_top = 112.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 136.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Light"
|
||||
|
||||
[node name="Canvas" type="VBoxContainer" parent="HSplitContainer/ScrollContainer/VBoxContainer"]
|
||||
margin_top = 720.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 912.0
|
||||
|
||||
[node name="GuideOptions" type="GridContainer" parent="HSplitContainer/ScrollContainer/VBoxContainer/Canvas"]
|
||||
margin_right = 306.0
|
||||
margin_bottom = 20.0
|
||||
custom_constants/vseparation = 4
|
||||
custom_constants/hseparation = 4
|
||||
columns = 2
|
||||
|
||||
[node name="GuideColorLabel" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/Canvas/GuideOptions"]
|
||||
margin_top = 3.0
|
||||
margin_right = 110.0
|
||||
margin_bottom = 17.0
|
||||
rect_min_size = Vector2( 110, 0 )
|
||||
hint_tooltip = "A color of ruler guides displayed on the canvas"
|
||||
mouse_filter = 0
|
||||
text = "Guides color:"
|
||||
|
||||
[node name="GuideColor" type="ColorPickerButton" parent="HSplitContainer/ScrollContainer/VBoxContainer/Canvas/GuideOptions"]
|
||||
margin_left = 114.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 20.0
|
||||
rect_min_size = Vector2( 64, 20 )
|
||||
hint_tooltip = "A color of ruler guides displayed on the canvas"
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
color = Color( 0.63, 0.13, 0.94, 1 )
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="HSplitContainer/ScrollContainer/VBoxContainer/Canvas"]
|
||||
margin_top = 24.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 28.0
|
||||
|
||||
[node name="GridOptions" type="GridContainer" parent="HSplitContainer/ScrollContainer/VBoxContainer/Canvas"]
|
||||
margin_top = 32.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 108.0
|
||||
custom_constants/vseparation = 4
|
||||
custom_constants/hseparation = 4
|
||||
columns = 2
|
||||
|
||||
[node name="WidthLabel" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/Canvas/GridOptions"]
|
||||
margin_top = 5.0
|
||||
margin_right = 110.0
|
||||
margin_bottom = 19.0
|
||||
rect_min_size = Vector2( 110, 0 )
|
||||
hint_tooltip = "Sets how far apart are vertical lines of the grid"
|
||||
mouse_filter = 0
|
||||
text = "Grid width:"
|
||||
|
||||
[node name="GridWidthValue" type="SpinBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Canvas/GridOptions"]
|
||||
margin_left = 114.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 24.0
|
||||
hint_tooltip = "Sets how far apart are vertical lines of the grid"
|
||||
mouse_default_cursor_shape = 2
|
||||
min_value = 1.0
|
||||
max_value = 16384.0
|
||||
value = 1.0
|
||||
align = 2
|
||||
suffix = "px"
|
||||
|
||||
[node name="Height" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/Canvas/GridOptions"]
|
||||
margin_top = 33.0
|
||||
margin_right = 110.0
|
||||
margin_bottom = 47.0
|
||||
hint_tooltip = "Sets how far apart are horizontal lines of the grid"
|
||||
mouse_filter = 0
|
||||
text = "Grid height:"
|
||||
|
||||
[node name="GridHeightValue" type="SpinBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Canvas/GridOptions"]
|
||||
margin_left = 114.0
|
||||
margin_top = 28.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 52.0
|
||||
hint_tooltip = "Sets how far apart are horizontal lines of the grid"
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
min_value = 1.0
|
||||
max_value = 16384.0
|
||||
value = 1.0
|
||||
align = 2
|
||||
suffix = "px"
|
||||
|
||||
[node name="GridColorLabel" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/Canvas/GridOptions"]
|
||||
margin_top = 59.0
|
||||
margin_right = 110.0
|
||||
margin_bottom = 73.0
|
||||
hint_tooltip = "A color of the grid"
|
||||
mouse_filter = 0
|
||||
text = "Grid color:"
|
||||
|
||||
[node name="GridColor" type="ColorPickerButton" parent="HSplitContainer/ScrollContainer/VBoxContainer/Canvas/GridOptions"]
|
||||
margin_left = 114.0
|
||||
margin_top = 56.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 76.0
|
||||
rect_min_size = Vector2( 64, 20 )
|
||||
hint_tooltip = "A color of the grid"
|
||||
mouse_default_cursor_shape = 2
|
||||
|
||||
[node name="HSeparator2" type="HSeparator" parent="HSplitContainer/ScrollContainer/VBoxContainer/Canvas"]
|
||||
margin_top = 112.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 116.0
|
||||
|
||||
[node name="CheckerOptions" type="GridContainer" parent="HSplitContainer/ScrollContainer/VBoxContainer/Canvas"]
|
||||
margin_top = 120.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 192.0
|
||||
custom_constants/vseparation = 4
|
||||
custom_constants/hseparation = 4
|
||||
columns = 2
|
||||
|
||||
[node name="SizeLabel" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/Canvas/CheckerOptions"]
|
||||
margin_top = 5.0
|
||||
margin_right = 110.0
|
||||
margin_bottom = 19.0
|
||||
rect_min_size = Vector2( 110, 0 )
|
||||
hint_tooltip = "Size of the transparent checker background"
|
||||
mouse_filter = 0
|
||||
text = "Checker size:"
|
||||
|
||||
[node name="CheckerSizeValue" type="SpinBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Canvas/CheckerOptions"]
|
||||
margin_left = 114.0
|
||||
margin_right = 188.0
|
||||
margin_bottom = 24.0
|
||||
hint_tooltip = "Size of the transparent checker background"
|
||||
mouse_default_cursor_shape = 2
|
||||
min_value = 1.0
|
||||
max_value = 16384.0
|
||||
value = 10.0
|
||||
align = 2
|
||||
suffix = "px"
|
||||
|
||||
[node name="CheckerColor1Label" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/Canvas/CheckerOptions"]
|
||||
margin_top = 31.0
|
||||
margin_right = 110.0
|
||||
margin_bottom = 45.0
|
||||
hint_tooltip = "First color of the transparent checker background"
|
||||
mouse_filter = 0
|
||||
text = "Checker color 1:"
|
||||
|
||||
[node name="CheckerColor1" type="ColorPickerButton" parent="HSplitContainer/ScrollContainer/VBoxContainer/Canvas/CheckerOptions"]
|
||||
margin_left = 114.0
|
||||
margin_top = 28.0
|
||||
margin_right = 188.0
|
||||
margin_bottom = 48.0
|
||||
rect_min_size = Vector2( 64, 20 )
|
||||
hint_tooltip = "First color of the transparent checker background"
|
||||
mouse_default_cursor_shape = 2
|
||||
color = Color( 0.7, 0.7, 0.7, 1 )
|
||||
|
||||
[node name="CheckerColor2Label" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/Canvas/CheckerOptions"]
|
||||
margin_top = 55.0
|
||||
margin_right = 110.0
|
||||
margin_bottom = 69.0
|
||||
hint_tooltip = "Second color of the transparent checker background"
|
||||
mouse_filter = 0
|
||||
text = "Checker color 2:"
|
||||
|
||||
[node name="CheckerColor2" type="ColorPickerButton" parent="HSplitContainer/ScrollContainer/VBoxContainer/Canvas/CheckerOptions"]
|
||||
margin_left = 114.0
|
||||
margin_top = 52.0
|
||||
margin_right = 188.0
|
||||
margin_bottom = 72.0
|
||||
rect_min_size = Vector2( 64, 20 )
|
||||
hint_tooltip = "Second color of the transparent checker background"
|
||||
mouse_default_cursor_shape = 2
|
||||
color = Color( 1, 1, 1, 1 )
|
||||
|
||||
[node name="Image" type="VBoxContainer" parent="HSplitContainer/ScrollContainer/VBoxContainer"]
|
||||
margin_top = 916.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 992.0
|
||||
|
||||
[node name="ImageOptions" type="GridContainer" parent="HSplitContainer/ScrollContainer/VBoxContainer/Image"]
|
||||
margin_right = 306.0
|
||||
margin_bottom = 76.0
|
||||
custom_constants/vseparation = 4
|
||||
custom_constants/hseparation = 4
|
||||
columns = 2
|
||||
|
||||
[node name="DefaultWidthLabel" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/Image/ImageOptions"]
|
||||
margin_top = 5.0
|
||||
margin_right = 110.0
|
||||
margin_bottom = 19.0
|
||||
rect_min_size = Vector2( 110, 0 )
|
||||
hint_tooltip = "A default width of a new image"
|
||||
mouse_filter = 0
|
||||
text = "Default width:"
|
||||
|
||||
[node name="ImageDefaultWidth" type="SpinBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Image/ImageOptions"]
|
||||
margin_left = 114.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 24.0
|
||||
hint_tooltip = "A default width of a new image"
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
min_value = 1.0
|
||||
max_value = 16384.0
|
||||
value = 64.0
|
||||
align = 2
|
||||
suffix = "px"
|
||||
|
||||
[node name="DefaultHeightLabel" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/Image/ImageOptions"]
|
||||
margin_top = 33.0
|
||||
margin_right = 110.0
|
||||
margin_bottom = 47.0
|
||||
hint_tooltip = "A default height of a new image"
|
||||
mouse_filter = 0
|
||||
text = "Default height:"
|
||||
|
||||
[node name="ImageDefaultHeight" type="SpinBox" parent="HSplitContainer/ScrollContainer/VBoxContainer/Image/ImageOptions"]
|
||||
margin_left = 114.0
|
||||
margin_top = 28.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 52.0
|
||||
hint_tooltip = "A default height of a new image"
|
||||
mouse_default_cursor_shape = 2
|
||||
min_value = 1.0
|
||||
max_value = 16384.0
|
||||
value = 64.0
|
||||
align = 2
|
||||
suffix = "px"
|
||||
|
||||
[node name="DefaultFillColorLabel" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/Image/ImageOptions"]
|
||||
margin_top = 59.0
|
||||
margin_right = 110.0
|
||||
margin_bottom = 73.0
|
||||
hint_tooltip = "A default background color of a new image"
|
||||
mouse_filter = 0
|
||||
text = "Default fill color:"
|
||||
|
||||
[node name="DefaultFillColor" type="ColorPickerButton" parent="HSplitContainer/ScrollContainer/VBoxContainer/Image/ImageOptions"]
|
||||
margin_left = 114.0
|
||||
margin_top = 56.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 76.0
|
||||
rect_min_size = Vector2( 64, 20 )
|
||||
hint_tooltip = "A default background color of a new image"
|
||||
mouse_default_cursor_shape = 2
|
||||
color = Color( 0, 0, 0, 0 )
|
||||
|
||||
[node name="Shortcuts" type="VBoxContainer" parent="HSplitContainer/ScrollContainer/VBoxContainer"]
|
||||
margin_top = 996.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 1230.0
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts"]
|
||||
margin_right = 306.0
|
||||
margin_bottom = 20.0
|
||||
hint_tooltip = "Only custom preset can be modified"
|
||||
|
||||
[node name="Label" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/HBoxContainer"]
|
||||
margin_top = 3.0
|
||||
margin_right = 45.0
|
||||
margin_bottom = 17.0
|
||||
text = "Preset:"
|
||||
|
||||
[node name="PresetOptionButton" type="OptionButton" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/HBoxContainer"]
|
||||
margin_left = 49.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 20.0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Default"
|
||||
items = [ "Default", null, false, 0, null, "Custom", null, false, 1, null ]
|
||||
selected = 0
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts"]
|
||||
margin_top = 24.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 28.0
|
||||
|
||||
[node name="Shortcuts" type="GridContainer" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts"]
|
||||
margin_top = 32.0
|
||||
margin_right = 306.0
|
||||
margin_bottom = 234.0
|
||||
custom_constants/vseparation = 2
|
||||
custom_constants/hseparation = 5
|
||||
columns = 3
|
||||
|
||||
[node name="Empty" type="Control" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_right = 137.0
|
||||
margin_bottom = 14.0
|
||||
|
||||
[node name="LeftToolLabel" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_left = 142.0
|
||||
margin_right = 221.0
|
||||
margin_bottom = 14.0
|
||||
hint_tooltip = "A tool assigned to the left mouse button"
|
||||
mouse_filter = 0
|
||||
text = "Left Tool:"
|
||||
align = 1
|
||||
|
||||
[node name="RightToolLabel" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_left = 226.0
|
||||
margin_right = 305.0
|
||||
margin_bottom = 14.0
|
||||
hint_tooltip = "A tool assigned to the right mouse button"
|
||||
mouse_filter = 0
|
||||
text = "Right Tool:"
|
||||
align = 1
|
||||
|
||||
[node name="Empty2" type="Control" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_top = 16.0
|
||||
margin_right = 137.0
|
||||
margin_bottom = 20.0
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
visible = false
|
||||
margin_top = 18.0
|
||||
margin_right = 137.0
|
||||
margin_bottom = 22.0
|
||||
|
||||
[node name="HSeparator2" type="HSeparator" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_left = 142.0
|
||||
margin_top = 16.0
|
||||
margin_right = 221.0
|
||||
margin_bottom = 20.0
|
||||
|
||||
[node name="HSeparator3" type="HSeparator" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_left = 226.0
|
||||
margin_top = 16.0
|
||||
margin_right = 305.0
|
||||
margin_bottom = 20.0
|
||||
|
||||
[node name="RectSelectLabel" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_top = 25.0
|
||||
margin_right = 137.0
|
||||
margin_bottom = 39.0
|
||||
text = "Rectangular Selection"
|
||||
|
||||
[node name="left_rectangle_select_tool" type="Button" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_left = 142.0
|
||||
margin_top = 22.0
|
||||
margin_right = 221.0
|
||||
margin_bottom = 42.0
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="right_rectangle_select_tool" type="Button" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_left = 226.0
|
||||
margin_top = 22.0
|
||||
margin_right = 305.0
|
||||
margin_bottom = 42.0
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="ZoomLabel" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_top = 47.0
|
||||
margin_right = 137.0
|
||||
margin_bottom = 61.0
|
||||
text = "Zoom"
|
||||
|
||||
[node name="left_zoom_tool" type="Button" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_left = 142.0
|
||||
margin_top = 44.0
|
||||
margin_right = 221.0
|
||||
margin_bottom = 64.0
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="right_zoom_tool" type="Button" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_left = 226.0
|
||||
margin_top = 44.0
|
||||
margin_right = 305.0
|
||||
margin_bottom = 64.0
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="ColorPickerLabel" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_top = 69.0
|
||||
margin_right = 137.0
|
||||
margin_bottom = 83.0
|
||||
text = "Color Picker"
|
||||
|
||||
[node name="left_colorpicker_tool" type="Button" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_left = 142.0
|
||||
margin_top = 66.0
|
||||
margin_right = 221.0
|
||||
margin_bottom = 86.0
|
||||
|
||||
[node name="right_colorpicker_tool" type="Button" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_left = 226.0
|
||||
margin_top = 66.0
|
||||
margin_right = 305.0
|
||||
margin_bottom = 86.0
|
||||
|
||||
[node name="PencilLabel" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_top = 91.0
|
||||
margin_right = 137.0
|
||||
margin_bottom = 105.0
|
||||
text = "Pencil"
|
||||
|
||||
[node name="left_pencil_tool" type="Button" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_left = 142.0
|
||||
margin_top = 88.0
|
||||
margin_right = 221.0
|
||||
margin_bottom = 108.0
|
||||
|
||||
[node name="right_pencil_tool" type="Button" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_left = 226.0
|
||||
margin_top = 88.0
|
||||
margin_right = 305.0
|
||||
margin_bottom = 108.0
|
||||
|
||||
[node name="EraserLabel" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_top = 113.0
|
||||
margin_right = 137.0
|
||||
margin_bottom = 127.0
|
||||
text = "Eraser"
|
||||
|
||||
[node name="left_eraser_tool" type="Button" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_left = 142.0
|
||||
margin_top = 110.0
|
||||
margin_right = 221.0
|
||||
margin_bottom = 130.0
|
||||
|
||||
[node name="right_eraser_tool" type="Button" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_left = 226.0
|
||||
margin_top = 110.0
|
||||
margin_right = 305.0
|
||||
margin_bottom = 130.0
|
||||
|
||||
[node name="BucketLabel" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_top = 135.0
|
||||
margin_right = 137.0
|
||||
margin_bottom = 149.0
|
||||
text = "Bucket"
|
||||
|
||||
[node name="left_fill_tool" type="Button" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_left = 142.0
|
||||
margin_top = 132.0
|
||||
margin_right = 221.0
|
||||
margin_bottom = 152.0
|
||||
|
||||
[node name="right_fill_tool" type="Button" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_left = 226.0
|
||||
margin_top = 132.0
|
||||
margin_right = 305.0
|
||||
margin_bottom = 152.0
|
||||
|
||||
[node name="LightenDarkenLabel" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_top = 157.0
|
||||
margin_right = 137.0
|
||||
margin_bottom = 171.0
|
||||
text = "Lighten/Darken"
|
||||
|
||||
[node name="left_lightdark_tool" type="Button" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_left = 142.0
|
||||
margin_top = 154.0
|
||||
margin_right = 221.0
|
||||
margin_bottom = 174.0
|
||||
|
||||
[node name="right_lightdark_tool" type="Button" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_left = 226.0
|
||||
margin_top = 154.0
|
||||
margin_right = 305.0
|
||||
margin_bottom = 174.0
|
||||
|
||||
[node name="HSeparator4" type="HSeparator" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_top = 176.0
|
||||
margin_right = 137.0
|
||||
margin_bottom = 180.0
|
||||
|
||||
[node name="HSeparator5" type="HSeparator" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_left = 142.0
|
||||
margin_top = 176.0
|
||||
margin_right = 221.0
|
||||
margin_bottom = 180.0
|
||||
|
||||
[node name="HSeparator6" type="HSeparator" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_left = 226.0
|
||||
margin_top = 176.0
|
||||
margin_right = 305.0
|
||||
margin_bottom = 180.0
|
||||
|
||||
[node name="Switch Colors" type="Label" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_top = 185.0
|
||||
margin_right = 137.0
|
||||
margin_bottom = 199.0
|
||||
text = "Switch Colors"
|
||||
|
||||
[node name="switch_colors" type="Button" parent="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/Shortcuts"]
|
||||
margin_left = 142.0
|
||||
margin_top = 182.0
|
||||
margin_right = 221.0
|
||||
margin_bottom = 202.0
|
||||
|
||||
[node name="Popups" type="Node" parent="."]
|
||||
|
||||
[node name="ShortcutSelector" type="ConfirmationDialog" parent="Popups"]
|
||||
margin_right = 250.0
|
||||
margin_bottom = 87.5
|
||||
rect_min_size = Vector2( 250, 87.5 )
|
||||
window_title = "Set the shortcut"
|
||||
dialog_text = "Press a key or a key combination to set the shortcut"
|
||||
dialog_hide_on_ok = false
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="EnteredShortcut" type="Label" parent="Popups/ShortcutSelector"]
|
||||
margin_left = 8.0
|
||||
margin_top = 22.0
|
||||
margin_right = 341.0
|
||||
margin_bottom = 51.5
|
||||
align = 1
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
[connection signal="about_to_show" from="." to="." method="_on_PreferencesDialog_about_to_show"]
|
||||
[connection signal="popup_hide" from="." to="." method="_on_PreferencesDialog_popup_hide"]
|
||||
[connection signal="item_selected" from="HSplitContainer/Tree" to="." method="_on_Tree_item_selected"]
|
||||
[connection signal="pressed" from="HSplitContainer/ScrollContainer/VBoxContainer/General/SmoothZoom" to="." method="_on_SmoothZoom_pressed"]
|
||||
[connection signal="toggled" from="HSplitContainer/ScrollContainer/VBoxContainer/General/GridContainer/LeftIndicatorCheckbox" to="." method="_on_LeftIndicatorCheckbox_toggled"]
|
||||
[connection signal="toggled" from="HSplitContainer/ScrollContainer/VBoxContainer/General/GridContainer/RightIndicatorCheckbox" to="." method="_on_RightIndicatorCheckbox_toggled"]
|
||||
[connection signal="toggled" from="HSplitContainer/ScrollContainer/VBoxContainer/General/GridContainer/LeftToolIconCheckbox" to="." method="_on_LeftToolIconCheckbox_toggled"]
|
||||
[connection signal="toggled" from="HSplitContainer/ScrollContainer/VBoxContainer/General/GridContainer/RightToolIconCheckbox" to="." method="_on_RightToolIconCheckbox_toggled"]
|
||||
[connection signal="item_selected" from="HSplitContainer/ScrollContainer/VBoxContainer/General/PressureSentivity/PressureSensitivityOptionButton" to="." method="_on_PressureSensitivityOptionButton_item_selected"]
|
||||
[connection signal="pressed" from="HSplitContainer/ScrollContainer/VBoxContainer/General/OpenLastProject" to="." method="_on_OpenLastProject_pressed"]
|
||||
[connection signal="toggled" from="HSplitContainer/ScrollContainer/VBoxContainer/General/EnableAutosave" to="." method="_on_EnableAutosave_toggled"]
|
||||
[connection signal="value_changed" from="HSplitContainer/ScrollContainer/VBoxContainer/General/AutosaveInterval/AutosaveInterval" to="." method="_on_AutosaveInterval_value_changed"]
|
||||
[connection signal="color_changed" from="HSplitContainer/ScrollContainer/VBoxContainer/Canvas/GuideOptions/GuideColor" to="." method="_on_GuideColor_color_changed"]
|
||||
[connection signal="value_changed" from="HSplitContainer/ScrollContainer/VBoxContainer/Canvas/GridOptions/GridWidthValue" to="." method="_on_GridWidthValue_value_changed"]
|
||||
[connection signal="value_changed" from="HSplitContainer/ScrollContainer/VBoxContainer/Canvas/GridOptions/GridHeightValue" to="." method="_on_GridHeightValue_value_changed"]
|
||||
[connection signal="color_changed" from="HSplitContainer/ScrollContainer/VBoxContainer/Canvas/GridOptions/GridColor" to="." method="_on_GridColor_color_changed"]
|
||||
[connection signal="value_changed" from="HSplitContainer/ScrollContainer/VBoxContainer/Canvas/CheckerOptions/CheckerSizeValue" to="." method="_on_CheckerSize_value_changed"]
|
||||
[connection signal="color_changed" from="HSplitContainer/ScrollContainer/VBoxContainer/Canvas/CheckerOptions/CheckerColor1" to="." method="_on_CheckerColor1_color_changed"]
|
||||
[connection signal="color_changed" from="HSplitContainer/ScrollContainer/VBoxContainer/Canvas/CheckerOptions/CheckerColor2" to="." method="_on_CheckerColor2_color_changed"]
|
||||
[connection signal="value_changed" from="HSplitContainer/ScrollContainer/VBoxContainer/Image/ImageOptions/ImageDefaultWidth" to="." method="_on_ImageDefaultWidth_value_changed"]
|
||||
[connection signal="value_changed" from="HSplitContainer/ScrollContainer/VBoxContainer/Image/ImageOptions/ImageDefaultHeight" to="." method="_on_ImageDefaultHeight_value_changed"]
|
||||
[connection signal="color_changed" from="HSplitContainer/ScrollContainer/VBoxContainer/Image/ImageOptions/DefaultFillColor" to="." method="_on_DefaultBackground_color_changed"]
|
||||
[connection signal="item_selected" from="HSplitContainer/ScrollContainer/VBoxContainer/Shortcuts/HBoxContainer/PresetOptionButton" to="." method="_on_PresetOptionButton_item_selected"]
|
||||
[connection signal="confirmed" from="Popups/ShortcutSelector" to="." method="_on_ShortcutSelector_confirmed"]
|
||||
[connection signal="popup_hide" from="Popups/ShortcutSelector" to="." method="_on_ShortcutSelector_popup_hide"]
|
61
src/UI/Dialogs/RotateImage.gd
Normal file
61
src/UI/Dialogs/RotateImage.gd
Normal file
|
@ -0,0 +1,61 @@
|
|||
extends ConfirmationDialog
|
||||
|
||||
var texture : ImageTexture
|
||||
var aux_img : Image
|
||||
var layer : Image
|
||||
|
||||
func _ready() -> void:
|
||||
texture = ImageTexture.new()
|
||||
texture.flags = 0
|
||||
aux_img = Image.new()
|
||||
$VBoxContainer/HBoxContainer2/OptionButton.add_item("Rotxel")
|
||||
$VBoxContainer/HBoxContainer2/OptionButton.add_item("Upscale, Rotate and Downscale")
|
||||
$VBoxContainer/HBoxContainer2/OptionButton.add_item("Nearest neighbour")
|
||||
|
||||
func set_sprite(sprite : Image) -> void:
|
||||
aux_img.copy_from(sprite)
|
||||
layer = sprite
|
||||
texture.create_from_image(aux_img, 0)
|
||||
$VBoxContainer/TextureRect.texture = texture
|
||||
|
||||
|
||||
func _on_HSlider_value_changed(_value) -> void:
|
||||
rotate()
|
||||
$VBoxContainer/HBoxContainer/SpinBox.value = $VBoxContainer/HBoxContainer/HSlider.value
|
||||
|
||||
|
||||
func _on_SpinBox_value_changed(_value):
|
||||
$VBoxContainer/HBoxContainer/HSlider.value = $VBoxContainer/HBoxContainer/SpinBox.value
|
||||
|
||||
|
||||
func _on_RotateImage_confirmed() -> void:
|
||||
Global.canvas.handle_undo("Draw")
|
||||
match $VBoxContainer/HBoxContainer2/OptionButton.text:
|
||||
"Rotxel":
|
||||
Global.rotxel(layer,$VBoxContainer/HBoxContainer/HSlider.value*PI/180)
|
||||
"Nearest neighbour":
|
||||
Global.nn_rotate(layer,$VBoxContainer/HBoxContainer/HSlider.value*PI/180)
|
||||
"Upscale, Rotate and Downscale":
|
||||
Global.fake_rotsprite(layer,$VBoxContainer/HBoxContainer/HSlider.value*PI/180)
|
||||
Global.canvas.handle_redo("Draw")
|
||||
$VBoxContainer/HBoxContainer/HSlider.value = 0
|
||||
|
||||
func rotate() -> void:
|
||||
var sprite : Image = Image.new()
|
||||
sprite.copy_from(aux_img)
|
||||
match $VBoxContainer/HBoxContainer2/OptionButton.text:
|
||||
"Rotxel":
|
||||
Global.rotxel(sprite,$VBoxContainer/HBoxContainer/HSlider.value*PI/180)
|
||||
"Nearest neighbour":
|
||||
Global.nn_rotate(sprite,$VBoxContainer/HBoxContainer/HSlider.value*PI/180)
|
||||
"Upscale, Rotate and Downscale":
|
||||
Global.fake_rotsprite(sprite,$VBoxContainer/HBoxContainer/HSlider.value*PI/180)
|
||||
texture.create_from_image(sprite, 0)
|
||||
|
||||
|
||||
func _on_OptionButton_item_selected(_id) -> void:
|
||||
rotate()
|
||||
|
||||
|
||||
func _on_RotateImage_about_to_show() -> void:
|
||||
$VBoxContainer/HBoxContainer/HSlider.value = 0
|
86
src/UI/Dialogs/RotateImage.tscn
Normal file
86
src/UI/Dialogs/RotateImage.tscn
Normal file
|
@ -0,0 +1,86 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://src/UI/Dialogs/RotateImage.gd" type="Script" id=1]
|
||||
|
||||
|
||||
|
||||
[node name="RotateImage" type="ConfirmationDialog"]
|
||||
margin_right = 245.0
|
||||
margin_bottom = 241.0
|
||||
resizable = true
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = 8.0
|
||||
margin_top = 8.0
|
||||
margin_right = -8.0
|
||||
margin_bottom = -36.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="VBoxContainer"]
|
||||
margin_right = 229.0
|
||||
margin_bottom = 145.0
|
||||
size_flags_vertical = 3
|
||||
expand = true
|
||||
stretch_mode = 6
|
||||
|
||||
[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer"]
|
||||
margin_top = 149.0
|
||||
margin_right = 229.0
|
||||
margin_bottom = 169.0
|
||||
|
||||
[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer2"]
|
||||
margin_top = 3.0
|
||||
margin_right = 34.0
|
||||
margin_bottom = 17.0
|
||||
text = "Type:"
|
||||
|
||||
[node name="OptionButton" type="OptionButton" parent="VBoxContainer/HBoxContainer2"]
|
||||
margin_left = 38.0
|
||||
margin_right = 229.0
|
||||
margin_bottom = 20.0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"]
|
||||
margin_top = 173.0
|
||||
margin_right = 229.0
|
||||
margin_bottom = 197.0
|
||||
|
||||
[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer"]
|
||||
margin_top = 5.0
|
||||
margin_right = 44.0
|
||||
margin_bottom = 19.0
|
||||
text = "Angle: "
|
||||
|
||||
[node name="HSlider" type="HSlider" parent="VBoxContainer/HBoxContainer"]
|
||||
margin_left = 48.0
|
||||
margin_right = 151.0
|
||||
margin_bottom = 24.0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
max_value = 359.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="SpinBox" type="SpinBox" parent="VBoxContainer/HBoxContainer"]
|
||||
margin_left = 155.0
|
||||
margin_right = 229.0
|
||||
margin_bottom = 24.0
|
||||
mouse_default_cursor_shape = 2
|
||||
max_value = 359.0
|
||||
[connection signal="about_to_show" from="." to="." method="_on_RotateImage_about_to_show"]
|
||||
[connection signal="confirmed" from="." to="." method="_on_RotateImage_confirmed"]
|
||||
[connection signal="item_selected" from="VBoxContainer/HBoxContainer2/OptionButton" to="." method="_on_OptionButton_item_selected"]
|
||||
[connection signal="value_changed" from="VBoxContainer/HBoxContainer/HSlider" to="." method="_on_HSlider_value_changed"]
|
||||
[connection signal="value_changed" from="VBoxContainer/HBoxContainer/SpinBox" to="." method="_on_SpinBox_value_changed"]
|
21
src/UI/Dialogs/ScaleImage.gd
Normal file
21
src/UI/Dialogs/ScaleImage.gd
Normal file
|
@ -0,0 +1,21 @@
|
|||
extends ConfirmationDialog
|
||||
|
||||
|
||||
func _on_ScaleImage_confirmed() -> void:
|
||||
var width : int = $VBoxContainer/OptionsContainer/WidthValue.value
|
||||
var height : int = $VBoxContainer/OptionsContainer/HeightValue.value
|
||||
var interpolation : int = $VBoxContainer/OptionsContainer/InterpolationType.selected
|
||||
Global.undos += 1
|
||||
Global.undo_redo.create_action("Scale")
|
||||
Global.undo_redo.add_do_property(Global.canvas, "size", Vector2(width, height).floor())
|
||||
|
||||
for i in range(Global.canvas.layers.size() - 1, -1, -1):
|
||||
var sprite : Image = Global.canvas.layers[i][1].get_data()
|
||||
sprite.resize(width, height, interpolation)
|
||||
Global.undo_redo.add_do_property(Global.canvas.layers[i][0], "data", sprite.data)
|
||||
Global.undo_redo.add_undo_property(Global.canvas.layers[i][0], "data", Global.canvas.layers[i][0].data)
|
||||
|
||||
Global.undo_redo.add_undo_property(Global.canvas, "size", Global.canvas.size)
|
||||
Global.undo_redo.add_undo_method(Global, "undo", [Global.canvas])
|
||||
Global.undo_redo.add_do_method(Global, "redo", [Global.canvas])
|
||||
Global.undo_redo.commit_action()
|
78
src/UI/Dialogs/ScaleImage.tscn
Normal file
78
src/UI/Dialogs/ScaleImage.tscn
Normal file
|
@ -0,0 +1,78 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://src/UI/Dialogs/ScaleImage.gd" type="Script" id=1]
|
||||
|
||||
|
||||
|
||||
[node name="ScaleImage" type="ConfirmationDialog"]
|
||||
margin_right = 200.0
|
||||
margin_bottom = 114.0
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
margin_left = 8.0
|
||||
margin_top = 8.0
|
||||
margin_right = 192.0
|
||||
margin_bottom = 102.0
|
||||
|
||||
[node name="ImageSize" type="Label" parent="VBoxContainer"]
|
||||
margin_right = 184.0
|
||||
margin_bottom = 15.0
|
||||
text = "Image Size"
|
||||
|
||||
[node name="OptionsContainer" type="GridContainer" parent="VBoxContainer"]
|
||||
margin_top = 19.0
|
||||
margin_right = 184.0
|
||||
margin_bottom = 90.0
|
||||
custom_constants/vseparation = 4
|
||||
custom_constants/hseparation = 2
|
||||
columns = 2
|
||||
|
||||
[node name="WidthLabel" type="Label" parent="VBoxContainer/OptionsContainer"]
|
||||
margin_top = 5.0
|
||||
margin_right = 72.0
|
||||
margin_bottom = 20.0
|
||||
text = "Width:"
|
||||
|
||||
[node name="WidthValue" type="SpinBox" parent="VBoxContainer/OptionsContainer"]
|
||||
margin_left = 72.0
|
||||
margin_right = 155.0
|
||||
margin_bottom = 25.0
|
||||
mouse_default_cursor_shape = 2
|
||||
min_value = 1.0
|
||||
max_value = 16384.0
|
||||
value = 64.0
|
||||
suffix = "px"
|
||||
|
||||
[node name="Height" type="Label" parent="VBoxContainer/OptionsContainer"]
|
||||
margin_top = 30.0
|
||||
margin_right = 72.0
|
||||
margin_bottom = 45.0
|
||||
text = "Height:"
|
||||
|
||||
[node name="HeightValue" type="SpinBox" parent="VBoxContainer/OptionsContainer"]
|
||||
margin_left = 72.0
|
||||
margin_top = 25.0
|
||||
margin_right = 155.0
|
||||
margin_bottom = 50.0
|
||||
mouse_default_cursor_shape = 2
|
||||
min_value = 1.0
|
||||
max_value = 16384.0
|
||||
value = 64.0
|
||||
suffix = "px"
|
||||
|
||||
[node name="InterpolationLabel" type="Label" parent="VBoxContainer/OptionsContainer"]
|
||||
margin_top = 53.0
|
||||
margin_right = 72.0
|
||||
margin_bottom = 68.0
|
||||
text = "Interpolation:"
|
||||
|
||||
[node name="InterpolationType" type="OptionButton" parent="VBoxContainer/OptionsContainer"]
|
||||
margin_left = 72.0
|
||||
margin_top = 50.0
|
||||
margin_right = 155.0
|
||||
margin_bottom = 71.0
|
||||
text = "Nearest"
|
||||
items = [ "Nearest", null, false, 0, null, "Bilinear", null, false, 1, null, "Cubic", null, false, 2, null, "Trilinear", null, false, 3, null, "Lanczos", null, false, 4, null ]
|
||||
selected = 0
|
||||
[connection signal="confirmed" from="." to="." method="_on_ScaleImage_confirmed"]
|
75
src/UI/Dialogs/SplashDialog.gd
Normal file
75
src/UI/Dialogs/SplashDialog.gd
Normal file
|
@ -0,0 +1,75 @@
|
|||
extends WindowDialog
|
||||
|
||||
onready var changes_label : Label = $"Contents/HBoxContainer/Buttons_Changelog/VBoxContainer/Changlog/ChangesLabel"
|
||||
onready var art_by_label : Label = $"Contents/HBoxContainer/Logo_ArtWork/CenterContainer/ArtContainer/ArtCredits"
|
||||
onready var show_on_startup_button : CheckBox = $"Contents/MarginContainer/Info/VBoxContainer/HBoxContainer/ShowOnStartup"
|
||||
onready var developed_by_label : Label = $"Contents/MarginContainer/Info/VBoxContainer/Branding/VBoxContainer/DevelopedBy"
|
||||
onready var platinum_placeholder_label : Label = $"Contents/MarginContainer/Info/Sponsors/PlatinumContainer/PlaceholderLabel"
|
||||
onready var gold_placeholder_label : Label = $"Contents/MarginContainer/Info/Sponsors/GoldContainer/PlaceholderLabel"
|
||||
|
||||
|
||||
func _on_SplashDialog_about_to_show() -> void:
|
||||
if Global.config_cache.has_section_key("preferences", "startup"):
|
||||
show_on_startup_button.pressed = !Global.config_cache.get_value("preferences", "startup")
|
||||
var current_version : String = ProjectSettings.get_setting("application/config/Version")
|
||||
window_title = "Pixelorama" + " " + current_version
|
||||
changes_label.text = current_version + " " + tr("Changes")
|
||||
|
||||
art_by_label.text = tr("Art by") + ": Erevos"
|
||||
if "zh" in TranslationServer.get_locale():
|
||||
show_on_startup_button.add_font_override("font", preload("res://Assets/Fonts/CJK/NotoSansCJKtc-Small.tres"))
|
||||
developed_by_label.add_font_override("font", preload("res://Assets/Fonts/CJK/NotoSansCJKtc-Small.tres"))
|
||||
platinum_placeholder_label.add_font_override("font", preload("res://Assets/Fonts/CJK/NotoSansCJKtc-Bold.tres"))
|
||||
gold_placeholder_label.add_font_override("font", preload("res://Assets/Fonts/CJK/NotoSansCJKtc-Bold.tres"))
|
||||
else:
|
||||
show_on_startup_button.add_font_override("font", preload("res://Assets/Fonts/Roboto-Small.tres"))
|
||||
developed_by_label.add_font_override("font", preload("res://Assets/Fonts/Roboto-Small.tres"))
|
||||
platinum_placeholder_label.add_font_override("font", preload("res://Assets/Fonts/Roboto-Bold.tres"))
|
||||
gold_placeholder_label.add_font_override("font", preload("res://Assets/Fonts/Roboto-Bold.tres"))
|
||||
|
||||
|
||||
func _on_ArtCredits_pressed() -> void:
|
||||
OS.shell_open("https://www.instagram.com/erevoid")
|
||||
|
||||
|
||||
func _on_ShowOnStartup_toggled(pressed : bool) -> void:
|
||||
if pressed:
|
||||
Global.config_cache.set_value("preferences", "startup", false)
|
||||
else:
|
||||
Global.config_cache.set_value("preferences", "startup", true)
|
||||
|
||||
|
||||
func _on_PatronButton_pressed() -> void:
|
||||
OS.shell_open("https://www.patreon.com/OramaInteractive")
|
||||
|
||||
|
||||
func _on_TakeThisSpot_pressed() -> void:
|
||||
OS.shell_open("https://www.patreon.com/OramaInteractive")
|
||||
|
||||
|
||||
func _on_GithubButton_pressed() -> void:
|
||||
OS.shell_open("https://github.com/Orama-Interactive/Pixelorama")
|
||||
|
||||
|
||||
func _on_DiscordButton_pressed() -> void:
|
||||
OS.shell_open("https://discord.gg/GTMtr8s")
|
||||
|
||||
|
||||
func _on_NewBtn_pressed() -> void:
|
||||
Global.control.file_menu_id_pressed(0)
|
||||
visible = false
|
||||
|
||||
|
||||
func _on_OpenBtn__pressed() -> void:
|
||||
Global.control.file_menu_id_pressed(1)
|
||||
visible = false
|
||||
|
||||
|
||||
func _on_OpenLastBtn_pressed() -> void:
|
||||
Global.control.file_menu_id_pressed(2)
|
||||
visible = false
|
||||
|
||||
|
||||
func _on_ImportBtn_pressed() -> void:
|
||||
Global.control.file_menu_id_pressed(5)
|
||||
visible = false
|
441
src/UI/Dialogs/SplashDialog.tscn
Normal file
441
src/UI/Dialogs/SplashDialog.tscn
Normal file
|
@ -0,0 +1,441 @@
|
|||
[gd_scene load_steps=12 format=2]
|
||||
|
||||
[ext_resource path="res://src/UI/Dialogs/SplashDialog.gd" type="Script" id=1]
|
||||
[ext_resource path="res://Assets/Graphics/Pixelorama Logo.png" type="Texture" id=2]
|
||||
[ext_resource path="res://Assets/Graphics/Become a patron.png" type="Texture" id=3]
|
||||
[ext_resource path="res://Assets/Graphics/Become a patron_Hover.png" type="Texture" id=4]
|
||||
[ext_resource path="res://Assets/Graphics/Splash Art.png" type="Texture" id=5]
|
||||
[ext_resource path="res://Assets/Fonts/Roboto-Bold.tres" type="DynamicFont" id=6]
|
||||
[ext_resource path="res://Assets/Fonts/Roboto-Small.tres" type="DynamicFont" id=7]
|
||||
[ext_resource path="res://Assets/Graphics/orama_64x64.png" type="Texture" id=8]
|
||||
[ext_resource path="res://Assets/Graphics/discord.png" type="Texture" id=9]
|
||||
[ext_resource path="res://Assets/Graphics/GitHub-32px.png" type="Texture" id=10]
|
||||
[ext_resource path="res://Assets/Graphics/Patreon_Mark_White.png" type="Texture" id=11]
|
||||
|
||||
|
||||
|
||||
[node name="SplashDialog" type="WindowDialog"]
|
||||
margin_right = 614.0
|
||||
margin_bottom = 590.0
|
||||
rect_min_size = Vector2( 600, 560 )
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Contents" type="VBoxContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
custom_constants/separation = 0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="Contents"]
|
||||
margin_right = 617.0
|
||||
margin_bottom = 436.0
|
||||
custom_constants/separation = 0
|
||||
|
||||
[node name="Logo_ArtWork" type="VBoxContainer" parent="Contents/HBoxContainer"]
|
||||
margin_right = 350.0
|
||||
margin_bottom = 436.0
|
||||
rect_min_size = Vector2( 350, 0 )
|
||||
custom_constants/separation = 15
|
||||
|
||||
[node name="PixeloramaLogo" type="TextureRect" parent="Contents/HBoxContainer/Logo_ArtWork"]
|
||||
margin_right = 350.0
|
||||
margin_bottom = 124.0
|
||||
rect_min_size = Vector2( 0, 80 )
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
texture = ExtResource( 2 )
|
||||
stretch_mode = 6
|
||||
|
||||
[node name="CenterContainer" type="MarginContainer" parent="Contents/HBoxContainer/Logo_ArtWork"]
|
||||
margin_top = 139.0
|
||||
margin_right = 350.0
|
||||
margin_bottom = 436.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 0
|
||||
|
||||
[node name="ArtContainer" type="VBoxContainer" parent="Contents/HBoxContainer/Logo_ArtWork/CenterContainer"]
|
||||
margin_right = 350.0
|
||||
margin_bottom = 297.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
custom_constants/separation = 17
|
||||
|
||||
[node name="SplashArt" type="TextureButton" parent="Contents/HBoxContainer/Logo_ArtWork/CenterContainer/ArtContainer"]
|
||||
margin_left = 45.0
|
||||
margin_right = 305.0
|
||||
margin_bottom = 260.0
|
||||
rect_min_size = Vector2( 260, 260 )
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 6
|
||||
texture_normal = ExtResource( 5 )
|
||||
expand = true
|
||||
stretch_mode = 5
|
||||
|
||||
[node name="ArtCredits" type="Button" parent="Contents/HBoxContainer/Logo_ArtWork/CenterContainer/ArtContainer"]
|
||||
margin_top = 277.0
|
||||
margin_right = 350.0
|
||||
margin_bottom = 297.0
|
||||
mouse_default_cursor_shape = 2
|
||||
custom_constants/hseparation = 0
|
||||
text = "Art by Erevoid"
|
||||
flat = true
|
||||
|
||||
[node name="VSeparator" type="VSeparator" parent="Contents/HBoxContainer"]
|
||||
margin_left = 350.0
|
||||
margin_right = 354.0
|
||||
margin_bottom = 436.0
|
||||
|
||||
[node name="Buttons_Changelog" type="MarginContainer" parent="Contents/HBoxContainer"]
|
||||
margin_left = 354.0
|
||||
margin_right = 617.0
|
||||
margin_bottom = 436.0
|
||||
size_flags_horizontal = 3
|
||||
custom_constants/margin_right = 10
|
||||
custom_constants/margin_top = 10
|
||||
custom_constants/margin_left = 10
|
||||
custom_constants/margin_bottom = 10
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="Contents/HBoxContainer/Buttons_Changelog"]
|
||||
margin_left = 10.0
|
||||
margin_top = 10.0
|
||||
margin_right = 253.0
|
||||
margin_bottom = 426.0
|
||||
size_flags_horizontal = 3
|
||||
custom_constants/separation = 10
|
||||
|
||||
[node name="Buttons" type="VBoxContainer" parent="Contents/HBoxContainer/Buttons_Changelog/VBoxContainer"]
|
||||
margin_right = 243.0
|
||||
margin_bottom = 110.0
|
||||
size_flags_vertical = 3
|
||||
custom_constants/separation = 10
|
||||
|
||||
[node name="NewBtn" type="Button" parent="Contents/HBoxContainer/Buttons_Changelog/VBoxContainer/Buttons"]
|
||||
margin_right = 243.0
|
||||
margin_bottom = 20.0
|
||||
text = "New"
|
||||
|
||||
[node name="OpenBtn " type="Button" parent="Contents/HBoxContainer/Buttons_Changelog/VBoxContainer/Buttons"]
|
||||
margin_top = 30.0
|
||||
margin_right = 243.0
|
||||
margin_bottom = 50.0
|
||||
text = "Open"
|
||||
|
||||
[node name="OpenLastBtn" type="Button" parent="Contents/HBoxContainer/Buttons_Changelog/VBoxContainer/Buttons"]
|
||||
margin_top = 60.0
|
||||
margin_right = 243.0
|
||||
margin_bottom = 80.0
|
||||
text = "Open Last Project"
|
||||
|
||||
[node name="ImportBtn" type="Button" parent="Contents/HBoxContainer/Buttons_Changelog/VBoxContainer/Buttons"]
|
||||
margin_top = 90.0
|
||||
margin_right = 243.0
|
||||
margin_bottom = 110.0
|
||||
text = "Import"
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="Contents/HBoxContainer/Buttons_Changelog/VBoxContainer"]
|
||||
margin_top = 120.0
|
||||
margin_right = 243.0
|
||||
margin_bottom = 124.0
|
||||
|
||||
[node name="Changlog" type="VBoxContainer" parent="Contents/HBoxContainer/Buttons_Changelog/VBoxContainer"]
|
||||
margin_top = 134.0
|
||||
margin_right = 243.0
|
||||
margin_bottom = 416.0
|
||||
size_flags_vertical = 3
|
||||
custom_constants/separation = 8
|
||||
|
||||
[node name="ChangesLabel" type="Label" parent="Contents/HBoxContainer/Buttons_Changelog/VBoxContainer/Changlog"]
|
||||
margin_right = 243.0
|
||||
margin_bottom = 14.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 8
|
||||
text = "v0.6 Changes"
|
||||
|
||||
[node name="ChangelogContainer" type="VBoxContainer" parent="Contents/HBoxContainer/Buttons_Changelog/VBoxContainer/Changlog"]
|
||||
margin_top = 22.0
|
||||
margin_right = 243.0
|
||||
margin_bottom = 282.0
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="ChangelogScroll" type="ScrollContainer" parent="Contents/HBoxContainer/Buttons_Changelog/VBoxContainer/Changlog/ChangelogContainer"]
|
||||
margin_right = 243.0
|
||||
margin_bottom = 260.0
|
||||
rect_min_size = Vector2( 0, 260 )
|
||||
|
||||
[node name="Label" type="Label" parent="Contents/HBoxContainer/Buttons_Changelog/VBoxContainer/Changlog/ChangelogContainer/ChangelogScroll"]
|
||||
margin_right = 243.0
|
||||
margin_bottom = 1680.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
text = "Added
|
||||
|
||||
- Image layer rotation! Choose between 2 rotation algorithms, Rotxel and Nearest Neighbour - Thanks to azagaya!
|
||||
- Crowdin integration for contributing translations!
|
||||
- Spanish translation - thanks to azagaya & Lilly And!
|
||||
- Chinese Simplified translation - thanks to Chenxu Wang!
|
||||
- Latvian translation - thanks to Agnis Aldiņš (NeZvers)!
|
||||
- Translators can now be seen in the About window.
|
||||
- It is now possible to remove custom brushes with the middle mouse button.
|
||||
- Added HSV mode to the color picker. (Added automatically because of the Godot 3.2 update)
|
||||
- Lanczos scaling interpolation. (Added because of the Godot 3.2 update)
|
||||
- You can now drag and drop (or right click and open with) image and .pxo files in Pixelorama.
|
||||
- You can now hide the animation timeline - Thanks to YeldhamDev!
|
||||
|
||||
Changed
|
||||
|
||||
- Major changes to alpha blending behavior. The alpha values now get added/blended together instead of just replacing the pixel with the new value.
|
||||
- Replaced some OS alerts with a custom made error dialog.
|
||||
- Made the zooming smoother, is toggleable in Preferences whether to keep the new zooming or the old one.
|
||||
- The camera now zooms at the mouse's position.
|
||||
- Made the \"X\" button on the custom brushes a little smaller.
|
||||
- The color picker will now have a small white triangle on the top left of the color preview if at least one of its RGB values are above 1 in Raw mode. (Added automatically because of the Godot 3.2 update)
|
||||
- You can now toggle the visibility of hidden items on and off in the file dialogs. (Added automatically because of the Godot 3.2 update)
|
||||
- The language buttons in the preferences have their localized names in their hint tooltips. For example, if you hover over the \"English\" button while the language is Greek, the hint tooltip will be \"Αγγλικά\", which is the Greek word for English.
|
||||
- Translation updates.
|
||||
- The presets in the ColorPickers are now hidden - Thanks to YeldhamDev!
|
||||
- When opening a project (.pxo file), the save path is being set to the opened project's path - Thanks to YeldhamDev!
|
||||
|
||||
Fixed
|
||||
|
||||
- Delay the splash screen popup so it shows properly centered - Thanks to YeldhamDev!
|
||||
- Possibly fixed crashes with motion drawing and undo/redoing.
|
||||
- Fixed bug (which also caused crashes sometimes) when generating an outline inside the image and it was going outside the canvas' borders.
|
||||
- Fixed crash when importing images that were failing to load. They still fail to load, but Pixelorama does not crash.
|
||||
- Possibly fixed a rare crash where the cursor image was failing to load. It is now being loaded only once.
|
||||
- Fixed ruler markings cutting off before they should - Thanks to YeldhamDev!
|
||||
- Fixed bug where resizing the image on export was not working on Godot 3.2 - Issue #161"
|
||||
autowrap = true
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="Contents"]
|
||||
margin_top = 436.0
|
||||
margin_right = 617.0
|
||||
margin_bottom = 440.0
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="Contents"]
|
||||
margin_top = 440.0
|
||||
margin_right = 617.0
|
||||
margin_bottom = 593.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
custom_constants/margin_right = 10
|
||||
custom_constants/margin_top = 10
|
||||
custom_constants/margin_left = 10
|
||||
custom_constants/margin_bottom = 10
|
||||
|
||||
[node name="Info" type="HBoxContainer" parent="Contents/MarginContainer"]
|
||||
margin_left = 10.0
|
||||
margin_top = 10.0
|
||||
margin_right = 607.0
|
||||
margin_bottom = 143.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
custom_constants/separation = 3
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Sponsors" type="HBoxContainer" parent="Contents/MarginContainer/Info"]
|
||||
margin_right = 362.0
|
||||
margin_bottom = 133.0
|
||||
size_flags_vertical = 3
|
||||
custom_constants/separation = 5
|
||||
|
||||
[node name="PlatinumContainer" type="VBoxContainer" parent="Contents/MarginContainer/Info/Sponsors"]
|
||||
margin_right = 125.0
|
||||
margin_bottom = 133.0
|
||||
rect_min_size = Vector2( 125, 0 )
|
||||
|
||||
[node name="Label" type="Label" parent="Contents/MarginContainer/Info/Sponsors/PlatinumContainer"]
|
||||
margin_right = 125.0
|
||||
margin_bottom = 14.0
|
||||
text = "Platinum Sponsor"
|
||||
align = 1
|
||||
|
||||
[node name="PlaceholderLabel" type="Label" parent="Contents/MarginContainer/Info/Sponsors/PlatinumContainer"]
|
||||
margin_top = 47.0
|
||||
margin_right = 125.0
|
||||
margin_bottom = 80.0
|
||||
size_flags_vertical = 6
|
||||
custom_fonts/font = ExtResource( 6 )
|
||||
custom_colors/font_color = Color( 0.678431, 0.611765, 0.807843, 1 )
|
||||
text = "Platinum
|
||||
Sponsor"
|
||||
align = 1
|
||||
|
||||
[node name="TakeThisSpot" type="Button" parent="Contents/MarginContainer/Info/Sponsors/PlatinumContainer"]
|
||||
margin_top = 113.0
|
||||
margin_right = 125.0
|
||||
margin_bottom = 133.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Take this spot!"
|
||||
flat = true
|
||||
|
||||
[node name="VSeparator" type="VSeparator" parent="Contents/MarginContainer/Info/Sponsors"]
|
||||
margin_left = 130.0
|
||||
margin_right = 134.0
|
||||
margin_bottom = 133.0
|
||||
|
||||
[node name="GoldContainer" type="VBoxContainer" parent="Contents/MarginContainer/Info/Sponsors"]
|
||||
margin_left = 139.0
|
||||
margin_right = 264.0
|
||||
margin_bottom = 133.0
|
||||
rect_min_size = Vector2( 125, 0 )
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="Label" type="Label" parent="Contents/MarginContainer/Info/Sponsors/GoldContainer"]
|
||||
margin_right = 125.0
|
||||
margin_bottom = 14.0
|
||||
text = "Gold Sponsors"
|
||||
align = 1
|
||||
|
||||
[node name="PlaceholderLabel" type="Label" parent="Contents/MarginContainer/Info/Sponsors/GoldContainer"]
|
||||
margin_top = 47.0
|
||||
margin_right = 125.0
|
||||
margin_bottom = 80.0
|
||||
size_flags_vertical = 6
|
||||
custom_fonts/font = ExtResource( 6 )
|
||||
custom_colors/font_color = Color( 0.678431, 0.611765, 0.807843, 1 )
|
||||
text = "Gold
|
||||
Sponsors"
|
||||
align = 1
|
||||
|
||||
[node name="TakeThisSpot" type="Button" parent="Contents/MarginContainer/Info/Sponsors/GoldContainer"]
|
||||
margin_top = 113.0
|
||||
margin_right = 125.0
|
||||
margin_bottom = 133.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Take this spot!"
|
||||
flat = true
|
||||
|
||||
[node name="VSeparator2" type="VSeparator" parent="Contents/MarginContainer/Info/Sponsors"]
|
||||
margin_left = 269.0
|
||||
margin_right = 273.0
|
||||
margin_bottom = 133.0
|
||||
|
||||
[node name="PatronContainer" type="VBoxContainer" parent="Contents/MarginContainer/Info/Sponsors"]
|
||||
margin_left = 278.0
|
||||
margin_right = 362.0
|
||||
margin_bottom = 133.0
|
||||
size_flags_horizontal = 3
|
||||
custom_constants/separation = 10
|
||||
alignment = 1
|
||||
|
||||
[node name="PatronsLabel" type="Label" parent="Contents/MarginContainer/Info/Sponsors/PatronContainer"]
|
||||
margin_right = 84.0
|
||||
margin_bottom = 14.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 8
|
||||
text = "Patrons:"
|
||||
align = 1
|
||||
|
||||
[node name="PatronButton" type="TextureButton" parent="Contents/MarginContainer/Info/Sponsors/PatronContainer"]
|
||||
margin_top = 24.0
|
||||
margin_right = 84.0
|
||||
margin_bottom = 133.0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
texture_normal = ExtResource( 3 )
|
||||
texture_hover = ExtResource( 4 )
|
||||
stretch_mode = 5
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="Contents/MarginContainer/Info"]
|
||||
margin_left = 365.0
|
||||
margin_right = 597.0
|
||||
margin_bottom = 133.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
custom_constants/separation = 5
|
||||
alignment = 2
|
||||
|
||||
[node name="Branding" type="HBoxContainer" parent="Contents/MarginContainer/Info/VBoxContainer"]
|
||||
margin_right = 232.0
|
||||
margin_bottom = 104.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
alignment = 2
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="Contents/MarginContainer/Info/VBoxContainer/Branding"]
|
||||
margin_left = 99.0
|
||||
margin_right = 196.0
|
||||
margin_bottom = 104.0
|
||||
size_flags_vertical = 3
|
||||
alignment = 1
|
||||
|
||||
[node name="Logo" type="TextureRect" parent="Contents/MarginContainer/Info/VBoxContainer/Branding/VBoxContainer"]
|
||||
margin_top = 3.0
|
||||
margin_right = 97.0
|
||||
margin_bottom = 67.0
|
||||
texture = ExtResource( 8 )
|
||||
stretch_mode = 4
|
||||
|
||||
[node name="DevelopedBy" type="Label" parent="Contents/MarginContainer/Info/VBoxContainer/Branding/VBoxContainer"]
|
||||
margin_top = 71.0
|
||||
margin_right = 97.0
|
||||
margin_bottom = 84.0
|
||||
custom_fonts/font = ExtResource( 7 )
|
||||
text = "Orama Interactive"
|
||||
align = 1
|
||||
|
||||
[node name="Copyright" type="Label" parent="Contents/MarginContainer/Info/VBoxContainer/Branding/VBoxContainer"]
|
||||
margin_top = 88.0
|
||||
margin_right = 97.0
|
||||
margin_bottom = 101.0
|
||||
custom_fonts/font = ExtResource( 7 )
|
||||
text = "Copyright 2019-2020"
|
||||
align = 1
|
||||
|
||||
[node name="Links" type="VBoxContainer" parent="Contents/MarginContainer/Info/VBoxContainer/Branding"]
|
||||
margin_left = 200.0
|
||||
margin_right = 232.0
|
||||
margin_bottom = 104.0
|
||||
|
||||
[node name="TextureButton" type="TextureButton" parent="Contents/MarginContainer/Info/VBoxContainer/Branding/Links"]
|
||||
margin_right = 32.0
|
||||
margin_bottom = 32.0
|
||||
texture_normal = ExtResource( 10 )
|
||||
|
||||
[node name="TextureButton2" type="TextureButton" parent="Contents/MarginContainer/Info/VBoxContainer/Branding/Links"]
|
||||
margin_top = 36.0
|
||||
margin_right = 32.0
|
||||
margin_bottom = 68.0
|
||||
texture_normal = ExtResource( 9 )
|
||||
|
||||
[node name="TextureButton3" type="TextureButton" parent="Contents/MarginContainer/Info/VBoxContainer/Branding/Links"]
|
||||
margin_top = 72.0
|
||||
margin_right = 32.0
|
||||
margin_bottom = 104.0
|
||||
texture_normal = ExtResource( 11 )
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="Contents/MarginContainer/Info/VBoxContainer"]
|
||||
margin_top = 109.0
|
||||
margin_right = 232.0
|
||||
margin_bottom = 133.0
|
||||
alignment = 2
|
||||
|
||||
[node name="ShowOnStartup" type="CheckBox" parent="Contents/MarginContainer/Info/VBoxContainer/HBoxContainer"]
|
||||
margin_left = 127.0
|
||||
margin_right = 232.0
|
||||
margin_bottom = 24.0
|
||||
mouse_default_cursor_shape = 2
|
||||
custom_fonts/font = ExtResource( 7 )
|
||||
text = "Don't show again"
|
||||
[connection signal="about_to_show" from="." to="." method="_on_SplashDialog_about_to_show"]
|
||||
[connection signal="pressed" from="Contents/HBoxContainer/Logo_ArtWork/CenterContainer/ArtContainer/SplashArt" to="." method="_on_ArtCredits_pressed"]
|
||||
[connection signal="pressed" from="Contents/HBoxContainer/Logo_ArtWork/CenterContainer/ArtContainer/ArtCredits" to="." method="_on_ArtCredits_pressed"]
|
||||
[connection signal="pressed" from="Contents/HBoxContainer/Buttons_Changelog/VBoxContainer/Buttons/NewBtn" to="." method="_on_NewBtn_pressed"]
|
||||
[connection signal="pressed" from="Contents/HBoxContainer/Buttons_Changelog/VBoxContainer/Buttons/OpenBtn " to="." method="_on_OpenBtn__pressed"]
|
||||
[connection signal="pressed" from="Contents/HBoxContainer/Buttons_Changelog/VBoxContainer/Buttons/OpenLastBtn" to="." method="_on_OpenLastBtn_pressed"]
|
||||
[connection signal="pressed" from="Contents/HBoxContainer/Buttons_Changelog/VBoxContainer/Buttons/ImportBtn" to="." method="_on_ImportBtn_pressed"]
|
||||
[connection signal="pressed" from="Contents/MarginContainer/Info/Sponsors/PlatinumContainer/TakeThisSpot" to="." method="_on_TakeThisSpot_pressed"]
|
||||
[connection signal="pressed" from="Contents/MarginContainer/Info/Sponsors/GoldContainer/TakeThisSpot" to="." method="_on_TakeThisSpot_pressed"]
|
||||
[connection signal="pressed" from="Contents/MarginContainer/Info/Sponsors/PatronContainer/PatronButton" to="." method="_on_PatronButton_pressed"]
|
||||
[connection signal="pressed" from="Contents/MarginContainer/Info/VBoxContainer/Branding/Links/TextureButton" to="." method="_on_GithubButton_pressed"]
|
||||
[connection signal="pressed" from="Contents/MarginContainer/Info/VBoxContainer/Branding/Links/TextureButton2" to="." method="_on_DiscordButton_pressed"]
|
||||
[connection signal="pressed" from="Contents/MarginContainer/Info/VBoxContainer/Branding/Links/TextureButton3" to="." method="_on_PatronButton_pressed"]
|
||||
[connection signal="toggled" from="Contents/MarginContainer/Info/VBoxContainer/HBoxContainer/ShowOnStartup" to="." method="_on_ShowOnStartup_toggled"]
|
12
src/UI/NotificationLabel.gd
Normal file
12
src/UI/NotificationLabel.gd
Normal file
|
@ -0,0 +1,12 @@
|
|||
extends Label
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
var tween := $Tween
|
||||
tween.interpolate_property(self, "rect_position", rect_position, Vector2(rect_position.x, rect_position.y - 100), 1, Tween.TRANS_LINEAR, Tween.EASE_OUT)
|
||||
tween.interpolate_property(self, "modulate", modulate, Color(modulate.r, modulate.g, modulate.b, 0), 1, Tween.TRANS_LINEAR, Tween.EASE_OUT)
|
||||
tween.start()
|
||||
|
||||
|
||||
func _on_Timer_timeout() -> void:
|
||||
queue_free()
|
22
src/UI/NotificationLabel.tscn
Normal file
22
src/UI/NotificationLabel.tscn
Normal file
|
@ -0,0 +1,22 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://src/UI/NotificationLabel.gd" type="Script" id=2]
|
||||
|
||||
|
||||
|
||||
[node name="NotificationLabel" type="Label"]
|
||||
margin_right = 116.0
|
||||
margin_bottom = 14.0
|
||||
custom_colors/font_color_shadow = Color( 0, 0, 0, 1 )
|
||||
text = "Undo: Notification"
|
||||
script = ExtResource( 2 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Tween" type="Tween" parent="."]
|
||||
|
||||
[node name="Timer" type="Timer" parent="."]
|
||||
one_shot = true
|
||||
autostart = true
|
||||
[connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"]
|
29
src/UI/PatternButton.gd
Normal file
29
src/UI/PatternButton.gd
Normal file
|
@ -0,0 +1,29 @@
|
|||
extends TextureButton
|
||||
|
||||
|
||||
var image : Image
|
||||
var image_size : Vector2
|
||||
var texture : ImageTexture
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
if image:
|
||||
image_size = image.get_size()
|
||||
texture = ImageTexture.new()
|
||||
texture.create_from_image(image, 0)
|
||||
|
||||
|
||||
func _on_PatternButton_pressed() -> void:
|
||||
if Global.pattern_window_position == "left":
|
||||
Global.pattern_left_image = image
|
||||
Global.left_fill_pattern_container.get_child(0).get_child(0).texture = texture
|
||||
Global.left_fill_pattern_container.get_child(2).get_child(1).max_value = image_size.x - 1
|
||||
Global.left_fill_pattern_container.get_child(3).get_child(1).max_value = image_size.y - 1
|
||||
|
||||
elif Global.pattern_window_position == "right":
|
||||
Global.pattern_right_image = image
|
||||
Global.right_fill_pattern_container.get_child(0).get_child(0).texture = texture
|
||||
Global.right_fill_pattern_container.get_child(2).get_child(1).max_value = image_size.x - 1
|
||||
Global.right_fill_pattern_container.get_child(3).get_child(1).max_value = image_size.y - 1
|
||||
|
||||
Global.patterns_popup.hide()
|
29
src/UI/PatternButton.tscn
Normal file
29
src/UI/PatternButton.tscn
Normal file
|
@ -0,0 +1,29 @@
|
|||
[gd_scene load_steps=3 format=2]
|
||||
|
||||
[ext_resource path="res://Assets/Graphics/Brush_button.png" type="Texture" id=1]
|
||||
[ext_resource path="res://src/UI/PatternButton.gd" type="Script" id=2]
|
||||
|
||||
|
||||
|
||||
[node name="PatternButton" type="TextureButton"]
|
||||
margin_right = 32.0
|
||||
margin_bottom = 32.0
|
||||
rect_min_size = Vector2( 3, 0 )
|
||||
button_mask = 7
|
||||
texture_normal = ExtResource( 1 )
|
||||
stretch_mode = 5
|
||||
script = ExtResource( 2 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="PatternTexture" type="TextureRect" parent="."]
|
||||
margin_right = 32.0
|
||||
margin_bottom = 32.0
|
||||
rect_min_size = Vector2( 32, 32 )
|
||||
expand = true
|
||||
stretch_mode = 6
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
[connection signal="pressed" from="." to="." method="_on_PatternButton_pressed"]
|
76
src/UI/Rulers/Guides.gd
Normal file
76
src/UI/Rulers/Guides.gd
Normal file
|
@ -0,0 +1,76 @@
|
|||
class_name Guide
|
||||
extends Line2D
|
||||
|
||||
enum Types {HORIZONTAL, VERTICAL}
|
||||
|
||||
var font := preload("res://Assets/Fonts/Roboto-Regular.tres")
|
||||
var has_focus := true
|
||||
var mouse_pos := Vector2.ZERO
|
||||
var previous_points := points
|
||||
var type = Types.HORIZONTAL
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
width = 0.1
|
||||
default_color = Global.guide_color
|
||||
|
||||
|
||||
func _input(_event : InputEvent):
|
||||
width = Global.camera.zoom.x * 2
|
||||
mouse_pos = get_local_mouse_position()
|
||||
var point0 := points[0]
|
||||
var point1 := points[1]
|
||||
if type == Types.HORIZONTAL:
|
||||
point0.y -= width * 3
|
||||
point1.y += width * 3
|
||||
else:
|
||||
point0.x -= width * 3
|
||||
point1.x += width * 3
|
||||
if Global.can_draw and Global.has_focus and point_in_rectangle(mouse_pos, point0, point1) and Input.is_action_just_pressed("left_mouse"):
|
||||
if !point_in_rectangle(Global.canvas.current_pixel, Global.canvas.location, Global.canvas.location + Global.canvas.size):
|
||||
has_focus = true
|
||||
Global.has_focus = false
|
||||
update()
|
||||
if has_focus:
|
||||
if Input.is_action_just_pressed("left_mouse"):
|
||||
previous_points = points
|
||||
if Input.is_action_pressed("left_mouse"):
|
||||
if type == Types.HORIZONTAL:
|
||||
points[0].y = round(mouse_pos.y)
|
||||
points[1].y = round(mouse_pos.y)
|
||||
else:
|
||||
points[0].x = round(mouse_pos.x)
|
||||
points[1].x = round(mouse_pos.x)
|
||||
if Input.is_action_just_released("left_mouse"):
|
||||
Global.has_focus = true
|
||||
has_focus = false
|
||||
if !outside_canvas():
|
||||
update()
|
||||
|
||||
|
||||
func _draw() -> void:
|
||||
if has_focus:
|
||||
var viewport_size: Vector2 = Global.main_viewport.rect_size
|
||||
var zoom: Vector2 = Global.camera.zoom
|
||||
if type == Types.HORIZONTAL:
|
||||
draw_set_transform(Vector2(Global.camera.offset.x - (viewport_size.x / 2) * zoom.x, points[0].y + font.get_height() * zoom.x * 2), rotation, zoom * 2)
|
||||
draw_string(font, Vector2.ZERO, "%spx" % str(round(mouse_pos.y)))
|
||||
else:
|
||||
draw_set_transform(Vector2(points[0].x + font.get_height() * zoom.y, Global.camera.offset.y - (viewport_size.y / 2.25) * zoom.y), rotation, zoom * 2)
|
||||
draw_string(font, Vector2.ZERO, "%spx" % str(round(mouse_pos.x)))
|
||||
|
||||
|
||||
func outside_canvas() -> bool:
|
||||
if type == Types.HORIZONTAL:
|
||||
if points[0].y < 0 || points[0].y > Global.canvas.size.y:
|
||||
queue_free()
|
||||
return true
|
||||
else:
|
||||
if points[0].x < 0 || points[0].x > Global.canvas.size.x:
|
||||
queue_free()
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
func point_in_rectangle(p : Vector2, coord1 : Vector2, coord2 : Vector2) -> bool:
|
||||
return p.x > coord1.x && p.y > coord1.y && p.x < coord2.x && p.y < coord2.y
|
79
src/UI/Rulers/HorizontalRuler.gd
Normal file
79
src/UI/Rulers/HorizontalRuler.gd
Normal file
|
@ -0,0 +1,79 @@
|
|||
extends Button
|
||||
|
||||
const RULER_WIDTH := 16
|
||||
|
||||
var font := preload("res://Assets/Fonts/Roboto-Small.tres")
|
||||
var major_subdivision := 2
|
||||
var minor_subdivision := 4
|
||||
|
||||
var first : Vector2
|
||||
var last : Vector2
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
Global.main_viewport.connect("item_rect_changed", self, "update")
|
||||
|
||||
|
||||
# Code taken and modified from Godot's source code
|
||||
func _draw() -> void:
|
||||
var transform := Transform2D()
|
||||
var ruler_transform := Transform2D()
|
||||
var major_subdivide := Transform2D()
|
||||
var minor_subdivide := Transform2D()
|
||||
var zoom: float = 1 / Global.camera.zoom.x
|
||||
transform.x = Vector2(zoom, zoom)
|
||||
|
||||
transform.origin = Global.main_viewport.rect_size / 2 + Global.camera.offset * -zoom
|
||||
|
||||
var basic_rule := 100.0
|
||||
var i := 0
|
||||
while(basic_rule * zoom > 100):
|
||||
basic_rule /= 5.0 if i % 2 else 2.0
|
||||
i += 1
|
||||
i = 0
|
||||
while(basic_rule * zoom < 100):
|
||||
basic_rule *= 2.0 if i % 2 else 5.0
|
||||
i += 1
|
||||
|
||||
ruler_transform = ruler_transform.scaled(Vector2(basic_rule, basic_rule))
|
||||
|
||||
major_subdivide = major_subdivide.scaled(Vector2(1.0 / major_subdivision, 1.0 / major_subdivision))
|
||||
minor_subdivide = minor_subdivide.scaled(Vector2(1.0 / minor_subdivision, 1.0 / minor_subdivision))
|
||||
|
||||
first = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(Vector2.ZERO)
|
||||
last = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(Global.main_viewport.rect_size)
|
||||
|
||||
for i in range(ceil(first.x), ceil(last.x)):
|
||||
var position : Vector2 = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Vector2(i, 0))
|
||||
if i % (major_subdivision * minor_subdivision) == 0:
|
||||
draw_line(Vector2(position.x + RULER_WIDTH, 0), Vector2(position.x + RULER_WIDTH, RULER_WIDTH), Color.white)
|
||||
var val = (ruler_transform * major_subdivide * minor_subdivide).xform(Vector2(i, 0)).x
|
||||
draw_string(font, Vector2(position.x + RULER_WIDTH + 2, font.get_height() - 4), str(int(val)))
|
||||
else:
|
||||
if i % minor_subdivision == 0:
|
||||
draw_line(Vector2(position.x + RULER_WIDTH, RULER_WIDTH * 0.33), Vector2(position.x + RULER_WIDTH, RULER_WIDTH), Color.white)
|
||||
else:
|
||||
draw_line(Vector2(position.x + RULER_WIDTH, RULER_WIDTH * 0.66), Vector2(position.x + RULER_WIDTH, RULER_WIDTH), Color.white)
|
||||
|
||||
|
||||
func _on_HorizontalRuler_pressed() -> void:
|
||||
if !Global.show_guides:
|
||||
return
|
||||
var mouse_pos := get_local_mouse_position()
|
||||
if mouse_pos.x < RULER_WIDTH: # For double guides
|
||||
Global.vertical_ruler._on_VerticalRuler_pressed()
|
||||
var guide := Guide.new()
|
||||
guide.type = guide.Types.HORIZONTAL
|
||||
guide.add_point(Vector2(-99999, Global.canvas.current_pixel.y))
|
||||
guide.add_point(Vector2(99999, Global.canvas.current_pixel.y))
|
||||
Global.canvas.add_child(guide)
|
||||
Global.has_focus = false
|
||||
update()
|
||||
|
||||
|
||||
func _on_HorizontalRuler_mouse_entered() -> void:
|
||||
var mouse_pos := get_local_mouse_position()
|
||||
if mouse_pos.x < RULER_WIDTH: # For double guides
|
||||
mouse_default_cursor_shape = Control.CURSOR_FDIAGSIZE
|
||||
else:
|
||||
mouse_default_cursor_shape = Control.CURSOR_VSPLIT
|
71
src/UI/Rulers/VerticalRuler.gd
Normal file
71
src/UI/Rulers/VerticalRuler.gd
Normal file
|
@ -0,0 +1,71 @@
|
|||
extends Button
|
||||
|
||||
const RULER_WIDTH := 16
|
||||
|
||||
var font := preload("res://Assets/Fonts/Roboto-Small.tres")
|
||||
var major_subdivision := 2
|
||||
var minor_subdivision := 4
|
||||
|
||||
var first : Vector2
|
||||
var last : Vector2
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
Global.main_viewport.connect("item_rect_changed", self, "update")
|
||||
|
||||
|
||||
# Code taken and modified from Godot's source code
|
||||
func _draw() -> void:
|
||||
var transform := Transform2D()
|
||||
var ruler_transform := Transform2D()
|
||||
var major_subdivide := Transform2D()
|
||||
var minor_subdivide := Transform2D()
|
||||
var zoom: float = 1 / Global.camera.zoom.x
|
||||
transform.y = Vector2(zoom, zoom)
|
||||
|
||||
transform.origin = Global.main_viewport.rect_size / 2 + Global.camera.offset * -zoom
|
||||
|
||||
var basic_rule := 100.0
|
||||
var i := 0
|
||||
while(basic_rule * zoom > 100):
|
||||
basic_rule /= 5.0 if i % 2 else 2.0
|
||||
i += 1
|
||||
i = 0
|
||||
while(basic_rule * zoom < 100):
|
||||
basic_rule *= 2.0 if i % 2 else 5.0
|
||||
i += 1
|
||||
|
||||
ruler_transform = ruler_transform.scaled(Vector2(basic_rule, basic_rule))
|
||||
|
||||
major_subdivide = major_subdivide.scaled(Vector2(1.0 / major_subdivision, 1.0 / major_subdivision))
|
||||
minor_subdivide = minor_subdivide.scaled(Vector2(1.0 / minor_subdivision, 1.0 / minor_subdivision))
|
||||
|
||||
first = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(Vector2.ZERO)
|
||||
last = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(Global.main_viewport.rect_size)
|
||||
|
||||
for i in range(ceil(first.y), ceil(last.y)):
|
||||
var position : Vector2 = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Vector2(0, i))
|
||||
if i % (major_subdivision * minor_subdivision) == 0:
|
||||
draw_line(Vector2(0, position.y), Vector2(RULER_WIDTH, position.y), Color.white)
|
||||
var text_xform = Transform2D(-PI / 2, Vector2(font.get_height() - 4, position.y - 2))
|
||||
draw_set_transform_matrix(get_transform() * text_xform)
|
||||
var val = (ruler_transform * major_subdivide * minor_subdivide).xform(Vector2(0, i)).y
|
||||
draw_string(font, Vector2(), str(int(val)))
|
||||
draw_set_transform_matrix(get_transform())
|
||||
else:
|
||||
if i % minor_subdivision == 0:
|
||||
draw_line(Vector2(RULER_WIDTH * 0.33, position.y), Vector2(RULER_WIDTH, position.y), Color.white)
|
||||
else:
|
||||
draw_line(Vector2(RULER_WIDTH * 0.66, position.y), Vector2(RULER_WIDTH, position.y), Color.white)
|
||||
|
||||
|
||||
func _on_VerticalRuler_pressed() -> void:
|
||||
if !Global.show_guides:
|
||||
return
|
||||
var guide := Guide.new()
|
||||
guide.type = guide.Types.VERTICAL
|
||||
guide.add_point(Vector2(Global.canvas.current_pixel.x, -99999))
|
||||
guide.add_point(Vector2(Global.canvas.current_pixel.x, 99999))
|
||||
Global.canvas.add_child(guide)
|
||||
Global.has_focus = false
|
||||
update()
|
6
src/UI/SecondViewport.gd
Normal file
6
src/UI/SecondViewport.gd
Normal file
|
@ -0,0 +1,6 @@
|
|||
extends Viewport
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
world_2d = Global.canvas.get_parent().world_2d
|
24
src/UI/Timeline/AnimationTag.tscn
Normal file
24
src/UI/Timeline/AnimationTag.tscn
Normal file
|
@ -0,0 +1,24 @@
|
|||
[gd_scene format=2]
|
||||
|
||||
[node name="AnimationTag" type="VBoxContainer"]
|
||||
margin_right = 39.0
|
||||
margin_bottom = 32.0
|
||||
rect_min_size = Vector2( 39, 32 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Line2D" type="Line2D" parent="."]
|
||||
points = PoolVector2Array( 0, 32, 0, 0, 39, 0, 39, 32 )
|
||||
width = 1.0
|
||||
texture_mode = 1313163520
|
||||
|
||||
[node name="Label" type="Label" parent="."]
|
||||
margin_left = 7.0
|
||||
margin_right = 32.0
|
||||
margin_bottom = 32.0
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 3
|
||||
text = "Idle"
|
||||
align = 1
|
||||
valign = 1
|
494
src/UI/Timeline/AnimationTimeline.gd
Normal file
494
src/UI/Timeline/AnimationTimeline.gd
Normal file
|
@ -0,0 +1,494 @@
|
|||
extends Panel
|
||||
|
||||
var fps := 6.0
|
||||
var animation_loop := 1 # 0 is no loop, 1 is cycle loop, 2 is ping-pong loop
|
||||
var animation_forward := true
|
||||
var first_frame := 0
|
||||
var last_frame := Global.canvases.size() - 1
|
||||
|
||||
onready var timeline_scroll : ScrollContainer = $AnimationContainer/TimelineContainer/TimelineScroll
|
||||
onready var tag_scroll_container : ScrollContainer = $AnimationContainer/TimelineContainer/OpacityAndTagContainer/TagScroll
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
timeline_scroll.get_h_scrollbar().connect("value_changed", self, "_h_scroll_changed")
|
||||
Global.animation_timer.wait_time = 1 / fps
|
||||
|
||||
|
||||
func _h_scroll_changed(value : float) -> void:
|
||||
# Let the main timeline ScrollContainer affect the tag ScrollContainer too
|
||||
tag_scroll_container.get_child(0).rect_min_size.x = timeline_scroll.get_child(0).rect_size.x - 212
|
||||
tag_scroll_container.scroll_horizontal = value
|
||||
|
||||
|
||||
func add_frame() -> void:
|
||||
var new_canvas : Canvas = load("res://src/Canvas.tscn").instance()
|
||||
new_canvas.size = Global.canvas.size
|
||||
new_canvas.frame = Global.canvases.size()
|
||||
|
||||
var new_canvases: Array = Global.canvases.duplicate()
|
||||
new_canvases.append(new_canvas)
|
||||
|
||||
Global.undos += 1
|
||||
Global.undo_redo.create_action("Add Frame")
|
||||
Global.undo_redo.add_do_method(Global, "redo", [new_canvas])
|
||||
Global.undo_redo.add_undo_method(Global, "undo", [new_canvas])
|
||||
|
||||
Global.undo_redo.add_do_property(Global, "canvases", new_canvases)
|
||||
Global.undo_redo.add_do_property(Global, "canvas", new_canvas)
|
||||
Global.undo_redo.add_do_property(Global, "current_frame", new_canvases.size() - 1)
|
||||
|
||||
for c in Global.canvases:
|
||||
Global.undo_redo.add_do_property(c, "visible", false)
|
||||
Global.undo_redo.add_undo_property(c, "visible", c.visible)
|
||||
|
||||
for l_i in range(Global.layers.size()):
|
||||
if Global.layers[l_i][4]: # If the link button is pressed
|
||||
Global.layers[l_i][5].append(new_canvas)
|
||||
|
||||
Global.undo_redo.add_undo_property(Global, "canvases", Global.canvases)
|
||||
Global.undo_redo.add_undo_property(Global, "canvas", Global.canvas)
|
||||
Global.undo_redo.add_undo_property(Global, "current_frame", Global.current_frame)
|
||||
Global.undo_redo.commit_action()
|
||||
|
||||
|
||||
func _on_DeleteFrame_pressed(frame := -1) -> void:
|
||||
if Global.canvases.size() == 1:
|
||||
return
|
||||
if frame == -1:
|
||||
frame = Global.current_frame
|
||||
|
||||
var canvas : Canvas = Global.canvases[frame]
|
||||
var new_canvases := Global.canvases.duplicate()
|
||||
new_canvases.erase(canvas)
|
||||
var current_frame := Global.current_frame
|
||||
if current_frame > 0 && current_frame == new_canvases.size(): # If it's the last frame
|
||||
current_frame -= 1
|
||||
|
||||
var new_animation_tags := Global.animation_tags.duplicate(true)
|
||||
# Loop through the tags to see if the frame is in one
|
||||
for tag in new_animation_tags:
|
||||
if frame + 1 >= tag[2] && frame + 1 <= tag[3]:
|
||||
if tag[3] == tag[2]: # If we're deleting the only frame in the tag
|
||||
new_animation_tags.erase(tag)
|
||||
else:
|
||||
tag[3] -= 1
|
||||
elif frame + 1 < tag[2]:
|
||||
tag[2] -= 1
|
||||
tag[3] -= 1
|
||||
|
||||
# Check if one of the cels of the frame is linked
|
||||
# if they are, unlink them too
|
||||
# this prevents removed cels being kept in linked memory
|
||||
var new_layers := Global.layers.duplicate(true)
|
||||
for layer in new_layers:
|
||||
for linked in layer[5]:
|
||||
if linked == Global.canvases[frame]:
|
||||
layer[5].erase(linked)
|
||||
|
||||
Global.undos += 1
|
||||
Global.undo_redo.create_action("Remove Frame")
|
||||
|
||||
Global.undo_redo.add_do_property(Global, "canvases", new_canvases)
|
||||
Global.undo_redo.add_do_property(Global, "canvas", new_canvases[current_frame])
|
||||
Global.undo_redo.add_do_property(Global, "current_frame", current_frame)
|
||||
Global.undo_redo.add_do_property(Global, "animation_tags", new_animation_tags)
|
||||
Global.undo_redo.add_do_property(Global, "layers", new_layers)
|
||||
|
||||
# Change the frame value of the canvaseso on the right
|
||||
# for example, if frame "3" was deleted, then "4" would have to become "3"
|
||||
for i in range(frame, new_canvases.size()):
|
||||
var c : Canvas = new_canvases[i]
|
||||
Global.undo_redo.add_do_property(c, "frame", i)
|
||||
Global.undo_redo.add_undo_property(c, "frame", c.frame)
|
||||
|
||||
|
||||
Global.undo_redo.add_undo_property(Global, "canvases", Global.canvases)
|
||||
Global.undo_redo.add_undo_property(Global, "canvas", canvas)
|
||||
Global.undo_redo.add_undo_property(Global, "current_frame", Global.current_frame)
|
||||
Global.undo_redo.add_undo_property(Global, "animation_tags", Global.animation_tags)
|
||||
Global.undo_redo.add_undo_property(Global, "layers", Global.layers)
|
||||
|
||||
Global.undo_redo.add_do_method(Global, "redo", [canvas])
|
||||
Global.undo_redo.add_undo_method(Global, "undo", [canvas])
|
||||
Global.undo_redo.commit_action()
|
||||
|
||||
|
||||
func _on_CopyFrame_pressed(frame := -1) -> void:
|
||||
if frame == -1:
|
||||
frame = Global.current_frame
|
||||
|
||||
var canvas : Canvas = Global.canvases[frame]
|
||||
var new_canvas : Canvas = load("res://src/Canvas.tscn").instance()
|
||||
new_canvas.size = Global.canvas.size
|
||||
new_canvas.frame = Global.canvases.size()
|
||||
|
||||
var new_canvases := Global.canvases.duplicate()
|
||||
new_canvases.insert(frame + 1, new_canvas)
|
||||
|
||||
for layer in canvas.layers: # Copy every layer
|
||||
var sprite := Image.new()
|
||||
sprite.copy_from(layer[0])
|
||||
sprite.lock()
|
||||
var tex := ImageTexture.new()
|
||||
tex.create_from_image(sprite, 0)
|
||||
new_canvas.layers.append([sprite, tex, layer[2]])
|
||||
|
||||
var new_animation_tags := Global.animation_tags.duplicate(true)
|
||||
# Loop through the tags to see if the frame is in one
|
||||
for tag in new_animation_tags:
|
||||
if frame + 1 >= tag[2] && frame + 1 <= tag[3]:
|
||||
tag[3] += 1
|
||||
|
||||
Global.undos += 1
|
||||
Global.undo_redo.create_action("Add Frame")
|
||||
Global.undo_redo.add_do_method(Global, "redo", [new_canvas])
|
||||
Global.undo_redo.add_undo_method(Global, "undo", [new_canvas])
|
||||
|
||||
Global.undo_redo.add_do_property(Global, "canvases", new_canvases)
|
||||
Global.undo_redo.add_do_property(Global, "canvas", new_canvas)
|
||||
Global.undo_redo.add_do_property(Global, "current_frame", frame + 1)
|
||||
Global.undo_redo.add_do_property(Global, "animation_tags", new_animation_tags)
|
||||
for i in range(Global.layers.size()):
|
||||
for child in Global.layers[i][3].get_children():
|
||||
Global.undo_redo.add_do_property(child, "pressed", false)
|
||||
Global.undo_redo.add_undo_property(child, "pressed", child.pressed)
|
||||
for c in Global.canvases:
|
||||
Global.undo_redo.add_do_property(c, "visible", false)
|
||||
Global.undo_redo.add_undo_property(c, "visible", c.visible)
|
||||
|
||||
for i in range(frame, new_canvases.size()):
|
||||
var c : Canvas = new_canvases[i]
|
||||
Global.undo_redo.add_do_property(c, "frame", i)
|
||||
Global.undo_redo.add_undo_property(c, "frame", c.frame)
|
||||
|
||||
Global.undo_redo.add_undo_property(Global, "canvases", Global.canvases)
|
||||
Global.undo_redo.add_undo_property(Global, "canvas", Global.canvas)
|
||||
Global.undo_redo.add_undo_property(Global, "current_frame", frame)
|
||||
Global.undo_redo.add_undo_property(Global, "animation_tags", Global.animation_tags)
|
||||
Global.undo_redo.commit_action()
|
||||
|
||||
|
||||
func _on_FrameTagButton_pressed() -> void:
|
||||
Global.tag_dialog.popup_centered()
|
||||
|
||||
|
||||
func _on_OnionSkinning_pressed() -> void:
|
||||
Global.onion_skinning = !Global.onion_skinning
|
||||
Global.canvas.update()
|
||||
var theme_type := Global.theme_type
|
||||
if theme_type == "Gold":
|
||||
theme_type = "Light"
|
||||
var texture_button : TextureRect = Global.onion_skinning_button.get_child(0)
|
||||
if Global.onion_skinning:
|
||||
texture_button.texture = load("res://Assets/Graphics/%s Themes/Timeline/onion_skinning.png" % theme_type)
|
||||
else:
|
||||
texture_button.texture = load("res://Assets/Graphics/%s Themes/Timeline/onion_skinning_off.png" % theme_type)
|
||||
|
||||
|
||||
func _on_OnionSkinningSettings_pressed() -> void:
|
||||
$OnionSkinningSettings.popup(Rect2(Global.onion_skinning_button.rect_global_position.x - $OnionSkinningSettings.rect_size.x - 16, Global.onion_skinning_button.rect_global_position.y - 106, 136, 126))
|
||||
|
||||
|
||||
func _on_LoopAnim_pressed() -> void:
|
||||
var texture_button : TextureRect = Global.loop_animation_button.get_child(0)
|
||||
var theme_type := Global.theme_type
|
||||
if theme_type == "Gold":
|
||||
theme_type = "Light"
|
||||
match animation_loop:
|
||||
0: # Make it loop
|
||||
animation_loop = 1
|
||||
texture_button.texture = load("res://Assets/Graphics/%s Themes/Timeline/loop.png" % theme_type)
|
||||
Global.loop_animation_button.hint_tooltip = "Cycle loop"
|
||||
1: # Make it ping-pong
|
||||
animation_loop = 2
|
||||
texture_button.texture = load("res://Assets/Graphics/%s Themes/Timeline/loop_pingpong.png" % theme_type)
|
||||
Global.loop_animation_button.hint_tooltip = "Ping-pong loop"
|
||||
2: # Make it stop
|
||||
animation_loop = 0
|
||||
texture_button.texture = load("res://Assets/Graphics/%s Themes/Timeline/loop_none.png" % theme_type)
|
||||
Global.loop_animation_button.hint_tooltip = "No loop"
|
||||
|
||||
|
||||
func _on_PlayForward_toggled(button_pressed : bool) -> void:
|
||||
var theme_type := Global.theme_type
|
||||
if theme_type == "Gold":
|
||||
theme_type = "Light"
|
||||
if button_pressed:
|
||||
Global.play_forward.get_child(0).texture = load("res://Assets/Graphics/%s Themes/Timeline/pause.png" % theme_type)
|
||||
else:
|
||||
Global.play_forward.get_child(0).texture = load("res://Assets/Graphics/%s Themes/Timeline/play.png" % theme_type)
|
||||
|
||||
play_animation(button_pressed, true)
|
||||
|
||||
|
||||
func _on_PlayBackwards_toggled(button_pressed : bool) -> void:
|
||||
var theme_type := Global.theme_type
|
||||
if theme_type == "Gold":
|
||||
theme_type = "Light"
|
||||
if button_pressed:
|
||||
Global.play_backwards.get_child(0).texture = load("res://Assets/Graphics/%s Themes/Timeline/pause.png" % theme_type)
|
||||
else:
|
||||
Global.play_backwards.get_child(0).texture = load("res://Assets/Graphics/%s Themes/Timeline/play_backwards.png" % theme_type)
|
||||
|
||||
play_animation(button_pressed, false)
|
||||
|
||||
|
||||
func _on_AnimationTimer_timeout() -> void:
|
||||
if animation_forward:
|
||||
if Global.current_frame < last_frame:
|
||||
Global.current_frame += 1
|
||||
else:
|
||||
match animation_loop:
|
||||
0: # No loop
|
||||
Global.play_forward.pressed = false
|
||||
Global.play_backwards.pressed = false
|
||||
Global.animation_timer.stop()
|
||||
1: # Cycle loop
|
||||
Global.current_frame = first_frame
|
||||
2: # Ping pong loop
|
||||
animation_forward = false
|
||||
_on_AnimationTimer_timeout()
|
||||
|
||||
else:
|
||||
if Global.current_frame > first_frame:
|
||||
Global.current_frame -= 1
|
||||
else:
|
||||
match animation_loop:
|
||||
0: # No loop
|
||||
Global.play_backwards.pressed = false
|
||||
Global.play_forward.pressed = false
|
||||
Global.animation_timer.stop()
|
||||
1: # Cycle loop
|
||||
Global.current_frame = last_frame
|
||||
2: # Ping pong loop
|
||||
animation_forward = true
|
||||
_on_AnimationTimer_timeout()
|
||||
|
||||
|
||||
func play_animation(play : bool, forward_dir : bool) -> void:
|
||||
var theme_type := Global.theme_type
|
||||
if theme_type == "Gold":
|
||||
theme_type = "Light"
|
||||
|
||||
if forward_dir:
|
||||
Global.play_backwards.disconnect("toggled", self, "_on_PlayBackwards_toggled")
|
||||
Global.play_backwards.pressed = false
|
||||
Global.play_backwards.get_child(0).texture = load("res://Assets/Graphics/%s Themes/Timeline/play_backwards.png" % theme_type)
|
||||
Global.play_backwards.connect("toggled", self, "_on_PlayBackwards_toggled")
|
||||
else:
|
||||
Global.play_forward.disconnect("toggled", self, "_on_PlayForward_toggled")
|
||||
Global.play_forward.pressed = false
|
||||
Global.play_forward.get_child(0).texture = load("res://Assets/Graphics/%s Themes/Timeline/play.png" % theme_type)
|
||||
Global.play_forward.connect("toggled", self, "_on_PlayForward_toggled")
|
||||
if Global.canvases.size() == 1:
|
||||
if forward_dir:
|
||||
Global.play_forward.pressed = false
|
||||
else:
|
||||
Global.play_backwards.pressed = false
|
||||
return
|
||||
|
||||
first_frame = 0
|
||||
last_frame = Global.canvases.size() - 1
|
||||
if Global.play_only_tags:
|
||||
for tag in Global.animation_tags:
|
||||
if Global.current_frame + 1 >= tag[2] && Global.current_frame + 1 <= tag[3]:
|
||||
first_frame = tag[2] - 1
|
||||
last_frame = min(Global.canvases.size() - 1, tag[3] - 1)
|
||||
|
||||
if play:
|
||||
Global.animation_timer.wait_time = 1 / fps
|
||||
Global.animation_timer.start()
|
||||
animation_forward = forward_dir
|
||||
else:
|
||||
Global.animation_timer.stop()
|
||||
|
||||
|
||||
func _on_NextFrame_pressed() -> void:
|
||||
if Global.current_frame < Global.canvases.size() - 1:
|
||||
Global.current_frame += 1
|
||||
|
||||
|
||||
func _on_PreviousFrame_pressed() -> void:
|
||||
if Global.current_frame > 0:
|
||||
Global.current_frame -= 1
|
||||
|
||||
|
||||
func _on_LastFrame_pressed() -> void:
|
||||
Global.current_frame = Global.canvases.size() - 1
|
||||
|
||||
|
||||
func _on_FirstFrame_pressed() -> void:
|
||||
Global.current_frame = 0
|
||||
|
||||
|
||||
func _on_FPSValue_value_changed(value : float) -> void:
|
||||
fps = float(value)
|
||||
Global.animation_timer.wait_time = 1 / fps
|
||||
|
||||
|
||||
func _on_PastOnionSkinning_value_changed(value : float) -> void:
|
||||
Global.onion_skinning_past_rate = int(value)
|
||||
Global.canvas.update()
|
||||
|
||||
|
||||
func _on_FutureOnionSkinning_value_changed(value : float) -> void:
|
||||
Global.onion_skinning_future_rate = int(value)
|
||||
Global.canvas.update()
|
||||
|
||||
|
||||
func _on_BlueRedMode_toggled(button_pressed : bool) -> void:
|
||||
Global.onion_skinning_blue_red = button_pressed
|
||||
Global.canvas.update()
|
||||
|
||||
|
||||
# Layer buttons
|
||||
|
||||
func add_layer(is_new := true) -> void:
|
||||
var layer_name = null
|
||||
if !is_new: # Clone layer
|
||||
layer_name = Global.layers[Global.current_layer][0] + " (" + tr("copy") + ")"
|
||||
|
||||
var new_layers : Array = Global.layers.duplicate()
|
||||
|
||||
# Store [Layer name (0), Layer visibility boolean (1), Layer lock boolean (2), Frame container (3),
|
||||
# will new frames be linked boolean (4), Array of linked frames (5)]
|
||||
new_layers.append([layer_name, true, false, HBoxContainer.new(), false, []])
|
||||
|
||||
Global.undos += 1
|
||||
Global.undo_redo.create_action("Add Layer")
|
||||
|
||||
for c in Global.canvases:
|
||||
var new_layer := Image.new()
|
||||
if is_new:
|
||||
new_layer.create(c.size.x, c.size.y, false, Image.FORMAT_RGBA8)
|
||||
else: # Clone layer
|
||||
new_layer.copy_from(c.layers[Global.current_layer][0])
|
||||
|
||||
new_layer.lock()
|
||||
var new_layer_tex := ImageTexture.new()
|
||||
new_layer_tex.create_from_image(new_layer, 0)
|
||||
|
||||
var new_canvas_layers : Array = c.layers.duplicate()
|
||||
# Store [Image, ImageTexture, Opacity]
|
||||
new_canvas_layers.append([new_layer, new_layer_tex, 1])
|
||||
Global.undo_redo.add_do_property(c, "layers", new_canvas_layers)
|
||||
Global.undo_redo.add_undo_property(c, "layers", c.layers)
|
||||
|
||||
Global.undo_redo.add_do_property(Global, "current_layer", Global.current_layer + 1)
|
||||
Global.undo_redo.add_do_property(Global, "layers", new_layers)
|
||||
Global.undo_redo.add_undo_property(Global, "current_layer", Global.current_layer)
|
||||
Global.undo_redo.add_undo_property(Global, "layers", Global.layers)
|
||||
|
||||
Global.undo_redo.add_undo_method(Global, "undo", [Global.canvas])
|
||||
Global.undo_redo.add_do_method(Global, "redo", [Global.canvas])
|
||||
Global.undo_redo.commit_action()
|
||||
|
||||
|
||||
func _on_RemoveLayer_pressed() -> void:
|
||||
var new_layers : Array = Global.layers.duplicate()
|
||||
new_layers.remove(Global.current_layer)
|
||||
Global.undos += 1
|
||||
Global.undo_redo.create_action("Remove Layer")
|
||||
if Global.current_layer > 0:
|
||||
Global.undo_redo.add_do_property(Global, "current_layer", Global.current_layer - 1)
|
||||
else:
|
||||
Global.undo_redo.add_do_property(Global, "current_layer", Global.current_layer)
|
||||
|
||||
for c in Global.canvases:
|
||||
var new_canvas_layers : Array = c.layers.duplicate()
|
||||
new_canvas_layers.remove(Global.current_layer)
|
||||
Global.undo_redo.add_do_property(c, "layers", new_canvas_layers)
|
||||
Global.undo_redo.add_undo_property(c, "layers", c.layers)
|
||||
|
||||
Global.undo_redo.add_do_property(Global, "layers", new_layers)
|
||||
Global.undo_redo.add_undo_property(Global, "current_layer", Global.current_layer)
|
||||
Global.undo_redo.add_undo_property(Global, "layers", Global.layers)
|
||||
Global.undo_redo.add_do_method(Global, "redo", [Global.canvas])
|
||||
Global.undo_redo.add_undo_method(Global, "undo", [Global.canvas])
|
||||
Global.undo_redo.commit_action()
|
||||
|
||||
|
||||
func change_layer_order(rate : int) -> void:
|
||||
var change = Global.current_layer + rate
|
||||
|
||||
var new_layers : Array = Global.layers.duplicate()
|
||||
var temp = new_layers[Global.current_layer]
|
||||
new_layers[Global.current_layer] = new_layers[change]
|
||||
new_layers[change] = temp
|
||||
Global.undo_redo.create_action("Change Layer Order")
|
||||
for c in Global.canvases:
|
||||
var new_layers_canvas : Array = c.layers.duplicate()
|
||||
var temp_canvas = new_layers_canvas[Global.current_layer]
|
||||
new_layers_canvas[Global.current_layer] = new_layers_canvas[change]
|
||||
new_layers_canvas[change] = temp_canvas
|
||||
Global.undo_redo.add_do_property(c, "layers", new_layers_canvas)
|
||||
Global.undo_redo.add_undo_property(c, "layers", c.layers)
|
||||
|
||||
Global.undo_redo.add_do_property(Global, "current_layer", change)
|
||||
Global.undo_redo.add_do_property(Global, "layers", new_layers)
|
||||
Global.undo_redo.add_undo_property(Global, "layers", Global.layers)
|
||||
Global.undo_redo.add_undo_property(Global, "current_layer", Global.current_layer)
|
||||
|
||||
Global.undo_redo.add_undo_method(Global, "undo", [Global.canvas])
|
||||
Global.undo_redo.add_do_method(Global, "redo", [Global.canvas])
|
||||
Global.undo_redo.commit_action()
|
||||
|
||||
|
||||
func _on_MergeDownLayer_pressed() -> void:
|
||||
var new_layers : Array = Global.layers.duplicate(true)
|
||||
|
||||
Global.undos += 1
|
||||
Global.undo_redo.create_action("Merge Layer")
|
||||
for c in Global.canvases:
|
||||
var new_layers_canvas : Array = c.layers.duplicate(true)
|
||||
var selected_layer := Image.new()
|
||||
selected_layer.copy_from(new_layers_canvas[Global.current_layer][0])
|
||||
selected_layer.lock()
|
||||
|
||||
if c.layers[Global.current_layer][2] < 1: # If we have layer transparency
|
||||
for xx in selected_layer.get_size().x:
|
||||
for yy in selected_layer.get_size().y:
|
||||
var pixel_color : Color = selected_layer.get_pixel(xx, yy)
|
||||
var alpha : float = pixel_color.a * c.layers[Global.current_layer][2]
|
||||
selected_layer.set_pixel(xx, yy, Color(pixel_color.r, pixel_color.g, pixel_color.b, alpha))
|
||||
|
||||
var new_layer := Image.new()
|
||||
new_layer.copy_from(c.layers[Global.current_layer - 1][0])
|
||||
new_layer.lock()
|
||||
c.blend_rect(new_layer, selected_layer, Rect2(c.position, c.size), Vector2.ZERO)
|
||||
new_layers_canvas.remove(Global.current_layer)
|
||||
if !selected_layer.is_invisible() and Global.layers[Global.current_layer - 1][5].size() > 1 and (c in Global.layers[Global.current_layer - 1][5]):
|
||||
new_layers[Global.current_layer - 1][5].erase(c)
|
||||
var tex := ImageTexture.new()
|
||||
tex.create_from_image(new_layer, 0)
|
||||
new_layers_canvas[Global.current_layer - 1][0] = new_layer
|
||||
new_layers_canvas[Global.current_layer - 1][1] = tex
|
||||
else:
|
||||
Global.undo_redo.add_do_property(c.layers[Global.current_layer - 1][0], "data", new_layer.data)
|
||||
Global.undo_redo.add_undo_property(c.layers[Global.current_layer - 1][0], "data", c.layers[Global.current_layer - 1][0].data)
|
||||
|
||||
Global.undo_redo.add_do_property(c, "layers", new_layers_canvas)
|
||||
Global.undo_redo.add_undo_property(c, "layers", c.layers)
|
||||
|
||||
new_layers.remove(Global.current_layer)
|
||||
Global.undo_redo.add_do_property(Global, "current_layer", Global.current_layer - 1)
|
||||
Global.undo_redo.add_do_property(Global, "layers", new_layers)
|
||||
Global.undo_redo.add_undo_property(Global, "layers", Global.layers)
|
||||
Global.undo_redo.add_undo_property(Global, "current_layer", Global.current_layer)
|
||||
|
||||
Global.undo_redo.add_undo_method(Global, "undo", Global.canvases)
|
||||
Global.undo_redo.add_do_method(Global, "redo", Global.canvases)
|
||||
Global.undo_redo.commit_action()
|
||||
|
||||
|
||||
func _on_OpacitySlider_value_changed(value) -> void:
|
||||
Global.canvas.layers[Global.current_layer][2] = value / 100
|
||||
Global.layer_opacity_slider.value = value
|
||||
Global.layer_opacity_slider.value = value
|
||||
Global.layer_opacity_spinbox.value = value
|
||||
Global.canvas.update()
|
||||
|
||||
|
||||
func _on_OnionSkinningSettings_popup_hide() -> void:
|
||||
Global.can_draw = true
|
838
src/UI/Timeline/AnimationTimeline.tscn
Normal file
838
src/UI/Timeline/AnimationTimeline.tscn
Normal file
|
@ -0,0 +1,838 @@
|
|||
[gd_scene load_steps=51 format=2]
|
||||
|
||||
[ext_resource path="res://src/UI/Timeline/AnimationTimeline.gd" type="Script" id=1]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/New_Layer.png" type="Texture" id=2]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/New_Layer_Hover.png" type="Texture" id=3]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Delete_Layer.png" type="Texture" id=4]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Delete_Layer_Hover.png" type="Texture" id=5]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Delete_Layer_Disabled.png" type="Texture" id=6]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Move_Up.png" type="Texture" id=7]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Move_Up_Hover.png" type="Texture" id=8]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Move_Up_Disabled.png" type="Texture" id=9]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Move_Down.png" type="Texture" id=10]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Move_Down_Hover.png" type="Texture" id=11]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Move_Down_Disabled.png" type="Texture" id=12]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Clone_Layer.png" type="Texture" id=13]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Clone_Layer_Hover.png" type="Texture" id=14]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Merge_Down.png" type="Texture" id=15]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Merge_Down_Hover.png" type="Texture" id=16]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Merge_Down_Disabled.png" type="Texture" id=17]
|
||||
[ext_resource path="res://src/UI/Timeline/LayerButton.tscn" type="PackedScene" id=18]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/new_frame.png" type="Texture" id=19]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/remove_frame.png" type="Texture" id=20]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/go_to_first_frame.png" type="Texture" id=21]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/play.png" type="Texture" id=22]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/previous_frame.png" type="Texture" id=23]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/play_backwards.png" type="Texture" id=24]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/go_to_last_frame.png" type="Texture" id=25]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/next_frame.png" type="Texture" id=26]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/copy_frame.png" type="Texture" id=27]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/tag.png" type="Texture" id=28]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/onion_skinning_off.png" type="Texture" id=29]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/expandable.png" type="Texture" id=30]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/loop.png" type="Texture" id=31]
|
||||
[ext_resource path="res://src/UI/Dialogs/FrameTagDialog.tscn" type="PackedScene" id=42]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[sub_resource type="InputEventKey" id=1]
|
||||
control = true
|
||||
command = true
|
||||
scancode = 16777229
|
||||
|
||||
[sub_resource type="ShortCut" id=2]
|
||||
shortcut = SubResource( 1 )
|
||||
|
||||
[sub_resource type="InputEventKey" id=3]
|
||||
control = true
|
||||
command = true
|
||||
scancode = 16777231
|
||||
|
||||
[sub_resource type="ShortCut" id=4]
|
||||
shortcut = SubResource( 3 )
|
||||
|
||||
[sub_resource type="InputEventKey" id=5]
|
||||
scancode = 16777247
|
||||
|
||||
[sub_resource type="ShortCut" id=6]
|
||||
shortcut = SubResource( 5 )
|
||||
|
||||
[sub_resource type="InputEventKey" id=7]
|
||||
scancode = 16777248
|
||||
|
||||
[sub_resource type="ShortCut" id=8]
|
||||
shortcut = SubResource( 7 )
|
||||
|
||||
[sub_resource type="InputEventKey" id=9]
|
||||
control = true
|
||||
command = true
|
||||
scancode = 16777233
|
||||
|
||||
[sub_resource type="ShortCut" id=10]
|
||||
shortcut = SubResource( 9 )
|
||||
|
||||
[sub_resource type="InputEventKey" id=11]
|
||||
control = true
|
||||
command = true
|
||||
scancode = 16777230
|
||||
|
||||
[sub_resource type="ShortCut" id=12]
|
||||
shortcut = SubResource( 11 )
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id=13]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id=14]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id=15]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id=16]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id=17]
|
||||
|
||||
[sub_resource type="Theme" id=18]
|
||||
HScrollBar/icons/decrement = null
|
||||
HScrollBar/icons/decrement_highlight = null
|
||||
HScrollBar/icons/increment = null
|
||||
HScrollBar/icons/increment_highlight = null
|
||||
HScrollBar/styles/grabber = SubResource( 13 )
|
||||
HScrollBar/styles/grabber_highlight = SubResource( 14 )
|
||||
HScrollBar/styles/grabber_pressed = SubResource( 15 )
|
||||
HScrollBar/styles/scroll = SubResource( 16 )
|
||||
HScrollBar/styles/scroll_focus = SubResource( 17 )
|
||||
|
||||
[node name="AnimationTimeline" type="Panel"]
|
||||
margin_top = 438.0
|
||||
margin_right = 704.0
|
||||
margin_bottom = 620.0
|
||||
rect_min_size = Vector2( 0, 200 )
|
||||
size_flags_horizontal = 3
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="AnimationContainer" type="HBoxContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="ForLayerButtons" type="VBoxContainer" parent="AnimationContainer"]
|
||||
margin_right = 68.0
|
||||
margin_bottom = 200.0
|
||||
|
||||
[node name="SpacerControl" type="Control" parent="AnimationContainer/ForLayerButtons"]
|
||||
margin_right = 68.0
|
||||
margin_bottom = 30.0
|
||||
rect_min_size = Vector2( 0, 30 )
|
||||
|
||||
[node name="LayerButtons" type="GridContainer" parent="AnimationContainer/ForLayerButtons"]
|
||||
margin_top = 34.0
|
||||
margin_right = 68.0
|
||||
margin_bottom = 138.0
|
||||
size_flags_vertical = 0
|
||||
custom_constants/vseparation = 4
|
||||
custom_constants/hseparation = 4
|
||||
columns = 2
|
||||
|
||||
[node name="AddLayer" type="TextureButton" parent="AnimationContainer/ForLayerButtons/LayerButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_right = 32.0
|
||||
margin_bottom = 32.0
|
||||
hint_tooltip = "Create a new layer"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 2
|
||||
texture_normal = ExtResource( 2 )
|
||||
texture_hover = ExtResource( 3 )
|
||||
|
||||
[node name="RemoveLayer" type="TextureButton" parent="AnimationContainer/ForLayerButtons/LayerButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_left = 36.0
|
||||
margin_right = 68.0
|
||||
margin_bottom = 32.0
|
||||
hint_tooltip = "Remove current layer"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 8
|
||||
disabled = true
|
||||
texture_normal = ExtResource( 4 )
|
||||
texture_hover = ExtResource( 5 )
|
||||
texture_disabled = ExtResource( 6 )
|
||||
|
||||
[node name="MoveUpLayer" type="TextureButton" parent="AnimationContainer/ForLayerButtons/LayerButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_top = 36.0
|
||||
margin_right = 32.0
|
||||
margin_bottom = 68.0
|
||||
hint_tooltip = "Move up the current layer"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 8
|
||||
disabled = true
|
||||
texture_normal = ExtResource( 7 )
|
||||
texture_hover = ExtResource( 8 )
|
||||
texture_disabled = ExtResource( 9 )
|
||||
|
||||
[node name="MoveDownLayer" type="TextureButton" parent="AnimationContainer/ForLayerButtons/LayerButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_left = 36.0
|
||||
margin_top = 36.0
|
||||
margin_right = 68.0
|
||||
margin_bottom = 68.0
|
||||
hint_tooltip = "Move down the current layer"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 8
|
||||
disabled = true
|
||||
texture_normal = ExtResource( 10 )
|
||||
texture_hover = ExtResource( 11 )
|
||||
texture_disabled = ExtResource( 12 )
|
||||
|
||||
[node name="CloneLayer" type="TextureButton" parent="AnimationContainer/ForLayerButtons/LayerButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_top = 72.0
|
||||
margin_right = 32.0
|
||||
margin_bottom = 104.0
|
||||
hint_tooltip = "Clone current layer"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 2
|
||||
texture_normal = ExtResource( 13 )
|
||||
texture_hover = ExtResource( 14 )
|
||||
|
||||
[node name="MergeDownLayer" type="TextureButton" parent="AnimationContainer/ForLayerButtons/LayerButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_left = 36.0
|
||||
margin_top = 72.0
|
||||
margin_right = 68.0
|
||||
margin_bottom = 104.0
|
||||
hint_tooltip = "Merge current layer with the one below"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 8
|
||||
disabled = true
|
||||
texture_normal = ExtResource( 15 )
|
||||
texture_hover = ExtResource( 16 )
|
||||
texture_disabled = ExtResource( 17 )
|
||||
|
||||
[node name="SpacerControl" type="Control" parent="AnimationContainer"]
|
||||
margin_left = 72.0
|
||||
margin_right = 88.0
|
||||
margin_bottom = 200.0
|
||||
rect_min_size = Vector2( 16, 0 )
|
||||
|
||||
[node name="TimelineContainer" type="VBoxContainer" parent="AnimationContainer"]
|
||||
margin_left = 92.0
|
||||
margin_right = 696.0
|
||||
margin_bottom = 200.0
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="SpacerControl" type="Control" parent="AnimationContainer/TimelineContainer"]
|
||||
margin_right = 604.0
|
||||
|
||||
[node name="AnimationButtons" type="HBoxContainer" parent="AnimationContainer/TimelineContainer"]
|
||||
margin_top = 4.0
|
||||
margin_right = 604.0
|
||||
margin_bottom = 28.0
|
||||
rect_min_size = Vector2( 0, 24 )
|
||||
|
||||
[node name="CurrentFrame" type="Label" parent="AnimationContainer/TimelineContainer/AnimationButtons"]
|
||||
margin_top = 5.0
|
||||
margin_right = 150.0
|
||||
margin_bottom = 19.0
|
||||
rect_min_size = Vector2( 150, 0 )
|
||||
text = "Current frame: 1/1"
|
||||
|
||||
[node name="AddFrame" type="Button" parent="AnimationContainer/TimelineContainer/AnimationButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_left = 154.0
|
||||
margin_right = 174.0
|
||||
margin_bottom = 20.0
|
||||
rect_min_size = Vector2( 20, 0 )
|
||||
hint_tooltip = "Add a new frame"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 0
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/AnimationButtons/AddFrame"]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = -6.0
|
||||
margin_top = -6.0
|
||||
margin_right = 6.0
|
||||
margin_bottom = 6.0
|
||||
texture = ExtResource( 19 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="DeleteFrame" type="Button" parent="AnimationContainer/TimelineContainer/AnimationButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_left = 178.0
|
||||
margin_right = 198.0
|
||||
margin_bottom = 20.0
|
||||
rect_min_size = Vector2( 20, 0 )
|
||||
hint_tooltip = "Remove Frame"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 0
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/AnimationButtons/DeleteFrame"]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = -6.0
|
||||
margin_top = -1.0
|
||||
margin_right = 6.0
|
||||
margin_bottom = 1.0
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 0
|
||||
texture = ExtResource( 20 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="CopyFrame" type="Button" parent="AnimationContainer/TimelineContainer/AnimationButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_left = 202.0
|
||||
margin_right = 222.0
|
||||
margin_bottom = 20.0
|
||||
rect_min_size = Vector2( 20, 0 )
|
||||
hint_tooltip = "Clone Frame"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 0
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/AnimationButtons/CopyFrame"]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = -5.0
|
||||
margin_top = -7.0
|
||||
margin_right = 5.0
|
||||
margin_bottom = 7.0
|
||||
texture = ExtResource( 27 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="FrameTagButton" type="Button" parent="AnimationContainer/TimelineContainer/AnimationButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_left = 226.0
|
||||
margin_right = 246.0
|
||||
margin_bottom = 20.0
|
||||
rect_min_size = Vector2( 20, 0 )
|
||||
hint_tooltip = "Manage frame tags"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 0
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/AnimationButtons/FrameTagButton"]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = -7.0
|
||||
margin_top = -7.0
|
||||
margin_right = 7.0
|
||||
margin_bottom = 7.0
|
||||
texture = ExtResource( 28 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="PlaybackButtons" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/AnimationButtons"]
|
||||
margin_left = 286.0
|
||||
margin_right = 426.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_horizontal = 6
|
||||
|
||||
[node name="FirstFrame" type="Button" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_right = 20.0
|
||||
margin_bottom = 20.0
|
||||
rect_min_size = Vector2( 20, 0 )
|
||||
hint_tooltip = "FIRSTFRAME_HT"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_vertical = 0
|
||||
shortcut_in_tooltip = false
|
||||
shortcut = SubResource( 2 )
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons/FirstFrame"]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = -5.5
|
||||
margin_top = -6.0
|
||||
margin_right = 5.5
|
||||
margin_bottom = 6.0
|
||||
texture = ExtResource( 21 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="PreviousFrame" type="Button" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_left = 24.0
|
||||
margin_right = 44.0
|
||||
margin_bottom = 20.0
|
||||
rect_min_size = Vector2( 20, 0 )
|
||||
hint_tooltip = "PREVIOUSFRAME_HT"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_vertical = 0
|
||||
shortcut_in_tooltip = false
|
||||
shortcut = SubResource( 4 )
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons/PreviousFrame"]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = -5.5
|
||||
margin_top = -6.0
|
||||
margin_right = 5.5
|
||||
margin_bottom = 6.0
|
||||
texture = ExtResource( 23 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="PlayBackwards" type="Button" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_left = 48.0
|
||||
margin_right = 68.0
|
||||
margin_bottom = 20.0
|
||||
rect_min_size = Vector2( 20, 0 )
|
||||
hint_tooltip = "PLAYBACKWARDS_HT"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_vertical = 0
|
||||
toggle_mode = true
|
||||
shortcut_in_tooltip = false
|
||||
shortcut = SubResource( 6 )
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons/PlayBackwards"]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = -4.0
|
||||
margin_top = -6.0
|
||||
margin_right = 3.0
|
||||
margin_bottom = 6.0
|
||||
texture = ExtResource( 24 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="PlayForward" type="Button" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_left = 72.0
|
||||
margin_right = 92.0
|
||||
margin_bottom = 20.0
|
||||
rect_min_size = Vector2( 20, 0 )
|
||||
hint_tooltip = "PLAYFORWARD_HT"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 0
|
||||
toggle_mode = true
|
||||
shortcut_in_tooltip = false
|
||||
shortcut = SubResource( 8 )
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons/PlayForward"]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = -3.5
|
||||
margin_top = -6.0
|
||||
margin_right = 3.5
|
||||
margin_bottom = 6.0
|
||||
texture = ExtResource( 22 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="NextFrame" type="Button" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_left = 96.0
|
||||
margin_right = 116.0
|
||||
margin_bottom = 20.0
|
||||
rect_min_size = Vector2( 20, 0 )
|
||||
hint_tooltip = "NEXTFRAME_HT"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_vertical = 0
|
||||
shortcut_in_tooltip = false
|
||||
shortcut = SubResource( 10 )
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons/NextFrame"]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = -5.5
|
||||
margin_top = -6.0
|
||||
margin_right = 5.5
|
||||
margin_bottom = 6.0
|
||||
texture = ExtResource( 26 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="LastFrame" type="Button" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_left = 120.0
|
||||
margin_right = 140.0
|
||||
margin_bottom = 20.0
|
||||
rect_min_size = Vector2( 20, 0 )
|
||||
hint_tooltip = "LASTFRAME_HT"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_vertical = 0
|
||||
shortcut_in_tooltip = false
|
||||
shortcut = SubResource( 12 )
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons/LastFrame"]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = -5.5
|
||||
margin_top = -6.0
|
||||
margin_right = 5.5
|
||||
margin_bottom = 6.0
|
||||
texture = ExtResource( 25 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="LoopButtons" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/AnimationButtons"]
|
||||
margin_left = 466.0
|
||||
margin_right = 604.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_horizontal = 0
|
||||
|
||||
[node name="OnionSkinningSettings" type="Button" parent="AnimationContainer/TimelineContainer/AnimationButtons/LoopButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_right = 12.0
|
||||
margin_bottom = 20.0
|
||||
hint_tooltip = "Onion Skinning settings"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 0
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/AnimationButtons/LoopButtons/OnionSkinningSettings"]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = -3.0
|
||||
margin_top = -6.0
|
||||
margin_right = 3.0
|
||||
margin_bottom = 6.0
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 0
|
||||
texture = ExtResource( 30 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="OnionSkinning" type="Button" parent="AnimationContainer/TimelineContainer/AnimationButtons/LoopButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_left = 16.0
|
||||
margin_right = 36.0
|
||||
margin_bottom = 20.0
|
||||
rect_min_size = Vector2( 20, 0 )
|
||||
hint_tooltip = "Enable/disable Onion Skinning"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_vertical = 0
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/AnimationButtons/LoopButtons/OnionSkinning"]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = -7.0
|
||||
margin_top = -7.0
|
||||
margin_right = 7.0
|
||||
margin_bottom = 7.0
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 0
|
||||
texture = ExtResource( 29 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="LoopAnim" type="Button" parent="AnimationContainer/TimelineContainer/AnimationButtons/LoopButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_left = 40.0
|
||||
margin_right = 60.0
|
||||
margin_bottom = 20.0
|
||||
rect_min_size = Vector2( 20, 0 )
|
||||
hint_tooltip = "Cycle loop"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_vertical = 0
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/AnimationButtons/LoopButtons/LoopAnim"]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = -7.0
|
||||
margin_top = -7.0
|
||||
margin_right = 7.0
|
||||
margin_bottom = 7.0
|
||||
texture = ExtResource( 31 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="FPSValue" type="SpinBox" parent="AnimationContainer/TimelineContainer/AnimationButtons/LoopButtons"]
|
||||
margin_left = 64.0
|
||||
margin_right = 138.0
|
||||
margin_bottom = 24.0
|
||||
hint_tooltip = "How many frames per second should the animation preview be?
|
||||
The more FPS, the faster the animation plays."
|
||||
mouse_default_cursor_shape = 2
|
||||
min_value = 0.1
|
||||
step = 0.1
|
||||
value = 6.0
|
||||
align = 1
|
||||
suffix = "FPS"
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="AnimationContainer/TimelineContainer"]
|
||||
margin_top = 32.0
|
||||
margin_right = 604.0
|
||||
margin_bottom = 36.0
|
||||
|
||||
[node name="OpacityAndTagContainer" type="HBoxContainer" parent="AnimationContainer/TimelineContainer"]
|
||||
margin_top = 40.0
|
||||
margin_right = 604.0
|
||||
margin_bottom = 72.0
|
||||
custom_constants/separation = 2
|
||||
|
||||
[node name="OpacityContainer" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/OpacityAndTagContainer"]
|
||||
margin_right = 214.0
|
||||
margin_bottom = 32.0
|
||||
rect_min_size = Vector2( 214, 0 )
|
||||
|
||||
[node name="OpacityLabel" type="Label" parent="AnimationContainer/TimelineContainer/OpacityAndTagContainer/OpacityContainer"]
|
||||
margin_right = 53.0
|
||||
margin_bottom = 32.0
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 1
|
||||
text = "Opacity:"
|
||||
valign = 1
|
||||
|
||||
[node name="OpacitySlider" type="HSlider" parent="AnimationContainer/TimelineContainer/OpacityAndTagContainer/OpacityContainer"]
|
||||
margin_left = 57.0
|
||||
margin_right = 136.0
|
||||
margin_bottom = 32.0
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 1
|
||||
value = 100.0
|
||||
ticks_on_borders = true
|
||||
|
||||
[node name="OpacitySpinBox" type="SpinBox" parent="AnimationContainer/TimelineContainer/OpacityAndTagContainer/OpacityContainer"]
|
||||
margin_left = 140.0
|
||||
margin_top = 4.0
|
||||
margin_right = 214.0
|
||||
margin_bottom = 28.0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_vertical = 4
|
||||
value = 100.0
|
||||
align = 1
|
||||
|
||||
[node name="TagScroll" type="ScrollContainer" parent="AnimationContainer/TimelineContainer/OpacityAndTagContainer"]
|
||||
margin_left = 216.0
|
||||
margin_right = 604.0
|
||||
margin_bottom = 32.0
|
||||
rect_min_size = Vector2( 0, 32 )
|
||||
size_flags_horizontal = 3
|
||||
theme = SubResource( 18 )
|
||||
scroll_vertical_enabled = false
|
||||
|
||||
[node name="TagContainer" type="Control" parent="AnimationContainer/TimelineContainer/OpacityAndTagContainer/TagScroll"]
|
||||
|
||||
[node name="TimelineScroll" type="ScrollContainer" parent="AnimationContainer/TimelineContainer"]
|
||||
margin_top = 76.0
|
||||
margin_right = 604.0
|
||||
margin_bottom = 200.0
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="LayersAndFrames" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll"]
|
||||
margin_right = 252.0
|
||||
margin_bottom = 124.0
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="LayerVBoxCont" type="VBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames"]
|
||||
margin_right = 212.0
|
||||
margin_bottom = 124.0
|
||||
|
||||
[node name="LayerLabel" type="Label" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames/LayerVBoxCont"]
|
||||
margin_right = 212.0
|
||||
margin_bottom = 16.0
|
||||
rect_min_size = Vector2( 0, 16 )
|
||||
text = "Layers"
|
||||
align = 1
|
||||
valign = 1
|
||||
|
||||
[node name="LayersContainer" type="VBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames/LayerVBoxCont"]
|
||||
margin_top = 20.0
|
||||
margin_right = 212.0
|
||||
margin_bottom = 56.0
|
||||
|
||||
[node name="LayerContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames/LayerVBoxCont/LayersContainer" instance=ExtResource( 18 )]
|
||||
margin_right = 212.0
|
||||
|
||||
[node name="FrameButtonsAndIds" type="VBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames"]
|
||||
margin_left = 216.0
|
||||
margin_right = 252.0
|
||||
margin_bottom = 124.0
|
||||
|
||||
[node name="FrameIDs" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames/FrameButtonsAndIds"]
|
||||
margin_right = 36.0
|
||||
margin_bottom = 16.0
|
||||
rect_min_size = Vector2( 0, 16 )
|
||||
|
||||
[node name="Label" type="Label" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames/FrameButtonsAndIds/FrameIDs"]
|
||||
margin_top = 1.0
|
||||
margin_right = 36.0
|
||||
margin_bottom = 15.0
|
||||
rect_min_size = Vector2( 36, 0 )
|
||||
text = "1"
|
||||
align = 1
|
||||
|
||||
[node name="FramesContainer" type="VBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames/FrameButtonsAndIds"]
|
||||
margin_top = 20.0
|
||||
margin_right = 36.0
|
||||
margin_bottom = 20.0
|
||||
|
||||
[node name="VSeparator" type="VSeparator" parent="AnimationContainer"]
|
||||
margin_left = 700.0
|
||||
margin_right = 704.0
|
||||
margin_bottom = 200.0
|
||||
|
||||
[node name="AnimationTimer" type="Timer" parent="."]
|
||||
|
||||
[node name="OnionSkinningSettings" type="WindowDialog" parent="."]
|
||||
rect_min_size = Vector2( 220, 126 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="OnionSkinningButtons" type="VBoxContainer" parent="OnionSkinningSettings"]
|
||||
anchor_top = 0.5
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 0.5
|
||||
margin_left = 4.0
|
||||
margin_top = -58.0
|
||||
margin_right = -4.0
|
||||
margin_bottom = 58.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="OnionSkinningPast" type="Label" parent="OnionSkinningSettings/OnionSkinningButtons"]
|
||||
margin_right = 212.0
|
||||
margin_bottom = 14.0
|
||||
text = "Past Frames"
|
||||
|
||||
[node name="PastOnionSkinning" type="SpinBox" parent="OnionSkinningSettings/OnionSkinningButtons"]
|
||||
margin_top = 18.0
|
||||
margin_right = 212.0
|
||||
margin_bottom = 42.0
|
||||
mouse_default_cursor_shape = 2
|
||||
min_value = 1.0
|
||||
value = 1.0
|
||||
align = 1
|
||||
|
||||
[node name="OnionSkinningFuture" type="Label" parent="OnionSkinningSettings/OnionSkinningButtons"]
|
||||
margin_top = 46.0
|
||||
margin_right = 212.0
|
||||
margin_bottom = 60.0
|
||||
text = "Future Frames"
|
||||
|
||||
[node name="FutureOnionSkinning" type="SpinBox" parent="OnionSkinningSettings/OnionSkinningButtons"]
|
||||
margin_top = 64.0
|
||||
margin_right = 212.0
|
||||
margin_bottom = 88.0
|
||||
mouse_default_cursor_shape = 2
|
||||
min_value = 1.0
|
||||
value = 1.0
|
||||
align = 1
|
||||
|
||||
[node name="BlueRedMode" type="CheckBox" parent="OnionSkinningSettings/OnionSkinningButtons"]
|
||||
margin_top = 92.0
|
||||
margin_right = 212.0
|
||||
margin_bottom = 116.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Blue-Red Mode"
|
||||
|
||||
[node name="FrameTagDialog" parent="." instance=ExtResource( 42 )]
|
||||
[connection signal="pressed" from="AnimationContainer/ForLayerButtons/LayerButtons/AddLayer" to="." method="add_layer" binds= [ true ]]
|
||||
[connection signal="pressed" from="AnimationContainer/ForLayerButtons/LayerButtons/RemoveLayer" to="." method="_on_RemoveLayer_pressed"]
|
||||
[connection signal="pressed" from="AnimationContainer/ForLayerButtons/LayerButtons/MoveUpLayer" to="." method="change_layer_order" binds= [ 1 ]]
|
||||
[connection signal="pressed" from="AnimationContainer/ForLayerButtons/LayerButtons/MoveDownLayer" to="." method="change_layer_order" binds= [ -1 ]]
|
||||
[connection signal="pressed" from="AnimationContainer/ForLayerButtons/LayerButtons/CloneLayer" to="." method="add_layer" binds= [ false ]]
|
||||
[connection signal="pressed" from="AnimationContainer/ForLayerButtons/LayerButtons/MergeDownLayer" to="." method="_on_MergeDownLayer_pressed"]
|
||||
[connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/AddFrame" to="." method="add_frame"]
|
||||
[connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/DeleteFrame" to="." method="_on_DeleteFrame_pressed"]
|
||||
[connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/CopyFrame" to="." method="_on_CopyFrame_pressed"]
|
||||
[connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/FrameTagButton" to="." method="_on_FrameTagButton_pressed"]
|
||||
[connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons/FirstFrame" to="." method="_on_FirstFrame_pressed"]
|
||||
[connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons/PreviousFrame" to="." method="_on_PreviousFrame_pressed"]
|
||||
[connection signal="toggled" from="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons/PlayBackwards" to="." method="_on_PlayBackwards_toggled"]
|
||||
[connection signal="toggled" from="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons/PlayForward" to="." method="_on_PlayForward_toggled"]
|
||||
[connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons/NextFrame" to="." method="_on_NextFrame_pressed"]
|
||||
[connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons/LastFrame" to="." method="_on_LastFrame_pressed"]
|
||||
[connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/LoopButtons/OnionSkinningSettings" to="." method="_on_OnionSkinningSettings_pressed"]
|
||||
[connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/LoopButtons/OnionSkinning" to="." method="_on_OnionSkinning_pressed"]
|
||||
[connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/LoopButtons/LoopAnim" to="." method="_on_LoopAnim_pressed"]
|
||||
[connection signal="value_changed" from="AnimationContainer/TimelineContainer/AnimationButtons/LoopButtons/FPSValue" to="." method="_on_FPSValue_value_changed"]
|
||||
[connection signal="value_changed" from="AnimationContainer/TimelineContainer/OpacityAndTagContainer/OpacityContainer/OpacitySlider" to="." method="_on_OpacitySlider_value_changed"]
|
||||
[connection signal="value_changed" from="AnimationContainer/TimelineContainer/OpacityAndTagContainer/OpacityContainer/OpacitySpinBox" to="." method="_on_OpacitySlider_value_changed"]
|
||||
[connection signal="timeout" from="AnimationTimer" to="." method="_on_AnimationTimer_timeout"]
|
||||
[connection signal="popup_hide" from="OnionSkinningSettings" to="." method="_on_OnionSkinningSettings_popup_hide"]
|
||||
[connection signal="value_changed" from="OnionSkinningSettings/OnionSkinningButtons/PastOnionSkinning" to="." method="_on_PastOnionSkinning_value_changed"]
|
||||
[connection signal="value_changed" from="OnionSkinningSettings/OnionSkinningButtons/FutureOnionSkinning" to="." method="_on_FutureOnionSkinning_value_changed"]
|
||||
[connection signal="toggled" from="OnionSkinningSettings/OnionSkinningButtons/BlueRedMode" to="." method="_on_BlueRedMode_toggled"]
|
121
src/UI/Timeline/CelButton.gd
Normal file
121
src/UI/Timeline/CelButton.gd
Normal file
|
@ -0,0 +1,121 @@
|
|||
extends Button
|
||||
|
||||
var frame := 0
|
||||
var layer := 0
|
||||
|
||||
onready var popup_menu : PopupMenu = $PopupMenu
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
hint_tooltip = "Frame: %s, Layer: %s" % [frame + 1, layer]
|
||||
if Global.canvases[frame] in Global.layers[layer][5]:
|
||||
get_node("LinkedIndicator").visible = true
|
||||
popup_menu.set_item_text(4, "Unlink Cel")
|
||||
popup_menu.set_item_metadata(4, "Unlink Cel")
|
||||
else:
|
||||
get_node("LinkedIndicator").visible = false
|
||||
popup_menu.set_item_text(4, "Link Cel")
|
||||
popup_menu.set_item_metadata(4, "Link Cel")
|
||||
|
||||
|
||||
func _on_CelButton_pressed() -> void:
|
||||
if Input.is_action_just_released("left_mouse"):
|
||||
Global.current_frame = frame
|
||||
Global.current_layer = layer
|
||||
elif Input.is_action_just_released("right_mouse"):
|
||||
if Global.canvases.size() == 1:
|
||||
popup_menu.set_item_disabled(0, true)
|
||||
popup_menu.set_item_disabled(2, true)
|
||||
popup_menu.set_item_disabled(3, true)
|
||||
else:
|
||||
popup_menu.set_item_disabled(0, false)
|
||||
if frame > 0:
|
||||
popup_menu.set_item_disabled(2, false)
|
||||
if frame < Global.canvases.size() - 1:
|
||||
popup_menu.set_item_disabled(3, false)
|
||||
popup_menu.popup(Rect2(get_global_mouse_position(), Vector2.ONE))
|
||||
pressed = !pressed
|
||||
elif Input.is_action_just_released("middle_mouse"): # Middle mouse click
|
||||
pressed = !pressed
|
||||
Global.animation_timeline._on_DeleteFrame_pressed(frame)
|
||||
else: # An example of this would be Space
|
||||
pressed = !pressed
|
||||
|
||||
|
||||
func _on_PopupMenu_id_pressed(ID : int) -> void:
|
||||
match ID:
|
||||
0: # Remove Frame
|
||||
Global.animation_timeline._on_DeleteFrame_pressed(frame)
|
||||
1: # Clone Frame
|
||||
Global.animation_timeline._on_CopyFrame_pressed(frame)
|
||||
2: # Move Left
|
||||
change_frame_order(-1)
|
||||
3: # Move Right
|
||||
change_frame_order(1)
|
||||
4: # Unlink Cel
|
||||
var cel_index : int = Global.layers[layer][5].find(Global.canvases[frame])
|
||||
var c = Global.canvases[frame]
|
||||
var new_layers := Global.layers.duplicate(true)
|
||||
var new_canvas_layers : Array = c.layers.duplicate(true)
|
||||
|
||||
if popup_menu.get_item_metadata(4) == "Unlink Cel":
|
||||
new_layers[layer][5].remove(cel_index)
|
||||
var sprite := Image.new()
|
||||
sprite.copy_from(Global.canvases[frame].layers[layer][0])
|
||||
sprite.lock()
|
||||
var tex := ImageTexture.new()
|
||||
tex.create_from_image(sprite, 0)
|
||||
new_canvas_layers[layer][0] = sprite
|
||||
new_canvas_layers[layer][1] = tex
|
||||
|
||||
Global.undo_redo.create_action("Unlink Cel")
|
||||
Global.undo_redo.add_do_property(Global, "layers", new_layers)
|
||||
Global.undo_redo.add_do_property(c, "layers", new_canvas_layers)
|
||||
Global.undo_redo.add_undo_property(Global, "layers", Global.layers)
|
||||
Global.undo_redo.add_undo_property(c, "layers", c.layers)
|
||||
|
||||
Global.undo_redo.add_undo_method(Global, "undo", [Global.canvases[frame]], layer)
|
||||
Global.undo_redo.add_do_method(Global, "redo", [Global.canvases[frame]], layer)
|
||||
Global.undo_redo.commit_action()
|
||||
elif popup_menu.get_item_metadata(4) == "Link Cel":
|
||||
new_layers[layer][5].append(Global.canvases[frame])
|
||||
Global.undo_redo.create_action("Link Cel")
|
||||
Global.undo_redo.add_do_property(Global, "layers", new_layers)
|
||||
if new_layers[layer][5].size() > 1:
|
||||
# If there are already linked cels, set the current cel's image
|
||||
# to the first linked cel's image
|
||||
new_canvas_layers[layer][0] = new_layers[layer][5][0].layers[layer][0]
|
||||
new_canvas_layers[layer][1] = new_layers[layer][5][0].layers[layer][1]
|
||||
Global.undo_redo.add_do_property(c, "layers", new_canvas_layers)
|
||||
Global.undo_redo.add_undo_property(c, "layers", c.layers)
|
||||
|
||||
Global.undo_redo.add_undo_property(Global, "layers", Global.layers)
|
||||
Global.undo_redo.add_undo_method(Global, "undo", [Global.canvases[frame]], layer)
|
||||
Global.undo_redo.add_do_method(Global, "redo", [Global.canvases[frame]], layer)
|
||||
Global.undo_redo.commit_action()
|
||||
|
||||
|
||||
func change_frame_order(rate : int) -> void:
|
||||
var change = frame + rate
|
||||
var new_canvases := Global.canvases.duplicate()
|
||||
var temp = new_canvases[frame]
|
||||
new_canvases[frame] = new_canvases[change]
|
||||
new_canvases[change] = temp
|
||||
|
||||
Global.undo_redo.create_action("Change Frame Order")
|
||||
Global.undo_redo.add_do_property(Global, "canvases", new_canvases)
|
||||
Global.undo_redo.add_do_property(Global.canvases[frame], "frame", change)
|
||||
Global.undo_redo.add_do_property(Global.canvases[change], "frame", frame)
|
||||
|
||||
if Global.current_frame == frame:
|
||||
Global.undo_redo.add_do_property(Global, "current_frame", change)
|
||||
Global.undo_redo.add_undo_property(Global, "current_frame", Global.current_frame)
|
||||
|
||||
Global.undo_redo.add_undo_property(Global, "canvases", Global.canvases)
|
||||
Global.undo_redo.add_undo_property(Global.canvases[frame], "frame", frame)
|
||||
Global.undo_redo.add_undo_property(Global.canvases[change], "frame", change)
|
||||
|
||||
Global.undo_redo.add_undo_method(Global, "undo", [Global.canvases[frame]])
|
||||
Global.undo_redo.add_do_method(Global, "redo", [Global.canvases[frame]])
|
||||
Global.undo_redo.commit_action()
|
||||
|
49
src/UI/Timeline/CelButton.tscn
Normal file
49
src/UI/Timeline/CelButton.tscn
Normal file
|
@ -0,0 +1,49 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://src/UI/Timeline/CelButton.gd" type="Script" id=1]
|
||||
|
||||
|
||||
|
||||
[node name="CelButton" type="Button"]
|
||||
margin_top = 18.0
|
||||
margin_right = 36.0
|
||||
margin_bottom = 54.0
|
||||
rect_min_size = Vector2( 36, 36 )
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 0
|
||||
toggle_mode = true
|
||||
button_mask = 7
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="CelTexture" type="TextureRect" parent="."]
|
||||
margin_left = 2.0
|
||||
margin_top = 1.78536
|
||||
margin_right = 34.0
|
||||
margin_bottom = 33.7854
|
||||
rect_min_size = Vector2( 32, 32 )
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 0
|
||||
expand = true
|
||||
stretch_mode = 6
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="PopupMenu" type="PopupMenu" parent="."]
|
||||
margin_right = 20.0
|
||||
margin_bottom = 20.0
|
||||
mouse_default_cursor_shape = 2
|
||||
items = [ "Remove Frame", null, 0, false, true, -1, 0, null, "", false, "Clone Frame", null, 0, false, false, -1, 0, null, "", false, "Move Left", null, 0, false, true, -1, 0, null, "", false, "Move Right", null, 0, false, true, -1, 0, null, "", false, "Link Cel", null, 0, false, false, -1, 0, null, "", false ]
|
||||
|
||||
[node name="LinkedIndicator" type="Polygon2D" parent="."]
|
||||
visible = false
|
||||
color = Color( 0.0627451, 0.741176, 0.215686, 1 )
|
||||
invert_enable = true
|
||||
invert_border = 1.0
|
||||
polygon = PoolVector2Array( 0, 0, 36, 0, 36, 36, 0, 36 )
|
||||
[connection signal="pressed" from="." to="." method="_on_CelButton_pressed"]
|
||||
[connection signal="id_pressed" from="PopupMenu" to="." method="_on_PopupMenu_id_pressed"]
|
80
src/UI/Timeline/LayerButton.gd
Normal file
80
src/UI/Timeline/LayerButton.gd
Normal file
|
@ -0,0 +1,80 @@
|
|||
class_name LayerButton
|
||||
extends Button
|
||||
|
||||
var i := 0
|
||||
var visibility_button : BaseButton
|
||||
var lock_button : BaseButton
|
||||
var linked_button : BaseButton
|
||||
var label : Label
|
||||
var line_edit : LineEdit
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
visibility_button = Global.find_node_by_name(self, "VisibilityButton")
|
||||
lock_button = Global.find_node_by_name(self, "LockButton")
|
||||
linked_button = Global.find_node_by_name(self, "LinkButton")
|
||||
label = Global.find_node_by_name(self, "Label")
|
||||
line_edit = Global.find_node_by_name(self, "LineEdit")
|
||||
|
||||
if Global.layers[i][1]:
|
||||
visibility_button.texture_normal = load("res://Assets/Graphics/%s Themes/Layers/Layer_Visible.png" % Global.theme_type)
|
||||
visibility_button.texture_hover = load("res://Assets/Graphics/%s Themes/Layers/Layer_Visible_Hover.png" % Global.theme_type)
|
||||
else:
|
||||
visibility_button.texture_normal = load("res://Assets/Graphics/%s Themes/Layers/Layer_Invisible.png" % Global.theme_type)
|
||||
visibility_button.texture_hover = load("res://Assets/Graphics/%s Themes/Layers/Layer_Invisible_Hover.png" % Global.theme_type)
|
||||
|
||||
if Global.layers[i][2]:
|
||||
lock_button.texture_normal = load("res://Assets/Graphics/%s Themes/Layers/Lock.png" % Global.theme_type)
|
||||
lock_button.texture_hover = load("res://Assets/Graphics/%s Themes/Layers/Lock_Hover.png" % Global.theme_type)
|
||||
else:
|
||||
lock_button.texture_normal = load("res://Assets/Graphics/%s Themes/Layers/Unlock.png" % Global.theme_type)
|
||||
lock_button.texture_hover = load("res://Assets/Graphics/%s Themes/Layers/Unlock_Hover.png" % Global.theme_type)
|
||||
|
||||
if Global.layers[i][4]: # If new layers will be linked
|
||||
linked_button.texture_normal = load("res://Assets/Graphics/%s Themes/Layers/Linked_Layer.png" % Global.theme_type)
|
||||
linked_button.texture_hover = load("res://Assets/Graphics/%s Themes/Layers/Linked_Layer_Hover.png" % Global.theme_type)
|
||||
else:
|
||||
linked_button.texture_normal = load("res://Assets/Graphics/%s Themes/Layers/Unlinked_Layer.png" % Global.theme_type)
|
||||
linked_button.texture_hover = load("res://Assets/Graphics/%s Themes/Layers/Unlinked_Layer_Hover.png" % Global.theme_type)
|
||||
|
||||
|
||||
func _input(event : InputEvent) -> void:
|
||||
if (event.is_action_released("ui_accept") or event.is_action_released("ui_cancel")) and line_edit.visible and event.scancode != KEY_SPACE:
|
||||
save_layer_name(line_edit.text)
|
||||
|
||||
|
||||
func _on_LayerContainer_pressed() -> void:
|
||||
pressed = !pressed
|
||||
label.visible = false
|
||||
line_edit.visible = true
|
||||
line_edit.editable = true
|
||||
line_edit.grab_focus()
|
||||
|
||||
|
||||
func _on_LineEdit_focus_exited() -> void:
|
||||
save_layer_name(line_edit.text)
|
||||
|
||||
|
||||
func save_layer_name(new_name : String) -> void:
|
||||
label.visible = true
|
||||
line_edit.visible = false
|
||||
line_edit.editable = false
|
||||
label.text = new_name
|
||||
Global.layers_changed_skip = true
|
||||
Global.layers[i][0] = new_name
|
||||
|
||||
|
||||
func _on_VisibilityButton_pressed() -> void:
|
||||
Global.layers[i][1] = !Global.layers[i][1]
|
||||
Global.canvas.update()
|
||||
|
||||
|
||||
func _on_LockButton_pressed() -> void:
|
||||
Global.layers[i][2] = !Global.layers[i][2]
|
||||
|
||||
|
||||
func _on_LinkButton_pressed() -> void:
|
||||
Global.layers[i][4] = !Global.layers[i][4]
|
||||
if Global.layers[i][4] && !Global.layers[i][5]:
|
||||
Global.layers[i][5].append(Global.canvas)
|
||||
Global.layers[i][3].get_child(Global.current_frame)._ready()
|
120
src/UI/Timeline/LayerButton.tscn
Normal file
120
src/UI/Timeline/LayerButton.tscn
Normal file
|
@ -0,0 +1,120 @@
|
|||
[gd_scene load_steps=8 format=2]
|
||||
|
||||
[ext_resource path="res://src/UI/Timeline/LayerButton.gd" type="Script" id=1]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Layer_Visible_Hover.png" type="Texture" id=2]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Unlock.png" type="Texture" id=3]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Unlinked_Layer.png" type="Texture" id=4]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Layer_Visible.png" type="Texture" id=5]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Unlock_Hover.png" type="Texture" id=6]
|
||||
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Unlinked_Layer_Hover.png" type="Texture" id=7]
|
||||
|
||||
|
||||
[node name="LayerContainer" type="Button"]
|
||||
margin_right = 210.0
|
||||
margin_bottom = 36.0
|
||||
rect_min_size = Vector2( 212, 36 )
|
||||
size_flags_horizontal = 0
|
||||
toggle_mode = true
|
||||
action_mode = 0
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_horizontal_guides_": [ ],
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
size_flags_horizontal = 0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="LayerButtons" type="HBoxContainer" parent="HBoxContainer"]
|
||||
margin_right = 104.0
|
||||
margin_bottom = 36.0
|
||||
|
||||
[node name="VisibilityButton" type="TextureButton" parent="HBoxContainer/LayerButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_top = 2.0
|
||||
margin_right = 32.0
|
||||
margin_bottom = 34.0
|
||||
hint_tooltip = "Toggle layer's visibility"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 4
|
||||
texture_normal = ExtResource( 5 )
|
||||
texture_hover = ExtResource( 2 )
|
||||
|
||||
[node name="LockButton" type="TextureButton" parent="HBoxContainer/LayerButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_left = 36.0
|
||||
margin_top = 2.0
|
||||
margin_right = 68.0
|
||||
margin_bottom = 34.0
|
||||
hint_tooltip = "Lock/unlock layer"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 4
|
||||
texture_normal = ExtResource( 3 )
|
||||
texture_hover = ExtResource( 6 )
|
||||
|
||||
[node name="LinkButton" type="TextureButton" parent="HBoxContainer/LayerButtons" groups=[
|
||||
"UIButtons",
|
||||
]]
|
||||
margin_left = 72.0
|
||||
margin_top = 2.0
|
||||
margin_right = 104.0
|
||||
margin_bottom = 34.0
|
||||
hint_tooltip = "Enable/disable cel linking
|
||||
|
||||
Linked cels are being shared across multiple frames"
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 4
|
||||
texture_normal = ExtResource( 4 )
|
||||
texture_hover = ExtResource( 7 )
|
||||
|
||||
[node name="LayerName" type="HBoxContainer" parent="HBoxContainer"]
|
||||
margin_left = 108.0
|
||||
margin_right = 212.0
|
||||
margin_bottom = 36.0
|
||||
rect_min_size = Vector2( 104, 0 )
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 0
|
||||
alignment = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Label" type="Label" parent="HBoxContainer/LayerName"]
|
||||
margin_top = 11.0
|
||||
margin_right = 104.0
|
||||
margin_bottom = 25.0
|
||||
size_flags_horizontal = 3
|
||||
text = "Layer 0"
|
||||
align = 1
|
||||
clip_text = true
|
||||
|
||||
[node name="LineEdit" type="LineEdit" parent="HBoxContainer/LayerName"]
|
||||
visible = false
|
||||
margin_left = 86.0
|
||||
margin_top = 5.0
|
||||
margin_right = 166.0
|
||||
margin_bottom = 37.0
|
||||
rect_min_size = Vector2( 80, 32 )
|
||||
size_flags_vertical = 4
|
||||
text = "Layer 0"
|
||||
editable = false
|
||||
caret_blink = true
|
||||
caret_blink_speed = 0.5
|
||||
[connection signal="pressed" from="." to="." method="_on_LayerContainer_pressed"]
|
||||
[connection signal="pressed" from="HBoxContainer/LayerButtons/VisibilityButton" to="." method="_on_VisibilityButton_pressed"]
|
||||
[connection signal="pressed" from="HBoxContainer/LayerButtons/LockButton" to="." method="_on_LockButton_pressed"]
|
||||
[connection signal="pressed" from="HBoxContainer/LayerButtons/LinkButton" to="." method="_on_LinkButton_pressed"]
|
||||
[connection signal="focus_exited" from="HBoxContainer/LayerName/LineEdit" to="." method="_on_LineEdit_focus_exited"]
|
8
src/UI/TransparentChecker.gd
Normal file
8
src/UI/TransparentChecker.gd
Normal file
|
@ -0,0 +1,8 @@
|
|||
extends ColorRect
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
rect_size = Global.canvas.size
|
||||
material.set_shader_param("size", Global.checker_size)
|
||||
material.set_shader_param("color1", Global.checker_color_1)
|
||||
material.set_shader_param("color2", Global.checker_color_2)
|
Loading…
Add table
Add a link
Reference in a new issue