1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-01-18 17:19:50 +00:00

Add a preference to share options between tools (#1120)

* Add share config button

* fill parameter now saves with curve tool

* rename _fill to _fill_inside for sync consistency (fill in pencil and shape tools basically represent the same thing)

* add icon

* Move the option to the preferences

* Add string to Translations.pot

* Re-introduce `is_syncing`

---------

Co-authored-by: Emmanouil Papadeas <35376950+OverloadedOrama@users.noreply.github.com>
This commit is contained in:
Variable 2024-10-16 18:00:20 +05:00 committed by GitHub
parent 1ae34bf57a
commit 3863cbaee7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 141 additions and 41 deletions

View file

@ -898,6 +898,10 @@ msgstr ""
msgid "Background color:"
msgstr ""
#. Found in the preferences, under the Tools category.
msgid "Share options between the left and the right tools"
msgstr ""
msgid "Left tool color:"
msgstr ""

View file

@ -276,6 +276,10 @@ var tool_button_size := ButtonSize.SMALL:
return
tool_button_size = value
Tools.set_button_size(tool_button_size)
var share_options_between_tools := false:
set(value):
share_options_between_tools = value
Tools.attempt_config_share(MOUSE_BUTTON_LEFT)
## Found in Preferences. The left tool color.
var left_tool_color := Color("0086cf"):
set(value):

View file

@ -2,6 +2,8 @@
extends Node
signal color_changed(color: Color, button: int)
signal config_changed(slot_idx: int, config: Dictionary)
@warning_ignore("unused_signal")
signal flip_rotated(flip_x, flip_y, rotate_90, rotate_180, rotate_270)
signal options_reset
@ -373,6 +375,34 @@ func _ready() -> void:
_show_relevant_tools(layer_type)
## Syncs the other tool using the config of tool located at [param from_idx].[br]
## NOTE: For optimization, if there is already a ready made config available, then we will use that
## instead of re-calculating the config, else we have no choice but to re-generate it
func attempt_config_share(from_idx: int, config: Dictionary = {}) -> void:
if not Global.share_options_between_tools:
return
if _slots.is_empty():
return
if config.is_empty() and _slots[from_idx]:
var from_slot: Slot = _slots.get(from_idx, null)
if from_slot:
var from_tool = from_slot.tool_node
if from_tool.has_method("get_config"):
config = from_tool.get_config()
var target_slot: Slot = _slots.get(MOUSE_BUTTON_LEFT, null)
if from_idx == MOUSE_BUTTON_LEFT:
target_slot = _slots.get(MOUSE_BUTTON_RIGHT, null)
if is_instance_valid(target_slot):
if (
target_slot.tool_node.has_method("set_config")
and target_slot.tool_node.has_method("update_config")
):
target_slot.tool_node.set("is_syncing", true)
target_slot.tool_node.set_config(config)
target_slot.tool_node.update_config()
target_slot.tool_node.set("is_syncing", false)
func reset_options() -> void:
default_color()
assign_tool(get_tool(MOUSE_BUTTON_LEFT).tool_node.name, MOUSE_BUTTON_LEFT, true)
@ -401,9 +431,13 @@ func remove_tool(t: Tool) -> void:
func set_tool(tool_name: String, button: int) -> void:
# To prevent any unintentional syncing, we will temporarily disconnect the signal
if config_changed.is_connected(attempt_config_share):
config_changed.disconnect(attempt_config_share)
var slot: Slot = _slots[button]
var panel: Node = _panels[button]
var node: Node = tools[tool_name].instantiate_scene()
var config_slot := MOUSE_BUTTON_LEFT if button == MOUSE_BUTTON_RIGHT else MOUSE_BUTTON_RIGHT
if button == MOUSE_BUTTON_LEFT: # As guides are only moved with left mouse
if tool_name == "Pan": # tool you want to give more access at guides
Global.move_guides_on_canvas = true
@ -422,6 +456,12 @@ func set_tool(tool_name: String, button: int) -> void:
elif button == MOUSE_BUTTON_RIGHT:
_right_tools_per_layer_type[_curr_layer_type] = tool_name
# Wait for config to get loaded, then re-connect and sync
await get_tree().process_frame
if not config_changed.is_connected(attempt_config_share):
config_changed.connect(attempt_config_share)
attempt_config_share(config_slot) # Sync it with the other tool
func get_tool(button: int) -> Slot:
return _slots[button]

View file

@ -36,10 +36,16 @@ var preferences: Array[Preference] = [
"custom_icon_color", "Interface/ButtonOptions/IconColorButton", "color", Color.GRAY
),
Preference.new(
"left_tool_color", "Interface/ButtonOptions/LeftToolColorButton", "color", Color("0086cf")
"share_options_between_tools",
"Tools/ToolOptions/ShareOptionsCheckBox",
"button_pressed",
false
),
Preference.new(
"right_tool_color", "Interface/ButtonOptions/RightToolColorButton", "color", Color("fd6d14")
"left_tool_color", "Tools/ToolOptions/LeftToolColorButton", "color", Color("0086cf")
),
Preference.new(
"right_tool_color", "Tools/ToolOptions/RightToolColorButton", "color", Color("fd6d14")
),
Preference.new(
"tool_button_size",

View file

@ -324,26 +324,6 @@ layout_mode = 2
mouse_default_cursor_shape = 2
color = Color(0.75, 0.75, 0.75, 1)
[node name="Label4" type="Label" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Interface/ButtonOptions"]
layout_mode = 2
text = "Left tool color:"
[node name="LeftToolColorButton" type="ColorPickerButton" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Interface/ButtonOptions"]
custom_minimum_size = Vector2(64, 20)
layout_mode = 2
mouse_default_cursor_shape = 2
color = Color(0, 0.52549, 0.811765, 1)
[node name="Label5" type="Label" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Interface/ButtonOptions"]
layout_mode = 2
text = "Right tool color:"
[node name="RightToolColorButton" type="ColorPickerButton" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Interface/ButtonOptions"]
custom_minimum_size = Vector2(64, 20)
layout_mode = 2
mouse_default_cursor_shape = 2
color = Color(0.992157, 0.427451, 0.0784314, 1)
[node name="Canvas" type="VBoxContainer" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide"]
visible = false
layout_mode = 2
@ -875,6 +855,49 @@ layout_mode = 2
mouse_default_cursor_shape = 2
color = Color(0, 0, 1, 1)
[node name="Tools" type="VBoxContainer" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide"]
visible = false
layout_mode = 2
[node name="ToolOptions" type="GridContainer" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Tools"]
layout_mode = 2
columns = 3
[node name="ShareOptionsLabel" type="Label" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Tools/ToolOptions"]
layout_mode = 2
size_flags_horizontal = 3
text = "Share options between the left and the right tools"
[node name="ShareOptionsCheckBox" type="CheckBox" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Tools/ToolOptions"]
layout_mode = 2
size_flags_horizontal = 3
mouse_default_cursor_shape = 2
text = "On"
[node name="LeftToolColorLabel" type="Label" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Tools/ToolOptions"]
layout_mode = 2
size_flags_horizontal = 3
text = "Left tool color:"
[node name="LeftToolColorButton" type="ColorPickerButton" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Tools/ToolOptions"]
custom_minimum_size = Vector2(64, 20)
layout_mode = 2
size_flags_horizontal = 3
mouse_default_cursor_shape = 2
color = Color(0, 0.52549, 0.811765, 1)
[node name="RightToolColorLabel" type="Label" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Tools/ToolOptions"]
layout_mode = 2
size_flags_horizontal = 3
text = "Right tool color:"
[node name="RightToolColorButton" type="ColorPickerButton" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Tools/ToolOptions"]
custom_minimum_size = Vector2(64, 20)
layout_mode = 2
size_flags_horizontal = 3
mouse_default_cursor_shape = 2
color = Color(0.992157, 0.427451, 0.0784314, 1)
[node name="Selection" type="VBoxContainer" parent="HSplitContainer/VBoxContainer/ScrollContainer/RightSide"]
visible = false
layout_mode = 2

View file

@ -71,14 +71,13 @@ func _on_Brush_selected(brush: Brushes.Brush) -> void:
func _on_BrushSize_value_changed(value: float) -> void:
if _brush_size != int(value):
_brush_size = int(value)
_brush_size_dynamics = _brush_size
if Tools.dynamics_size != Tools.Dynamics.NONE:
_brush_size_dynamics = Tools.brush_size_min
_cache_limit = (_brush_size * _brush_size) * 3 # This equation seems the best match
update_config()
save_config()
_brush_size = int(value)
_brush_size_dynamics = _brush_size
if Tools.dynamics_size != Tools.Dynamics.NONE:
_brush_size_dynamics = Tools.brush_size_min
_cache_limit = (_brush_size * _brush_size) * 3 # This equation seems the best match
update_config()
save_config()
func _reset_dynamics() -> void:
@ -113,6 +112,11 @@ func get_config() -> Dictionary:
"brush_index": _brush.index,
"brush_size": _brush_size,
"brush_interpolate": _brush_interpolate,
"brush_flip_x": _brush_flip_x,
"brush_flip_y": _brush_flip_y,
"brush_rotate_90": _brush_rotate_90,
"brush_rotate_180": _brush_rotate_180,
"brush_rotate_270": _brush_rotate_270,
}
@ -125,6 +129,11 @@ func set_config(config: Dictionary) -> void:
if Tools.dynamics_size != Tools.Dynamics.NONE:
_brush_size_dynamics = Tools.brush_size_min
_brush_interpolate = config.get("brush_interpolate", _brush_interpolate)
_brush_flip_x = config.get("brush_flip_x", _brush_flip_x)
_brush_flip_y = config.get("brush_flip_y", _brush_flip_y)
_brush_rotate_90 = config.get("brush_rotate_90", _brush_rotate_90)
_brush_rotate_180 = config.get("brush_rotate_180", _brush_rotate_180)
_brush_rotate_270 = config.get("brush_rotate_270", _brush_rotate_270)
func update_config() -> void:
@ -743,23 +752,28 @@ func _pick_color(pos: Vector2i) -> void:
func _on_flip_x_toggled(button_pressed: bool) -> void:
_brush_flip_x = button_pressed
update_brush()
save_config()
func _on_flip_y_toggled(button_pressed: bool) -> void:
_brush_flip_y = button_pressed
update_brush()
save_config()
func _on_rotate_90_toggled(button_pressed: bool) -> void:
_brush_rotate_90 = button_pressed
update_brush()
save_config()
func _on_rotate_180_toggled(button_pressed: bool) -> void:
_brush_rotate_180 = button_pressed
update_brush()
save_config()
func _on_rotate_270_toggled(button_pressed: bool) -> void:
_brush_rotate_270 = button_pressed
update_brush()
save_config()

View file

@ -3,7 +3,7 @@ extends "res://src/Tools/BaseDraw.gd"
var _start := Vector2i.ZERO
var _offset := Vector2i.ZERO
var _dest := Vector2i.ZERO
var _fill := false
var _fill_inside := false
var _drawing := false
var _displace_origin := false
var _thickness := 1
@ -41,27 +41,27 @@ func update_indicator() -> void:
func _on_FillCheckbox_toggled(button_pressed: bool) -> void:
_fill = button_pressed
_fill_inside = button_pressed
update_config()
save_config()
func get_config() -> Dictionary:
var config := super.get_config()
config["fill"] = _fill
config["fill_inside"] = _fill_inside
config["thickness"] = _thickness
return config
func set_config(config: Dictionary) -> void:
super.set_config(config)
_fill = config.get("fill", _fill)
_fill_inside = config.get("fill_inside", _fill_inside)
_thickness = config.get("thickness", _thickness)
func update_config() -> void:
super.update_config()
$FillCheckbox.button_pressed = _fill
$FillCheckbox.button_pressed = _fill_inside
$ThicknessSlider.value = _thickness
@ -237,7 +237,7 @@ func _get_result_rect(origin: Vector2i, dest: Vector2i) -> Rect2i:
func _get_points(shape_size: Vector2i) -> Array[Vector2i]:
return _get_shape_points_filled(shape_size) if _fill else _get_shape_points(shape_size)
return _get_shape_points_filled(shape_size) if _fill_inside else _get_shape_points(shape_size)
func _set_cursor_text(rect: Rect2i) -> void:

View file

@ -2,6 +2,7 @@ class_name BaseTool
extends VBoxContainer
var is_moving := false
var is_syncing := false
var kname: String
var tool_slot: Tools.Slot = null
var cursor_text := ""
@ -34,6 +35,8 @@ func _ready() -> void:
func save_config() -> void:
var config := get_config()
Global.config_cache.set_value(tool_slot.kname, kname, config)
if not is_syncing: # If the tool isn't busy syncing with another tool.
Tools.config_changed.emit(tool_slot.button, config)
func load_config() -> void:

View file

@ -2,7 +2,7 @@ extends "res://src/Tools/BaseDraw.gd"
var _curve := Curve2D.new() ## The [Curve2D] responsible for the shape of the curve being drawn.
var _drawing := false ## Set to true when a curve is being drawn.
var _fill := false ## When true, the inside area of the curve gets filled.
var _fill_inside := false ## When true, the inside area of the curve gets filled.
var _fill_inside_rect := Rect2i() ## The bounding box that surrounds the area that gets filled.
var _editing_bezier := false ## Needed to determine when to show the control points preview line.
var _editing_out_control_point := false ## True when controlling the out control point only.
@ -29,7 +29,7 @@ func _on_thickness_value_changed(value: int) -> void:
func _on_fill_checkbox_toggled(toggled_on: bool) -> void:
_fill = toggled_on
_fill_inside = toggled_on
update_config()
save_config()
@ -44,17 +44,20 @@ func update_indicator() -> void:
func get_config() -> Dictionary:
var config := super.get_config()
config["fill_inside"] = _fill_inside
config["thickness"] = _thickness
return config
func set_config(config: Dictionary) -> void:
super.set_config(config)
_fill_inside = config.get("fill_inside", _fill_inside)
_thickness = config.get("thickness", _thickness)
func update_config() -> void:
super.update_config()
$FillCheckbox.button_pressed = _fill_inside
$ThicknessSlider.value = _thickness
@ -188,7 +191,7 @@ func _draw_shape() -> void:
_fill_inside_rect = _fill_inside_rect.expand(point)
# Draw each point offsetted based on the shape's thickness
_draw_pixel(point, images)
if _fill:
if _fill_inside:
var v := Vector2i()
for x in _fill_inside_rect.size.x:
v.x = x + _fill_inside_rect.position.x

View file

@ -50,6 +50,7 @@ func _on_SpacingMode_toggled(button_pressed: bool) -> void:
func _on_Spacing_value_changed(value: Vector2) -> void:
_spacing = value
save_config()
func _input(event: InputEvent) -> void:
@ -58,10 +59,10 @@ func _input(event: InputEvent) -> void:
if event.is_action_pressed("change_tool_mode"):
_prev_mode = overwrite_button.button_pressed
if event.is_action("change_tool_mode"):
overwrite_button.button_pressed = !_prev_mode
overwrite_button.set_pressed_no_signal(!_prev_mode)
_overwrite = overwrite_button.button_pressed
if event.is_action_released("change_tool_mode"):
overwrite_button.button_pressed = _prev_mode
overwrite_button.set_pressed_no_signal(_prev_mode)
_overwrite = overwrite_button.button_pressed

View file

@ -105,6 +105,8 @@ anchor_bottom = 0.5
offset_left = -22.0
offset_top = -10.0
offset_bottom = 10.0
grow_horizontal = 0
grow_vertical = 2
mouse_default_cursor_shape = 2
item_count = 2
popup/item_0/text = "Move to canvas center"