1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-01-31 07:29:49 +00:00

Add a basic stabilizer

Not as powerful as other art software, but should be enough for pixel art
This commit is contained in:
Emmanouil Papadeas 2023-12-04 14:55:38 +02:00
parent 1b22e75034
commit d2734ab044
11 changed files with 73 additions and 18 deletions

View file

@ -1465,6 +1465,10 @@ msgstr ""
msgid "Dynamics"
msgstr ""
#. Found in the Dynamics options menu. A stabilizer is a feature that, when enabled, helps artists create smooth lines as they draw.
msgid "Stabilizer"
msgstr ""
#. Found in the Dynamics options menu. Pressure refers to tablet pen pressure.
msgid "Pressure"
msgstr ""

View file

@ -9,6 +9,8 @@ var vertical_mirror := false
var pixel_perfect := false
# Dynamics
var stabilizer_enabled := false
var stabilizer_value := 16
var dynamics_alpha: int = Dynamics.NONE
var dynamics_size: int = Dynamics.NONE
var pen_pressure := 1.0

View file

@ -6,6 +6,7 @@ var kname: String
var tool_slot: Tools.Slot = null
var cursor_text := ""
var _cursor := Vector2i(Vector2.INF)
var _stabilizer_center := Vector2.ZERO
var _draw_cache: Array[Vector2i] = [] ## For storing already drawn pixels
@warning_ignore("unused_private_class_variable")
@ -54,6 +55,7 @@ func update_config() -> void:
func draw_start(pos: Vector2i) -> void:
_stabilizer_center = pos
_draw_cache = []
is_moving = true
Global.current_project.can_undo = false
@ -260,6 +262,17 @@ func _snap_to_guide(
return snap_to
func _get_stabilized_position(normal_pos: Vector2) -> Vector2:
if not Tools.stabilizer_enabled:
return normal_pos
var difference := normal_pos - _stabilizer_center
var distance := difference.length() / Tools.stabilizer_value
var angle := difference.angle()
var pos := _stabilizer_center + Vector2(distance, distance) * Vector2.from_angle(angle)
_stabilizer_center = pos
return pos
func _get_draw_rect() -> Rect2i:
if Global.current_project.has_selection:
return Global.current_project.selection_map.get_used_rect()

View file

@ -318,7 +318,7 @@ func _draw_tool(pos: Vector2) -> PackedVector2Array:
# Bresenham's Algorithm
# Thanks to https://godotengine.org/qa/35276/tile-based-line-drawing-algorithm-efficiency
func draw_fill_gap(start: Vector2, end: Vector2) -> void:
func draw_fill_gap(start: Vector2i, end: Vector2i) -> void:
if Global.mirror_view:
# Even brushes are not perfectly centred and are offsetted by 1 px so we add it
if int(_stroke_dimensions.x) % 2 == 0:

View file

@ -66,11 +66,12 @@ func draw_start(pos: Vector2i) -> void:
cursor_text = ""
func draw_move(pos: Vector2i) -> void:
func draw_move(pos_i: Vector2i) -> void:
var pos := _get_stabilized_position(pos_i)
pos = snap_position(pos)
super.draw_move(pos)
if _picking_color: # Still return even if we released Alt
if Input.is_action_pressed("draw_color_picker"):
if Input.is_action_pressed(&"draw_color_picker"):
_pick_color(pos)
return

View file

@ -131,11 +131,12 @@ func draw_start(pos: Vector2i) -> void:
cursor_text = ""
func draw_move(pos: Vector2i) -> void:
func draw_move(pos_i: Vector2i) -> void:
var pos := _get_stabilized_position(pos_i)
pos = snap_position(pos)
super.draw_move(pos)
if _picking_color: # Still return even if we released Alt
if Input.is_action_pressed("draw_color_picker"):
if Input.is_action_pressed(&"draw_color_picker"):
_pick_color(pos)
return

View file

@ -12,9 +12,10 @@ func draw_start(pos: Vector2i) -> void:
_last_position = pos
func draw_move(pos: Vector2i) -> void:
func draw_move(pos_i: Vector2i) -> void:
if selection_node.arrow_key_move:
return
var pos := _get_stabilized_position(pos_i)
pos = snap_position(pos)
super.draw_move(pos)
if !_move:
@ -28,8 +29,6 @@ func draw_end(pos: Vector2i) -> void:
if selection_node.arrow_key_move:
return
pos = snap_position(pos)
if !_move:
_draw_points.append(pos)
super.draw_end(pos)

View file

@ -40,9 +40,10 @@ func draw_start(pos: Vector2i) -> void:
_last_position = pos
func draw_move(pos: Vector2i) -> void:
func draw_move(pos_i: Vector2i) -> void:
if selection_node.arrow_key_move:
return
var pos := _get_stabilized_position(pos_i)
pos = snap_position(pos)
super.draw_move(pos)
if !_move:
@ -56,8 +57,6 @@ func draw_end(pos: Vector2i) -> void:
if selection_node.arrow_key_move:
return
pos = snap_position(pos)
if !_move:
_draw_points.append_array(draw_tool(pos))
super.draw_end(pos)

View file

@ -237,11 +237,12 @@ func draw_start(pos: Vector2i) -> void:
cursor_text = ""
func draw_move(pos: Vector2i) -> void:
func draw_move(pos_i: Vector2i) -> void:
var pos := _get_stabilized_position(pos_i)
pos = snap_position(pos)
super.draw_move(pos)
if _picking_color: # Still return even if we released Alt
if Input.is_action_pressed("draw_color_picker"):
if Input.is_action_pressed(&"draw_color_picker"):
_pick_color(pos)
return

View file

@ -153,3 +153,11 @@ func _on_SizeMin_value_changed(value: float) -> void:
func _on_SizeMax_value_changed(value: float) -> void:
Tools.brush_size_max = int(value)
dynamics_changed.emit()
func _on_enable_stabilizer_toggled(toggled_on: bool) -> void:
Tools.stabilizer_enabled = toggled_on
func _on_stabilizer_value_value_changed(value: float) -> void:
Tools.stabilizer_value = value

View file

@ -45,7 +45,6 @@ gradient = SubResource("3")
gradient = SubResource("3")
[node name="Global Tool Options" type="PanelContainer"]
custom_minimum_size = Vector2(0, 36)
offset_left = 1.0
offset_right = 195.0
offset_bottom = 50.0
@ -147,12 +146,38 @@ texture = ExtResource("6")
[node name="DynamicsPanel" type="PopupPanel" parent="."]
canvas_item_default_texture_filter = 0
size = Vector2i(300, 334)
[node name="VBoxContainer" type="VBoxContainer" parent="DynamicsPanel"]
offset_left = 4.0
offset_top = 4.0
offset_right = 186.0
offset_bottom = 288.0
offset_left = 8.0
offset_top = 8.0
offset_right = 292.0
offset_bottom = 326.0
[node name="StabilizerContainer" type="HBoxContainer" parent="DynamicsPanel/VBoxContainer"]
layout_mode = 2
[node name="EnableStabilizer" type="CheckButton" parent="DynamicsPanel/VBoxContainer/StabilizerContainer"]
layout_mode = 2
mouse_default_cursor_shape = 2
text = "Stabilizer"
[node name="StabilizerValue" type="TextureProgressBar" parent="DynamicsPanel/VBoxContainer/StabilizerContainer"]
layout_mode = 2
size_flags_horizontal = 3
focus_mode = 2
mouse_default_cursor_shape = 2
theme_type_variation = &"ValueSlider"
min_value = 1.0
max_value = 64.0
value = 16.0
allow_greater = true
nine_patch_stretch = true
stretch_margin_left = 3
stretch_margin_top = 3
stretch_margin_right = 3
stretch_margin_bottom = 3
script = ExtResource("5")
[node name="DynamicsOptions" type="GridContainer" parent="DynamicsPanel/VBoxContainer"]
layout_mode = 2
@ -412,6 +437,8 @@ offset_bottom = 23.0
[connection signal="toggled" from="ScrollContainer/CenterContainer/GridContainer/Vertical" to="." method="_on_Vertical_toggled"]
[connection signal="toggled" from="ScrollContainer/CenterContainer/GridContainer/PixelPerfect" to="." method="_on_PixelPerfect_toggled"]
[connection signal="pressed" from="ScrollContainer/CenterContainer/GridContainer/Dynamics" to="." method="_on_Dynamics_pressed"]
[connection signal="toggled" from="DynamicsPanel/VBoxContainer/StabilizerContainer/EnableStabilizer" to="." method="_on_enable_stabilizer_toggled"]
[connection signal="value_changed" from="DynamicsPanel/VBoxContainer/StabilizerContainer/StabilizerValue" to="." method="_on_stabilizer_value_value_changed"]
[connection signal="value_changed" from="DynamicsPanel/VBoxContainer/LimitContainer/AlphaMin" to="." method="_on_AlphaMin_value_changed"]
[connection signal="value_changed" from="DynamicsPanel/VBoxContainer/LimitContainer/AlphaMax" to="." method="_on_AlphaMax_value_changed"]
[connection signal="value_changed" from="DynamicsPanel/VBoxContainer/LimitContainer/SizeMin" to="." method="_on_SizeMin_value_changed"]