mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-02-20 12:33:14 +00:00
Replace the Locked Aspect Ratio mode in the crop tool with a lock button next to the size sliders
This commit is contained in:
parent
2ad1391ca1
commit
acb32844a1
3 changed files with 72 additions and 126 deletions
|
@ -1,10 +1,11 @@
|
|||
extends BaseTool
|
||||
# Crop Tool, allows you to resize the canvas interactively
|
||||
|
||||
var _offset = Vector2.ZERO
|
||||
var _offset := Vector2.ZERO
|
||||
var _crop: CropRect
|
||||
var _start_pos: Vector2
|
||||
var _syncing := false
|
||||
var _locked_ratio := false
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
|
@ -29,28 +30,24 @@ func draw_move(position: Vector2) -> void:
|
|||
if _crop.locked_size:
|
||||
_crop.rect.position = position - _offset
|
||||
else:
|
||||
match _crop.mode:
|
||||
CropRect.Mode.MARGINS, CropRect.Mode.POSITION_SIZE:
|
||||
_crop.rect.position.x = min(_start_pos.x, position.x)
|
||||
_crop.rect.position.y = min(_start_pos.y, position.y)
|
||||
_crop.rect.end.x = max(_start_pos.x, position.x)
|
||||
_crop.rect.end.y = max(_start_pos.y, position.y)
|
||||
CropRect.Mode.LOCKED_ASPECT_RATIO:
|
||||
var distance = abs(_start_pos.x - position.x) + abs(_start_pos.y - position.y)
|
||||
_crop.rect.size.x = round(
|
||||
distance * _crop.ratio.x / (_crop.ratio.x + _crop.ratio.y)
|
||||
)
|
||||
_crop.rect.size.y = round(
|
||||
distance * _crop.ratio.y / (_crop.ratio.x + _crop.ratio.y)
|
||||
)
|
||||
if _start_pos.x < position.x:
|
||||
_crop.rect.position.x = _start_pos.x
|
||||
else:
|
||||
_crop.rect.position.x = _start_pos.x - _crop.rect.size.x
|
||||
if _start_pos.y < position.y:
|
||||
_crop.rect.position.y = _start_pos.y
|
||||
else:
|
||||
_crop.rect.position.y = _start_pos.y - _crop.rect.size.y
|
||||
if _crop.mode == CropRect.Mode.POSITION_SIZE and _locked_ratio:
|
||||
var ratio: Vector2 = $"%Size".ratio
|
||||
var distance := abs(_start_pos.x - position.x) + abs(_start_pos.y - position.y)
|
||||
_crop.rect.size.x = round(distance * ratio.x / (ratio.x + ratio.y))
|
||||
_crop.rect.size.y = round(distance * ratio.y / (ratio.x + ratio.y))
|
||||
if _start_pos.x < position.x:
|
||||
_crop.rect.position.x = _start_pos.x
|
||||
else:
|
||||
_crop.rect.position.x = _start_pos.x - _crop.rect.size.x
|
||||
if _start_pos.y < position.y:
|
||||
_crop.rect.position.y = _start_pos.y
|
||||
else:
|
||||
_crop.rect.position.y = _start_pos.y - _crop.rect.size.y
|
||||
else:
|
||||
_crop.rect.position.x = min(_start_pos.x, position.x)
|
||||
_crop.rect.position.y = min(_start_pos.y, position.y)
|
||||
_crop.rect.end.x = max(_start_pos.x, position.x)
|
||||
_crop.rect.end.y = max(_start_pos.y, position.y)
|
||||
# Ensure that the size is at least 1:
|
||||
_crop.rect.size.x = max(1, _crop.rect.size.x)
|
||||
_crop.rect.size.y = max(1, _crop.rect.size.y)
|
||||
|
@ -69,12 +66,6 @@ func _sync_ui() -> void:
|
|||
$"%DimensionsLabel".show()
|
||||
CropRect.Mode.POSITION_SIZE:
|
||||
$"%MarginsContainer".hide()
|
||||
$"%RatioContainer".hide()
|
||||
$"%PosSizeContainer".show()
|
||||
$"%DimensionsLabel".hide()
|
||||
CropRect.Mode.LOCKED_ASPECT_RATIO:
|
||||
$"%MarginsContainer".hide()
|
||||
$"%RatioContainer".show()
|
||||
$"%PosSizeContainer".show()
|
||||
$"%DimensionsLabel".hide()
|
||||
|
||||
|
@ -87,17 +78,10 @@ func _sync_ui() -> void:
|
|||
$"%Left".value = _crop.rect.position.x
|
||||
$"%Right".value = _crop.rect.end.x
|
||||
|
||||
$"%RatioX".value = _crop.ratio.x
|
||||
$"%RatioY".value = _crop.ratio.y
|
||||
|
||||
$"%PositionX".max_value = Global.current_project.size.x - 1
|
||||
$"%PositionY".max_value = Global.current_project.size.y - 1
|
||||
$"%Width".max_value = Global.current_project.size.x
|
||||
$"%Height".max_value = Global.current_project.size.y
|
||||
$"%PositionX".value = _crop.rect.position.x
|
||||
$"%PositionY".value = _crop.rect.position.y
|
||||
$"%Width".value = _crop.rect.size.x
|
||||
$"%Height".value = _crop.rect.size.y
|
||||
$"%Position".max_value = Global.current_project.size - Vector2.ONE
|
||||
$"%Size".max_value = Global.current_project.size
|
||||
$"%Position".value = _crop.rect.position
|
||||
$"%Size".value = _crop.rect.size
|
||||
|
||||
$"%DimensionsLabel".text = str(_crop.rect.size.x, " x ", _crop.rect.size.y)
|
||||
_syncing = false
|
||||
|
@ -161,49 +145,40 @@ func _on_Right_value_changed(value: float) -> void:
|
|||
func _on_RatioX_value_changed(value: float) -> void:
|
||||
if _syncing:
|
||||
return
|
||||
_crop.rect.size.x = round(max(1, _crop.rect.size.y / _crop.ratio.y * value))
|
||||
_crop.ratio.x = value
|
||||
var prev_ratio: Vector2 = $"%Size".ratio
|
||||
$"%Size".ratio.x = value
|
||||
_crop.rect.size.x = round(max(1, _crop.rect.size.y / prev_ratio.y * value))
|
||||
_crop.emit_signal("updated")
|
||||
|
||||
|
||||
func _on_RatioY_value_changed(value: float) -> void:
|
||||
if _syncing:
|
||||
return
|
||||
_crop.rect.size.y = round(max(1, _crop.rect.size.x / _crop.ratio.x * value))
|
||||
_crop.ratio.y = value
|
||||
var prev_ratio: Vector2 = $"%Size".ratio
|
||||
$"%Size".ratio.y = value
|
||||
_crop.rect.size.y = round(max(1, _crop.rect.size.x / prev_ratio.x * value))
|
||||
_crop.emit_signal("updated")
|
||||
|
||||
|
||||
func _on_PositionX_value_changed(value: float) -> void:
|
||||
func _on_Position_value_changed(value: Vector2) -> void:
|
||||
if _syncing:
|
||||
return
|
||||
_crop.rect.position.x = value
|
||||
_crop.rect.position = value
|
||||
_crop.emit_signal("updated")
|
||||
|
||||
|
||||
func _on_PositionY_value_changed(value: float) -> void:
|
||||
func _on_Size_value_changed(value: Vector2) -> void:
|
||||
if _syncing:
|
||||
return
|
||||
_crop.rect.position.y = value
|
||||
_crop.rect.size = value
|
||||
_crop.emit_signal("updated")
|
||||
|
||||
|
||||
func _on_Width_value_changed(value: float) -> void:
|
||||
if _syncing:
|
||||
return
|
||||
if _crop.mode == CropRect.Mode.LOCKED_ASPECT_RATIO:
|
||||
_crop.rect.size.y = round(max(1, (value / _crop.ratio.x) * _crop.ratio.y))
|
||||
_crop.rect.size.x = value
|
||||
_crop.emit_signal("updated")
|
||||
|
||||
|
||||
func _on_Height_value_changed(value: float) -> void:
|
||||
if _syncing:
|
||||
return
|
||||
if _crop.mode == CropRect.Mode.LOCKED_ASPECT_RATIO:
|
||||
_crop.rect.size.x = round(max(1, (value / _crop.ratio.y) * _crop.ratio.x))
|
||||
_crop.rect.size.y = value
|
||||
_crop.emit_signal("updated")
|
||||
func _on_Size_ratio_toggled(button_pressed: bool) -> void:
|
||||
$"%RatioX".value = $"%Size".ratio.x
|
||||
$"%RatioY".value = $"%Size".ratio.y
|
||||
$"%RatioContainer".visible = button_pressed
|
||||
_locked_ratio = button_pressed
|
||||
|
||||
|
||||
func _on_Apply_pressed() -> void:
|
||||
|
|
|
@ -1,20 +1,21 @@
|
|||
[gd_scene load_steps=5 format=2]
|
||||
[gd_scene load_steps=6 format=2]
|
||||
|
||||
[ext_resource path="res://src/Tools/BaseTool.tscn" type="PackedScene" id=1]
|
||||
[ext_resource path="res://src/UI/Nodes/ValueSlider.tscn" type="PackedScene" id=2]
|
||||
[ext_resource path="res://src/Tools/CropTool.gd" type="Script" id=3]
|
||||
[ext_resource path="res://assets/graphics/misc/unlocked_size.png" type="Texture" id=4]
|
||||
[ext_resource path="res://src/UI/Nodes/ValueSliderV2.tscn" type="PackedScene" id=5]
|
||||
|
||||
[node name="ToolOptions" instance=ExtResource( 1 )]
|
||||
script = ExtResource( 3 )
|
||||
|
||||
[node name="ModeLabel" type="Label" parent="." index="4"]
|
||||
[node name="ModeLabel" type="Label" parent="." index="2"]
|
||||
margin_top = 26.0
|
||||
margin_right = 116.0
|
||||
margin_bottom = 40.0
|
||||
text = "Mode:"
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="." index="5"]
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="." index="3"]
|
||||
margin_top = 44.0
|
||||
margin_right = 116.0
|
||||
margin_bottom = 66.0
|
||||
|
@ -23,10 +24,11 @@ margin_bottom = 66.0
|
|||
unique_name_in_owner = true
|
||||
margin_right = 84.0
|
||||
margin_bottom = 22.0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Margins"
|
||||
clip_text = true
|
||||
items = [ "Margins", null, false, 0, null, "Position + Size", null, false, 1, null, "Locked Aspect Ratio", null, false, 3, null ]
|
||||
items = [ "Margins", null, false, 0, null, "Position + Size", null, false, 1, null ]
|
||||
selected = 0
|
||||
|
||||
[node name="SizeLock" type="Button" parent="HBoxContainer" index="1"]
|
||||
|
@ -40,13 +42,14 @@ When enabled using the tool on the canvas will only move the cropping rectangle.
|
|||
|
||||
When disabled using the tool on the canvas will draw the rectangle."
|
||||
focus_mode = 0
|
||||
mouse_default_cursor_shape = 2
|
||||
toggle_mode = true
|
||||
icon = ExtResource( 4 )
|
||||
__meta__ = {
|
||||
"_editor_description_": ""
|
||||
}
|
||||
|
||||
[node name="MarginsContainer" type="VBoxContainer" parent="." index="6"]
|
||||
[node name="MarginsContainer" type="VBoxContainer" parent="." index="4"]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 70.0
|
||||
margin_right = 116.0
|
||||
|
@ -93,8 +96,9 @@ allow_greater = true
|
|||
allow_lesser = true
|
||||
prefix = "Right:"
|
||||
|
||||
[node name="RatioContainer" type="VBoxContainer" parent="." index="7"]
|
||||
[node name="RatioContainer" type="VBoxContainer" parent="." index="5"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
margin_top = 200.0
|
||||
margin_right = 116.0
|
||||
margin_bottom = 242.0
|
||||
|
@ -131,72 +135,55 @@ min_value = 1.0
|
|||
value = 1.0
|
||||
allow_greater = true
|
||||
|
||||
[node name="PosSizeContainer" type="VBoxContainer" parent="." index="8"]
|
||||
[node name="PosSizeContainer" type="VBoxContainer" parent="." index="6"]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 246.0
|
||||
margin_top = 200.0
|
||||
margin_right = 116.0
|
||||
margin_bottom = 390.0
|
||||
margin_bottom = 344.0
|
||||
|
||||
[node name="PositionLabel" type="Label" parent="PosSizeContainer" index="0"]
|
||||
margin_right = 116.0
|
||||
margin_bottom = 14.0
|
||||
text = "Position:"
|
||||
|
||||
[node name="PositionX" parent="PosSizeContainer" index="1" instance=ExtResource( 2 )]
|
||||
[node name="Position" parent="PosSizeContainer" index="1" instance=ExtResource( 5 )]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 18.0
|
||||
margin_right = 116.0
|
||||
margin_bottom = 42.0
|
||||
allow_greater = true
|
||||
allow_lesser = true
|
||||
prefix = "X:"
|
||||
|
||||
[node name="PositionY" parent="PosSizeContainer" index="2" instance=ExtResource( 2 )]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 46.0
|
||||
margin_right = 116.0
|
||||
margin_bottom = 70.0
|
||||
allow_greater = true
|
||||
allow_lesser = true
|
||||
prefix = "Y:"
|
||||
|
||||
[node name="SizeLabel" type="Label" parent="PosSizeContainer" index="3"]
|
||||
[node name="SizeLabel" type="Label" parent="PosSizeContainer" index="2"]
|
||||
margin_top = 74.0
|
||||
margin_right = 116.0
|
||||
margin_bottom = 88.0
|
||||
text = "Size:"
|
||||
|
||||
[node name="Width" parent="PosSizeContainer" index="4" instance=ExtResource( 2 )]
|
||||
[node name="Size" parent="PosSizeContainer" index="3" instance=ExtResource( 5 )]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 92.0
|
||||
margin_right = 116.0
|
||||
margin_bottom = 116.0
|
||||
min_value = 1.0
|
||||
value = 1.0
|
||||
allow_greater = true
|
||||
prefix = "W:"
|
||||
|
||||
[node name="Height" parent="PosSizeContainer" index="5" instance=ExtResource( 2 )]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 120.0
|
||||
margin_right = 116.0
|
||||
margin_bottom = 144.0
|
||||
min_value = 1.0
|
||||
value = 1.0
|
||||
value = Vector2( 1, 1 )
|
||||
min_value = Vector2( 1, 1 )
|
||||
allow_greater = true
|
||||
prefix = "H:"
|
||||
show_ratio = true
|
||||
prefix_x = "Width:"
|
||||
prefix_y = "Height:"
|
||||
|
||||
[node name="Apply" type="Button" parent="." index="9"]
|
||||
margin_top = 394.0
|
||||
[node name="Apply" type="Button" parent="." index="7"]
|
||||
margin_top = 348.0
|
||||
margin_right = 116.0
|
||||
margin_bottom = 414.0
|
||||
margin_bottom = 368.0
|
||||
mouse_default_cursor_shape = 2
|
||||
text = "Apply"
|
||||
|
||||
[node name="DimensionsLabel" type="Label" parent="." index="10"]
|
||||
[node name="DimensionsLabel" type="Label" parent="." index="8"]
|
||||
unique_name_in_owner = true
|
||||
margin_top = 418.0
|
||||
margin_top = 372.0
|
||||
margin_right = 116.0
|
||||
margin_bottom = 432.0
|
||||
margin_bottom = 386.0
|
||||
align = 1
|
||||
|
||||
[connection signal="item_selected" from="HBoxContainer/CropMode" to="." method="_on_CropMode_item_selected"]
|
||||
|
@ -207,8 +194,7 @@ align = 1
|
|||
[connection signal="value_changed" from="MarginsContainer/Right" to="." method="_on_Right_value_changed"]
|
||||
[connection signal="value_changed" from="RatioContainer/HBoxContainer/RatioX" to="." method="_on_RatioX_value_changed"]
|
||||
[connection signal="value_changed" from="RatioContainer/HBoxContainer/RatioY" to="." method="_on_RatioY_value_changed"]
|
||||
[connection signal="value_changed" from="PosSizeContainer/PositionX" to="." method="_on_PositionX_value_changed"]
|
||||
[connection signal="value_changed" from="PosSizeContainer/PositionY" to="." method="_on_PositionY_value_changed"]
|
||||
[connection signal="value_changed" from="PosSizeContainer/Width" to="." method="_on_Width_value_changed"]
|
||||
[connection signal="value_changed" from="PosSizeContainer/Height" to="." method="_on_Height_value_changed"]
|
||||
[connection signal="value_changed" from="PosSizeContainer/Position" to="." method="_on_Position_value_changed"]
|
||||
[connection signal="ratio_toggled" from="PosSizeContainer/Size" to="." method="_on_Size_ratio_toggled"]
|
||||
[connection signal="value_changed" from="PosSizeContainer/Size" to="." method="_on_Size_value_changed"]
|
||||
[connection signal="pressed" from="Apply" to="." method="_on_Apply_pressed"]
|
||||
|
|
|
@ -5,16 +5,15 @@ extends Node2D
|
|||
|
||||
signal updated
|
||||
|
||||
enum Mode { MARGINS, POSITION_SIZE, LOCKED_ASPECT_RATIO }
|
||||
enum Mode { MARGINS, POSITION_SIZE }
|
||||
|
||||
const BIG = 100000 # Size of big rectangles used to darken background.
|
||||
const DARKEN_COLOR = Color(0, 0, 0, 0.5)
|
||||
const LINE_COLOR = Color.white
|
||||
|
||||
var mode := 0 setget _set_mode
|
||||
var mode: int = Mode.MARGINS setget _set_mode
|
||||
var locked_size := false
|
||||
var rect := Rect2(0, 0, 1, 1)
|
||||
var ratio := Vector2.ONE
|
||||
|
||||
# How many crop tools are active (0-2), setter makes this visible if not 0
|
||||
var tool_count := 0 setget _set_tool_count
|
||||
|
@ -66,27 +65,13 @@ func apply() -> void:
|
|||
func reset() -> void:
|
||||
rect.position = Vector2.ZERO
|
||||
rect.size = Global.current_project.size
|
||||
if mode == Mode.LOCKED_ASPECT_RATIO:
|
||||
_auto_ratio_from_resolution()
|
||||
emit_signal("updated")
|
||||
|
||||
|
||||
func _auto_ratio_from_resolution() -> void:
|
||||
var divisor := _gcd(rect.size.x, rect.size.y)
|
||||
ratio = rect.size / divisor
|
||||
|
||||
|
||||
# Greatest common divisor
|
||||
func _gcd(a: int, b: int) -> int:
|
||||
return a if b == 0 else _gcd(b, a % b)
|
||||
|
||||
|
||||
# Setters
|
||||
|
||||
|
||||
func _set_mode(value: int) -> void:
|
||||
if value == Mode.LOCKED_ASPECT_RATIO and mode != Mode.LOCKED_ASPECT_RATIO:
|
||||
_auto_ratio_from_resolution()
|
||||
mode = value
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue