1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-03-13 06:45:17 +00:00

Expose pivot Option (#720)

* Added the pivot system

* Some re-arrangement

* a bug-fix

* fixed a conversion scale bug

The problem was the conversion from rect to pixel scale was not properly done, i changed it so that it sets conversion factor of shorter side according to the longer side

* Fix to allow manual pivoting

* remove an update()

i may have added it my self but i think its not needed now

* made shader pivot consistent with gd script

by doing `pivot + Vector2(0.5, 0.5)` for "Nearest neighbour (Shader)"

* Cosmetics

* Formatting

* more formatting

* an optimization
This commit is contained in:
Variable 2022-07-24 01:31:39 +05:00 committed by GitHub
parent 388c121520
commit 43a8a04704
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 272 additions and 86 deletions

View file

@ -9,9 +9,9 @@ uniform vec2 selection_size;
vec2 rotate(vec2 uv, vec2 pivot, float ratio) { vec2 rotate(vec2 uv, vec2 pivot, float ratio) {
// Scale and center image // Scale and center image
uv.x -= 0.5; uv.x -= pivot.x;
uv.x *= ratio; uv.x *= ratio;
uv.x += 0.5; uv.x += pivot.x;
// Rotate image // Rotate image
uv -= pivot; uv -= pivot;
@ -31,13 +31,10 @@ void fragment() {
vec2 tex_size = 1.0 / TEXTURE_PIXEL_SIZE; // Texture size in real pixel coordinates vec2 tex_size = 1.0 / TEXTURE_PIXEL_SIZE; // Texture size in real pixel coordinates
vec2 pixelated_uv = floor(UV * tex_size) / (tex_size - 1.0); // Pixelate UV to fit resolution vec2 pixelated_uv = floor(UV * tex_size) / (tex_size - 1.0); // Pixelate UV to fit resolution
vec2 pivot = selection_pivot / tex_size; // Normalize pivot position vec2 pivot = selection_pivot / tex_size; // Normalize pivot position
vec2 sel_size = selection_size / tex_size; // Normalize selection size
float ratio = tex_size.x / tex_size.y; // Resolution ratio float ratio = tex_size.x / tex_size.y; // Resolution ratio
// Make a border to prevent stretching pixels on the edge // Make a border to prevent stretching pixels on the edge
vec2 border_uv = rotate(pixelated_uv, pivot, ratio); vec2 border_uv = rotate(pixelated_uv, pivot, ratio);
border_uv -= pivot - sel_size / 2.0; // Move the border to selection position
border_uv /= sel_size; // Set border size to selection size
// Center the border // Center the border
border_uv -= 0.5; border_uv -= 0.5;

View file

@ -2,6 +2,7 @@ extends ImageEffect
var live_preview: bool = true var live_preview: bool = true
var shader: Shader = preload("res://src/Shaders/Rotation.shader") var shader: Shader = preload("res://src/Shaders/Rotation.shader")
var pivot := Vector2.ZERO
onready var type_option_button: OptionButton = $VBoxContainer/HBoxContainer2/TypeOptionButton onready var type_option_button: OptionButton = $VBoxContainer/HBoxContainer2/TypeOptionButton
onready var angle_hslider: HSlider = $VBoxContainer/AngleOptions/AngleHSlider onready var angle_hslider: HSlider = $VBoxContainer/AngleOptions/AngleHSlider
@ -24,24 +25,44 @@ func set_nodes() -> void:
func _about_to_show() -> void: func _about_to_show() -> void:
$VBoxContainer/Pivot/Options.visible = false
$VBoxContainer/Pivot/TogglePivot.pressed = false
decide_pivot()
confirmed = false confirmed = false
._about_to_show() ._about_to_show()
wait_apply_timer.wait_time = wait_time_spinbox.value / 1000.0 wait_apply_timer.wait_time = wait_time_spinbox.value / 1000.0
angle_hslider.value = 0 angle_hslider.value = 0
func decide_pivot():
var size := Global.current_project.size
pivot = Vector2(size.x / 2, size.y / 2)
# Pivot correction in case of even size
if type_option_button.text != "Nearest neighbour (Shader)":
if int(size.x) % 2 == 0:
pivot.x -= 0.5
if int(size.y) % 2 == 0:
pivot.y -= 0.5
if Global.current_project.has_selection and selection_checkbox.pressed:
var selection_rectangle: Rect2 = Global.current_project.get_selection_rectangle()
pivot = (
selection_rectangle.position
+ ((selection_rectangle.end - selection_rectangle.position) / 2)
)
if type_option_button.text != "Nearest neighbour (Shader)":
# Pivot correction in case of even size
if int(selection_rectangle.end.x - selection_rectangle.position.x) % 2 == 0:
pivot.x -= 0.5
if int(selection_rectangle.end.y - selection_rectangle.position.y) % 2 == 0:
pivot.y -= 0.5
func commit_action(_cel: Image, _project: Project = Global.current_project) -> void: func commit_action(_cel: Image, _project: Project = Global.current_project) -> void:
var angle: float = deg2rad(angle_hslider.value) var angle: float = deg2rad(angle_hslider.value)
# warning-ignore:integer_division # warning-ignore:integer_division
# warning-ignore:integer_division # warning-ignore:integer_division
var pivot = Vector2(_cel.get_width() / 2, _cel.get_height() / 2)
# Pivot correction in case of even size
if type_option_button.text != "Nearest neighbour (Shader)":
if _cel.get_width() % 2 == 0:
pivot.x -= 0.5
if _cel.get_height() % 2 == 0:
pivot.y -= 0.5
var selection_size := _cel.get_size() var selection_size := _cel.get_size()
var selection_tex := ImageTexture.new() var selection_tex := ImageTexture.new()
@ -50,21 +71,12 @@ func commit_action(_cel: Image, _project: Project = Global.current_project) -> v
image.copy_from(_cel) image.copy_from(_cel)
if _project.has_selection and selection_checkbox.pressed: if _project.has_selection and selection_checkbox.pressed:
var selection_rectangle: Rect2 = _project.get_selection_rectangle() var selection_rectangle: Rect2 = _project.get_selection_rectangle()
pivot = (
selection_rectangle.position
+ ((selection_rectangle.end - selection_rectangle.position) / 2)
)
selection_size = selection_rectangle.size selection_size = selection_rectangle.size
var selection: Image = _project.bitmap_to_image(_project.selection_bitmap) var selection: Image = _project.bitmap_to_image(_project.selection_bitmap)
selection_tex.create_from_image(selection, 0) selection_tex.create_from_image(selection, 0)
if type_option_button.text != "Nearest neighbour (Shader)": if type_option_button.text != "Nearest neighbour (Shader)":
# Pivot correction in case of even size
if int(selection_rectangle.end.x - selection_rectangle.position.x) % 2 == 0:
pivot.x -= 0.5
if int(selection_rectangle.end.y - selection_rectangle.position.y) % 2 == 0:
pivot.y -= 0.5
image.lock() image.lock()
_cel.lock() _cel.lock()
for x in _project.size.x: for x in _project.size.x:
@ -144,6 +156,8 @@ func _on_LiveCheckbox_toggled(button_pressed: bool) -> void:
live_preview = button_pressed live_preview = button_pressed
wait_time_spinbox.editable = !live_preview wait_time_spinbox.editable = !live_preview
wait_time_spinbox.get_parent().visible = !live_preview wait_time_spinbox.get_parent().visible = !live_preview
if !button_pressed:
rect_size.y += 1 # Reset rect_size of dialog
func _on_quick_change_angle_pressed(change_type: String) -> void: func _on_quick_change_angle_pressed(change_type: String) -> void:
@ -166,3 +180,70 @@ func _on_quick_change_angle_pressed(change_type: String) -> void:
elif new_angle >= 360: elif new_angle >= 360:
new_angle = new_angle - 360 new_angle = new_angle - 360
angle_hslider.value = new_angle angle_hslider.value = new_angle
func _on_TogglePivot_toggled(button_pressed: bool) -> void:
$VBoxContainer/Pivot/Options.visible = button_pressed
if button_pressed:
$VBoxContainer/Pivot/TogglePivot.text = "Pivot Options: (v)"
$VBoxContainer/Pivot/TogglePivot.focus_mode = 0
$VBoxContainer/Pivot/Options/X/XPivot.value = pivot.x
$VBoxContainer/Pivot/Options/Y/YPivot.value = pivot.y
else:
$VBoxContainer/Pivot/TogglePivot.text = "Pivot Options: (>)"
$VBoxContainer/Pivot/TogglePivot.focus_mode = 0
rect_size.y += 1 # Reset rect_size of dialog
func _on_Pivot_value_changed(value: float, is_x: bool) -> void:
if is_x:
pivot.x = value
else:
pivot.y = value
# Refresh the indicator
$VBoxContainer/AspectRatioContainer/Indicator.update()
if angle_hslider.value != 0:
update_preview()
func _on_Indicator_draw() -> void:
var pivot_indicator = $VBoxContainer/AspectRatioContainer/Indicator
var img_size := preview_image.get_size()
# find the scale using the larger measurement
var ratio = pivot_indicator.rect_size / img_size
# we need to set the scale according to the larger side
var conversion_scale: float
if img_size.x > img_size.y:
conversion_scale = ratio.x
else:
conversion_scale = ratio.y
var pivot_position = pivot * conversion_scale
pivot_indicator.draw_arc(pivot_position, 2, 0, 360, 360, Color.yellow, 0.5)
pivot_indicator.draw_arc(pivot_position, 6, 0, 360, 360, Color.white, 0.5)
pivot_indicator.draw_line(
pivot_position - Vector2.UP * 10, pivot_position - Vector2.DOWN * 10, Color.white, 0.5
)
pivot_indicator.draw_line(
pivot_position - Vector2.RIGHT * 10, pivot_position - Vector2.LEFT * 10, Color.white, 0.5
)
func _on_Indicator_gui_input(event: InputEvent) -> void:
if event is InputEventMouseMotion:
if event.pressure == 1.0:
var pivot_indicator = $VBoxContainer/AspectRatioContainer/Indicator
var x_pivot = $VBoxContainer/Pivot/Options/X/XPivot
var y_pivot = $VBoxContainer/Pivot/Options/Y/YPivot
var img_size := preview_image.get_size()
var mouse_pos = get_local_mouse_position() - pivot_indicator.rect_position
var ratio = img_size / pivot_indicator.rect_size
# we need to set the scale according to the larger side
var conversion_scale: float
if img_size.x > img_size.y:
conversion_scale = ratio.x
else:
conversion_scale = ratio.y
var new_pos = mouse_pos * conversion_scale
x_pivot.value = new_pos.x
y_pivot.value = new_pos.y
pivot_indicator.update()

View file

@ -4,9 +4,9 @@
[ext_resource path="res://src/UI/TransparentChecker.tscn" type="PackedScene" id=2] [ext_resource path="res://src/UI/TransparentChecker.tscn" type="PackedScene" id=2]
[node name="RotateImage" type="ConfirmationDialog"] [node name="RotateImage" type="ConfirmationDialog"]
margin_right = 320.0 margin_right = 342.0
margin_bottom = 380.0 margin_bottom = 450.0
rect_min_size = Vector2( 320, 380 ) rect_min_size = Vector2( 342, 450 )
window_title = "Rotate Image" window_title = "Rotate Image"
resizable = true resizable = true
script = ExtResource( 1 ) script = ExtResource( 1 )
@ -20,14 +20,14 @@ margin_right = -8.0
margin_bottom = -36.0 margin_bottom = -36.0
[node name="AspectRatioContainer" type="AspectRatioContainer" parent="VBoxContainer"] [node name="AspectRatioContainer" type="AspectRatioContainer" parent="VBoxContainer"]
margin_right = 304.0 margin_right = 326.0
margin_bottom = 204.0 margin_bottom = 226.0
size_flags_vertical = 3 size_flags_vertical = 3
[node name="Preview" type="TextureRect" parent="VBoxContainer/AspectRatioContainer"] [node name="Preview" type="TextureRect" parent="VBoxContainer/AspectRatioContainer"]
margin_left = 50.0 margin_left = 50.0
margin_right = 254.0 margin_right = 276.0
margin_bottom = 204.0 margin_bottom = 226.0
rect_min_size = Vector2( 200, 200 ) rect_min_size = Vector2( 200, 200 )
expand = true expand = true
stretch_mode = 5 stretch_mode = 5
@ -39,15 +39,21 @@ anchor_bottom = 1.0
margin_right = 0.0 margin_right = 0.0
margin_bottom = 0.0 margin_bottom = 0.0
[node name="Indicator" type="Control" parent="VBoxContainer/AspectRatioContainer"]
margin_left = 50.0
margin_right = 276.0
margin_bottom = 226.0
mouse_default_cursor_shape = 2
[node name="LiveSettings" type="HBoxContainer" parent="VBoxContainer"] [node name="LiveSettings" type="HBoxContainer" parent="VBoxContainer"]
margin_top = 208.0 margin_top = 230.0
margin_right = 304.0 margin_right = 326.0
margin_bottom = 232.0 margin_bottom = 254.0
alignment = 1 alignment = 1
[node name="LiveCheckbox" type="CheckBox" parent="VBoxContainer/LiveSettings"] [node name="LiveCheckbox" type="CheckBox" parent="VBoxContainer/LiveSettings"]
margin_left = 98.0 margin_left = 109.0
margin_right = 206.0 margin_right = 217.0
margin_bottom = 24.0 margin_bottom = 24.0
pressed = true pressed = true
text = "Live Preview" text = "Live Preview"
@ -55,7 +61,7 @@ text = "Live Preview"
[node name="WaitSettings" type="HBoxContainer" parent="VBoxContainer"] [node name="WaitSettings" type="HBoxContainer" parent="VBoxContainer"]
visible = false visible = false
margin_top = 232.0 margin_top = 232.0
margin_right = 332.0 margin_right = 326.0
margin_bottom = 256.0 margin_bottom = 256.0
alignment = 1 alignment = 1
__meta__ = { __meta__ = {
@ -63,15 +69,14 @@ __meta__ = {
} }
[node name="Label" type="Label" parent="VBoxContainer/WaitSettings"] [node name="Label" type="Label" parent="VBoxContainer/WaitSettings"]
margin_left = 3.0
margin_top = 5.0 margin_top = 5.0
margin_right = 251.0 margin_right = 248.0
margin_bottom = 19.0 margin_bottom = 19.0
text = "Update preview delay (in milliseconds)" text = "Update preview delay (in milliseconds)"
[node name="WaitTime" type="SpinBox" parent="VBoxContainer/WaitSettings"] [node name="WaitTime" type="SpinBox" parent="VBoxContainer/WaitSettings"]
margin_left = 255.0 margin_left = 252.0
margin_right = 329.0 margin_right = 326.0
margin_bottom = 24.0 margin_bottom = 24.0
min_value = 1.0 min_value = 1.0
max_value = 1000.0 max_value = 1000.0
@ -80,9 +85,9 @@ editable = false
suffix = "msec" suffix = "msec"
[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer"] [node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer"]
margin_top = 236.0 margin_top = 258.0
margin_right = 304.0 margin_right = 326.0
margin_bottom = 256.0 margin_bottom = 278.0
[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer2"] [node name="Label" type="Label" parent="VBoxContainer/HBoxContainer2"]
margin_top = 3.0 margin_top = 3.0
@ -92,52 +97,109 @@ text = "Type:"
[node name="TypeOptionButton" type="OptionButton" parent="VBoxContainer/HBoxContainer2"] [node name="TypeOptionButton" type="OptionButton" parent="VBoxContainer/HBoxContainer2"]
margin_left = 38.0 margin_left = 38.0
margin_right = 304.0 margin_right = 326.0
margin_bottom = 20.0 margin_bottom = 20.0
mouse_default_cursor_shape = 2 mouse_default_cursor_shape = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] [node name="HSeparator" type="HSeparator" parent="VBoxContainer"]
margin_top = 260.0 margin_top = 282.0
margin_right = 304.0 margin_right = 326.0
margin_bottom = 280.0 margin_bottom = 286.0
[node name="Pivot" type="VBoxContainer" parent="VBoxContainer"]
margin_top = 290.0
margin_right = 326.0
margin_bottom = 310.0
[node name="TogglePivot" type="Button" parent="VBoxContainer/Pivot"]
margin_right = 326.0
margin_bottom = 20.0
size_flags_vertical = 2
toggle_mode = true
text = "Pivot Options (>)"
flat = true
align = 0
[node name="Options" type="VBoxContainer" parent="VBoxContainer/Pivot"]
visible = false
margin_top = 24.0
margin_right = 326.0
margin_bottom = 76.0
size_flags_horizontal = 3
alignment = 1 alignment = 1
[node name="Deduct90" type="Button" parent="VBoxContainer/HBoxContainer"] [node name="X" type="HBoxContainer" parent="VBoxContainer/Pivot/Options"]
margin_left = 65.0 margin_right = 326.0
margin_right = 98.0 margin_bottom = 24.0
margin_bottom = 20.0
text = "-90"
[node name="Deduct45" type="Button" parent="VBoxContainer/HBoxContainer"] [node name="Label" type="Label" parent="VBoxContainer/Pivot/Options/X"]
margin_left = 102.0 margin_top = 5.0
margin_right = 135.0 margin_right = 106.0
margin_bottom = 20.0 margin_bottom = 19.0
text = "-45" size_flags_horizontal = 3
text = "X-axis"
align = 2
valign = 1
[node name="Zero" type="Button" parent="VBoxContainer/HBoxContainer"] [node name="XPivot" type="SpinBox" parent="VBoxContainer/Pivot/Options/X"]
margin_left = 139.0 margin_left = 110.0
margin_right = 159.0 margin_right = 216.0
margin_bottom = 20.0 margin_bottom = 24.0
text = "0" size_flags_horizontal = 3
min_value = -10000.0
max_value = 10000.0
step = 0.5
allow_greater = true
allow_lesser = true
[node name="Add45" type="Button" parent="VBoxContainer/HBoxContainer"] [node name="Spacer" type="Control" parent="VBoxContainer/Pivot/Options/X"]
margin_left = 163.0 margin_left = 220.0
margin_right = 199.0 margin_right = 326.0
margin_bottom = 20.0 margin_bottom = 24.0
text = "+45" size_flags_horizontal = 3
[node name="Add90" type="Button" parent="VBoxContainer/HBoxContainer"] [node name="Y" type="HBoxContainer" parent="VBoxContainer/Pivot/Options"]
margin_left = 203.0 margin_top = 28.0
margin_right = 239.0 margin_right = 326.0
margin_bottom = 20.0 margin_bottom = 52.0
text = "+90"
[node name="Label" type="Label" parent="VBoxContainer/Pivot/Options/Y"]
margin_top = 5.0
margin_right = 106.0
margin_bottom = 19.0
size_flags_horizontal = 3
text = "Y-axis"
align = 2
valign = 1
[node name="YPivot" type="SpinBox" parent="VBoxContainer/Pivot/Options/Y"]
margin_left = 110.0
margin_right = 216.0
margin_bottom = 24.0
size_flags_horizontal = 3
min_value = -10000.0
max_value = 10000.0
step = 0.5
allow_greater = true
allow_lesser = true
[node name="Spacer" type="Control" parent="VBoxContainer/Pivot/Options/Y"]
margin_left = 220.0
margin_right = 326.0
margin_bottom = 24.0
size_flags_horizontal = 3
[node name="HSeparator2" type="HSeparator" parent="VBoxContainer"]
margin_top = 314.0
margin_right = 326.0
margin_bottom = 318.0
[node name="AngleOptions" type="HBoxContainer" parent="VBoxContainer"] [node name="AngleOptions" type="HBoxContainer" parent="VBoxContainer"]
margin_top = 284.0 margin_top = 322.0
margin_right = 304.0 margin_right = 326.0
margin_bottom = 308.0 margin_bottom = 346.0
[node name="Label" type="Label" parent="VBoxContainer/AngleOptions"] [node name="Label" type="Label" parent="VBoxContainer/AngleOptions"]
margin_top = 5.0 margin_top = 5.0
@ -147,7 +209,7 @@ text = "Angle:"
[node name="AngleHSlider" type="HSlider" parent="VBoxContainer/AngleOptions"] [node name="AngleHSlider" type="HSlider" parent="VBoxContainer/AngleOptions"]
margin_left = 44.0 margin_left = 44.0
margin_right = 226.0 margin_right = 248.0
margin_bottom = 24.0 margin_bottom = 24.0
mouse_default_cursor_shape = 2 mouse_default_cursor_shape = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
@ -158,17 +220,58 @@ __meta__ = {
} }
[node name="AngleSpinBox" type="SpinBox" parent="VBoxContainer/AngleOptions"] [node name="AngleSpinBox" type="SpinBox" parent="VBoxContainer/AngleOptions"]
margin_left = 230.0 margin_left = 252.0
margin_right = 304.0 margin_right = 326.0
margin_bottom = 24.0 margin_bottom = 24.0
mouse_default_cursor_shape = 2 mouse_default_cursor_shape = 2
max_value = 359.0 max_value = 359.0
suffix = "°" suffix = "°"
[node name="QuickRotations" type="HBoxContainer" parent="VBoxContainer"]
margin_top = 350.0
margin_right = 326.0
margin_bottom = 370.0
alignment = 1
[node name="Deduct90" type="Button" parent="VBoxContainer/QuickRotations"]
margin_left = 76.0
margin_right = 109.0
margin_bottom = 20.0
text = "-90"
[node name="Deduct45" type="Button" parent="VBoxContainer/QuickRotations"]
margin_left = 113.0
margin_right = 146.0
margin_bottom = 20.0
text = "-45"
[node name="Zero" type="Button" parent="VBoxContainer/QuickRotations"]
margin_left = 150.0
margin_right = 170.0
margin_bottom = 20.0
text = "0"
[node name="Add45" type="Button" parent="VBoxContainer/QuickRotations"]
margin_left = 174.0
margin_right = 210.0
margin_bottom = 20.0
text = "+45"
[node name="Add90" type="Button" parent="VBoxContainer/QuickRotations"]
margin_left = 214.0
margin_right = 250.0
margin_bottom = 20.0
text = "+90"
[node name="HSeparator3" type="HSeparator" parent="VBoxContainer"]
margin_top = 374.0
margin_right = 326.0
margin_bottom = 378.0
[node name="OptionsContainer" type="HBoxContainer" parent="VBoxContainer"] [node name="OptionsContainer" type="HBoxContainer" parent="VBoxContainer"]
margin_top = 312.0 margin_top = 382.0
margin_right = 304.0 margin_right = 326.0
margin_bottom = 336.0 margin_bottom = 406.0
[node name="SelectionCheckBox" type="CheckBox" parent="VBoxContainer/OptionsContainer"] [node name="SelectionCheckBox" type="CheckBox" parent="VBoxContainer/OptionsContainer"]
margin_right = 160.0 margin_right = 160.0
@ -188,14 +291,19 @@ selected = 0
[node name="WaitApply" type="Timer" parent="."] [node name="WaitApply" type="Timer" parent="."]
[connection signal="draw" from="VBoxContainer/AspectRatioContainer/Indicator" to="." method="_on_Indicator_draw"]
[connection signal="gui_input" from="VBoxContainer/AspectRatioContainer/Indicator" to="." method="_on_Indicator_gui_input"]
[connection signal="toggled" from="VBoxContainer/LiveSettings/LiveCheckbox" to="." method="_on_LiveCheckbox_toggled"] [connection signal="toggled" from="VBoxContainer/LiveSettings/LiveCheckbox" to="." method="_on_LiveCheckbox_toggled"]
[connection signal="value_changed" from="VBoxContainer/WaitSettings/WaitTime" to="." method="_on_WaitTime_value_changed"] [connection signal="value_changed" from="VBoxContainer/WaitSettings/WaitTime" to="." method="_on_WaitTime_value_changed"]
[connection signal="item_selected" from="VBoxContainer/HBoxContainer2/TypeOptionButton" to="." method="_on_TypeOptionButton_item_selected"] [connection signal="item_selected" from="VBoxContainer/HBoxContainer2/TypeOptionButton" to="." method="_on_TypeOptionButton_item_selected"]
[connection signal="pressed" from="VBoxContainer/HBoxContainer/Deduct90" to="." method="_on_quick_change_angle_pressed" binds= [ "-90" ]] [connection signal="toggled" from="VBoxContainer/Pivot/TogglePivot" to="." method="_on_TogglePivot_toggled"]
[connection signal="pressed" from="VBoxContainer/HBoxContainer/Deduct45" to="." method="_on_quick_change_angle_pressed" binds= [ "-45" ]] [connection signal="value_changed" from="VBoxContainer/Pivot/Options/X/XPivot" to="." method="_on_Pivot_value_changed" binds= [ true ]]
[connection signal="pressed" from="VBoxContainer/HBoxContainer/Zero" to="." method="_on_quick_change_angle_pressed" binds= [ "0" ]] [connection signal="value_changed" from="VBoxContainer/Pivot/Options/Y/YPivot" to="." method="_on_Pivot_value_changed" binds= [ false ]]
[connection signal="pressed" from="VBoxContainer/HBoxContainer/Add45" to="." method="_on_quick_change_angle_pressed" binds= [ "+45" ]]
[connection signal="pressed" from="VBoxContainer/HBoxContainer/Add90" to="." method="_on_quick_change_angle_pressed" binds= [ "+90" ]]
[connection signal="value_changed" from="VBoxContainer/AngleOptions/AngleHSlider" to="." method="_on_HSlider_value_changed"] [connection signal="value_changed" from="VBoxContainer/AngleOptions/AngleHSlider" to="." method="_on_HSlider_value_changed"]
[connection signal="value_changed" from="VBoxContainer/AngleOptions/AngleSpinBox" to="." method="_on_SpinBox_value_changed"] [connection signal="value_changed" from="VBoxContainer/AngleOptions/AngleSpinBox" to="." method="_on_SpinBox_value_changed"]
[connection signal="pressed" from="VBoxContainer/QuickRotations/Deduct90" to="." method="_on_quick_change_angle_pressed" binds= [ "-90" ]]
[connection signal="pressed" from="VBoxContainer/QuickRotations/Deduct45" to="." method="_on_quick_change_angle_pressed" binds= [ "-45" ]]
[connection signal="pressed" from="VBoxContainer/QuickRotations/Zero" to="." method="_on_quick_change_angle_pressed" binds= [ "0" ]]
[connection signal="pressed" from="VBoxContainer/QuickRotations/Add45" to="." method="_on_quick_change_angle_pressed" binds= [ "+45" ]]
[connection signal="pressed" from="VBoxContainer/QuickRotations/Add90" to="." method="_on_quick_change_angle_pressed" binds= [ "+90" ]]
[connection signal="timeout" from="WaitApply" to="." method="_on_WaitApply_timeout"] [connection signal="timeout" from="WaitApply" to="." method="_on_WaitApply_timeout"]