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:
parent
1b22e75034
commit
d2734ab044
|
@ -1465,6 +1465,10 @@ msgstr ""
|
||||||
msgid "Dynamics"
|
msgid "Dynamics"
|
||||||
msgstr ""
|
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.
|
#. Found in the Dynamics options menu. Pressure refers to tablet pen pressure.
|
||||||
msgid "Pressure"
|
msgid "Pressure"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
@ -9,6 +9,8 @@ var vertical_mirror := false
|
||||||
var pixel_perfect := false
|
var pixel_perfect := false
|
||||||
|
|
||||||
# Dynamics
|
# Dynamics
|
||||||
|
var stabilizer_enabled := false
|
||||||
|
var stabilizer_value := 16
|
||||||
var dynamics_alpha: int = Dynamics.NONE
|
var dynamics_alpha: int = Dynamics.NONE
|
||||||
var dynamics_size: int = Dynamics.NONE
|
var dynamics_size: int = Dynamics.NONE
|
||||||
var pen_pressure := 1.0
|
var pen_pressure := 1.0
|
||||||
|
|
|
@ -6,6 +6,7 @@ var kname: String
|
||||||
var tool_slot: Tools.Slot = null
|
var tool_slot: Tools.Slot = null
|
||||||
var cursor_text := ""
|
var cursor_text := ""
|
||||||
var _cursor := Vector2i(Vector2.INF)
|
var _cursor := Vector2i(Vector2.INF)
|
||||||
|
var _stabilizer_center := Vector2.ZERO
|
||||||
|
|
||||||
var _draw_cache: Array[Vector2i] = [] ## For storing already drawn pixels
|
var _draw_cache: Array[Vector2i] = [] ## For storing already drawn pixels
|
||||||
@warning_ignore("unused_private_class_variable")
|
@warning_ignore("unused_private_class_variable")
|
||||||
|
@ -54,6 +55,7 @@ func update_config() -> void:
|
||||||
|
|
||||||
|
|
||||||
func draw_start(pos: Vector2i) -> void:
|
func draw_start(pos: Vector2i) -> void:
|
||||||
|
_stabilizer_center = pos
|
||||||
_draw_cache = []
|
_draw_cache = []
|
||||||
is_moving = true
|
is_moving = true
|
||||||
Global.current_project.can_undo = false
|
Global.current_project.can_undo = false
|
||||||
|
@ -260,6 +262,17 @@ func _snap_to_guide(
|
||||||
return snap_to
|
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:
|
func _get_draw_rect() -> Rect2i:
|
||||||
if Global.current_project.has_selection:
|
if Global.current_project.has_selection:
|
||||||
return Global.current_project.selection_map.get_used_rect()
|
return Global.current_project.selection_map.get_used_rect()
|
||||||
|
|
|
@ -318,7 +318,7 @@ func _draw_tool(pos: Vector2) -> PackedVector2Array:
|
||||||
|
|
||||||
# Bresenham's Algorithm
|
# Bresenham's Algorithm
|
||||||
# Thanks to https://godotengine.org/qa/35276/tile-based-line-drawing-algorithm-efficiency
|
# 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:
|
if Global.mirror_view:
|
||||||
# Even brushes are not perfectly centred and are offsetted by 1 px so we add it
|
# Even brushes are not perfectly centred and are offsetted by 1 px so we add it
|
||||||
if int(_stroke_dimensions.x) % 2 == 0:
|
if int(_stroke_dimensions.x) % 2 == 0:
|
||||||
|
|
|
@ -66,11 +66,12 @@ func draw_start(pos: Vector2i) -> void:
|
||||||
cursor_text = ""
|
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)
|
pos = snap_position(pos)
|
||||||
super.draw_move(pos)
|
super.draw_move(pos)
|
||||||
if _picking_color: # Still return even if we released Alt
|
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)
|
_pick_color(pos)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -131,11 +131,12 @@ func draw_start(pos: Vector2i) -> void:
|
||||||
cursor_text = ""
|
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)
|
pos = snap_position(pos)
|
||||||
super.draw_move(pos)
|
super.draw_move(pos)
|
||||||
if _picking_color: # Still return even if we released Alt
|
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)
|
_pick_color(pos)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,10 @@ func draw_start(pos: Vector2i) -> void:
|
||||||
_last_position = pos
|
_last_position = pos
|
||||||
|
|
||||||
|
|
||||||
func draw_move(pos: Vector2i) -> void:
|
func draw_move(pos_i: Vector2i) -> void:
|
||||||
if selection_node.arrow_key_move:
|
if selection_node.arrow_key_move:
|
||||||
return
|
return
|
||||||
|
var pos := _get_stabilized_position(pos_i)
|
||||||
pos = snap_position(pos)
|
pos = snap_position(pos)
|
||||||
super.draw_move(pos)
|
super.draw_move(pos)
|
||||||
if !_move:
|
if !_move:
|
||||||
|
@ -28,8 +29,6 @@ func draw_end(pos: Vector2i) -> void:
|
||||||
if selection_node.arrow_key_move:
|
if selection_node.arrow_key_move:
|
||||||
return
|
return
|
||||||
pos = snap_position(pos)
|
pos = snap_position(pos)
|
||||||
if !_move:
|
|
||||||
_draw_points.append(pos)
|
|
||||||
super.draw_end(pos)
|
super.draw_end(pos)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -40,9 +40,10 @@ func draw_start(pos: Vector2i) -> void:
|
||||||
_last_position = pos
|
_last_position = pos
|
||||||
|
|
||||||
|
|
||||||
func draw_move(pos: Vector2i) -> void:
|
func draw_move(pos_i: Vector2i) -> void:
|
||||||
if selection_node.arrow_key_move:
|
if selection_node.arrow_key_move:
|
||||||
return
|
return
|
||||||
|
var pos := _get_stabilized_position(pos_i)
|
||||||
pos = snap_position(pos)
|
pos = snap_position(pos)
|
||||||
super.draw_move(pos)
|
super.draw_move(pos)
|
||||||
if !_move:
|
if !_move:
|
||||||
|
@ -56,8 +57,6 @@ func draw_end(pos: Vector2i) -> void:
|
||||||
if selection_node.arrow_key_move:
|
if selection_node.arrow_key_move:
|
||||||
return
|
return
|
||||||
pos = snap_position(pos)
|
pos = snap_position(pos)
|
||||||
if !_move:
|
|
||||||
_draw_points.append_array(draw_tool(pos))
|
|
||||||
super.draw_end(pos)
|
super.draw_end(pos)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -237,11 +237,12 @@ func draw_start(pos: Vector2i) -> void:
|
||||||
cursor_text = ""
|
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)
|
pos = snap_position(pos)
|
||||||
super.draw_move(pos)
|
super.draw_move(pos)
|
||||||
if _picking_color: # Still return even if we released Alt
|
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)
|
_pick_color(pos)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -153,3 +153,11 @@ func _on_SizeMin_value_changed(value: float) -> void:
|
||||||
func _on_SizeMax_value_changed(value: float) -> void:
|
func _on_SizeMax_value_changed(value: float) -> void:
|
||||||
Tools.brush_size_max = int(value)
|
Tools.brush_size_max = int(value)
|
||||||
dynamics_changed.emit()
|
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
|
||||||
|
|
|
@ -45,7 +45,6 @@ gradient = SubResource("3")
|
||||||
gradient = SubResource("3")
|
gradient = SubResource("3")
|
||||||
|
|
||||||
[node name="Global Tool Options" type="PanelContainer"]
|
[node name="Global Tool Options" type="PanelContainer"]
|
||||||
custom_minimum_size = Vector2(0, 36)
|
|
||||||
offset_left = 1.0
|
offset_left = 1.0
|
||||||
offset_right = 195.0
|
offset_right = 195.0
|
||||||
offset_bottom = 50.0
|
offset_bottom = 50.0
|
||||||
|
@ -147,12 +146,38 @@ texture = ExtResource("6")
|
||||||
|
|
||||||
[node name="DynamicsPanel" type="PopupPanel" parent="."]
|
[node name="DynamicsPanel" type="PopupPanel" parent="."]
|
||||||
canvas_item_default_texture_filter = 0
|
canvas_item_default_texture_filter = 0
|
||||||
|
size = Vector2i(300, 334)
|
||||||
|
|
||||||
[node name="VBoxContainer" type="VBoxContainer" parent="DynamicsPanel"]
|
[node name="VBoxContainer" type="VBoxContainer" parent="DynamicsPanel"]
|
||||||
offset_left = 4.0
|
offset_left = 8.0
|
||||||
offset_top = 4.0
|
offset_top = 8.0
|
||||||
offset_right = 186.0
|
offset_right = 292.0
|
||||||
offset_bottom = 288.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"]
|
[node name="DynamicsOptions" type="GridContainer" parent="DynamicsPanel/VBoxContainer"]
|
||||||
layout_mode = 2
|
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/Vertical" to="." method="_on_Vertical_toggled"]
|
||||||
[connection signal="toggled" from="ScrollContainer/CenterContainer/GridContainer/PixelPerfect" to="." method="_on_PixelPerfect_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="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/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/AlphaMax" to="." method="_on_AlphaMax_value_changed"]
|
||||||
[connection signal="value_changed" from="DynamicsPanel/VBoxContainer/LimitContainer/SizeMin" to="." method="_on_SizeMin_value_changed"]
|
[connection signal="value_changed" from="DynamicsPanel/VBoxContainer/LimitContainer/SizeMin" to="." method="_on_SizeMin_value_changed"]
|
||||||
|
|
Loading…
Reference in a new issue