diff --git a/lorien/InfiniteCanvas/Cursor/ColorPickerCursor/ColorPickerCursor.gd b/lorien/InfiniteCanvas/Cursor/ColorPickerCursor/ColorPickerCursor.gd new file mode 100644 index 00000000..54d7fee4 --- /dev/null +++ b/lorien/InfiniteCanvas/Cursor/ColorPickerCursor/ColorPickerCursor.gd @@ -0,0 +1,6 @@ +class_name ColorPickerCursor +extends BaseCursor + +# ------------------------------------------------------------------------------------------------- +func _on_zoom_changed(zoom_value: float) -> void: + scale = Vector2.ONE / zoom_value diff --git a/lorien/InfiniteCanvas/Cursor/ColorPickerCursor/ColorPickerCursor.tscn b/lorien/InfiniteCanvas/Cursor/ColorPickerCursor/ColorPickerCursor.tscn new file mode 100644 index 00000000..5772eca6 --- /dev/null +++ b/lorien/InfiniteCanvas/Cursor/ColorPickerCursor/ColorPickerCursor.tscn @@ -0,0 +1,16 @@ +[gd_scene load_steps=5 format=3 uid="uid://dmybbclki2clv"] + +[ext_resource type="Shader" path="res://InfiniteCanvas/Cursor/cursor.gdshader" id="1_q5575"] +[ext_resource type="Script" path="res://InfiniteCanvas/Cursor/ColorPickerCursor/ColorPickerCursor.gd" id="2_labi7"] +[ext_resource type="Texture2D" uid="uid://tcovt1vw06tr" path="res://Assets/Icons/color_picker.png" id="3_rydea"] + +[sub_resource type="ShaderMaterial" id="1"] +shader = ExtResource("1_q5575") + +[node name="ColorPickerCursor" type="Sprite2D"] +material = SubResource("1") +script = ExtResource("2_labi7") + +[node name="Sprite2D" type="Sprite2D" parent="."] +position = Vector2(7, -7) +texture = ExtResource("3_rydea") diff --git a/lorien/InfiniteCanvas/InfiniteCanvas.gd b/lorien/InfiniteCanvas/InfiniteCanvas.gd index bab70818..1f9fd06d 100644 --- a/lorien/InfiniteCanvas/InfiniteCanvas.gd +++ b/lorien/InfiniteCanvas/InfiniteCanvas.gd @@ -12,6 +12,7 @@ const PLAYER = preload("res://Misc/Player/Player.tscn") @onready var _circle_tool: CircleTool = $CircleTool @onready var _eraser_tool: EraserTool = $EraserTool @onready var _selection_tool: SelectionTool = $SelectionTool +@onready var _color_picker_tool: ColorPickerTool = $ColorPickerTool @onready var _active_tool: CanvasTool = _brush_tool @onready var _active_tool_type: int = Types.Tool.BRUSH @onready var _strokes_parent: Node2D = $SubViewport/Strokes @@ -88,6 +89,16 @@ func _process_event(event: InputEvent) -> void: else: # restore tool from type use_tool(_active_tool_type) + + if event is InputEventKey: + var keyEvent := event as InputEventKey + if keyEvent.keycode == KEY_CTRL: + if keyEvent.pressed: + var tool_type := _active_tool_type + use_tool(Types.Tool.COLOR_PICKER) + _active_tool_type = tool_type + else: + use_tool(_active_tool_type) if event.is_action("deselect_all_strokes"): if _active_tool == _selection_tool: @@ -133,6 +144,10 @@ func use_tool(tool_type: int) -> void: Types.Tool.SELECT: _active_tool = _selection_tool _use_optimizer = false + Types.Tool.COLOR_PICKER: + _active_tool = _color_picker_tool + _use_optimizer = false + if prev_tool != _active_tool: prev_tool.enabled = false diff --git a/lorien/InfiniteCanvas/InfiniteCanvas.tscn b/lorien/InfiniteCanvas/InfiniteCanvas.tscn index c0a94fdb..a40ddfcb 100644 --- a/lorien/InfiniteCanvas/InfiniteCanvas.tscn +++ b/lorien/InfiniteCanvas/InfiniteCanvas.tscn @@ -9,12 +9,14 @@ [ext_resource type="Script" path="res://InfiniteCanvas/Tools/SelectionTool.gd" id="7"] [ext_resource type="PackedScene" path="res://InfiniteCanvas/Cursor/SelectionCursor/SelectionCursor.tscn" id="8"] [ext_resource type="Script" path="res://InfiniteCanvas/Tools/SelectionRectangle.gd" id="9"] +[ext_resource type="Script" path="res://InfiniteCanvas/Tools/ColorPickerTool.gd" id="9_xqyd5"] [ext_resource type="Shader" path="res://InfiniteCanvas/Tools/selection_rectangle.gdshader" id="10"] [ext_resource type="Script" path="res://InfiniteCanvas/Tools/RectangleTool.gd" id="11"] [ext_resource type="Script" path="res://InfiniteCanvas/InfiniteCanvasGrid.gd" id="12"] [ext_resource type="Script" path="res://InfiniteCanvas/Tools/CircleTool.gd" id="13"] [ext_resource type="Script" path="res://InfiniteCanvas/Tools/EraserTool.gd" id="14"] [ext_resource type="Script" path="res://InfiniteCanvas/DebugDraw.gd" id="15"] +[ext_resource type="PackedScene" uid="uid://dmybbclki2clv" path="res://InfiniteCanvas/Cursor/ColorPickerCursor/ColorPickerCursor.tscn" id="16_mifpa"] [sub_resource type="ShaderMaterial" id="1"] shader = ExtResource("10") @@ -55,6 +57,10 @@ script = ExtResource("7") selection_rectangle_path = NodePath("../SubViewport/SelectionRectangle") cursor_path = NodePath("../SubViewport/SelectionCursor") +[node name="ColorPickerTool" type="Node" parent="."] +script = ExtResource("9_xqyd5") +cursor_path = NodePath("../SubViewport/ColorPickerCursor") + [node name="SubViewport" type="SubViewport" parent="."] handle_input_locally = false size = Vector2i(1920, 1080) @@ -80,3 +86,5 @@ script = ExtResource("9") [node name="BrushCursor" parent="SubViewport" instance=ExtResource("4")] [node name="SelectionCursor" parent="SubViewport" instance=ExtResource("8")] + +[node name="ColorPickerCursor" parent="SubViewport" instance=ExtResource("16_mifpa")] diff --git a/lorien/InfiniteCanvas/Tools/ColorPickerTool.gd b/lorien/InfiniteCanvas/Tools/ColorPickerTool.gd new file mode 100644 index 00000000..4dc4ab96 --- /dev/null +++ b/lorien/InfiniteCanvas/Tools/ColorPickerTool.gd @@ -0,0 +1,33 @@ +class_name ColorPickerTool extends CanvasTool + + +# ------------------------------------------------------------------------------------------------- +func tool_event(event: InputEvent) -> void: + if ( + event is InputEventMouseButton + && event.button_index == MOUSE_BUTTON_LEFT + && event.is_pressed() + ): + var mouseEvent := event as InputEventMouseButton + var picked_color := _pick_color(mouseEvent.position) + if picked_color != Color.TRANSPARENT: + GlobalSignals.color_changed.emit(picked_color) + + +# ------------------------------------------------------------------------------------------------- +func _pick_color(pos: Vector2) -> Color: + var colorPicked := _canvas._viewport.get_texture().get_image().get_pixel(pos.x, pos.y) + # the exact color picked may be a hue of the original stroke because of antialiasing + # to fix this, search along every stroke for the color that has an more equal color the picked one + var minDelta := 0.5 + var bestColorMatch := Color.TRANSPARENT + var strokes := _canvas.get_all_strokes() + for stroke in strokes: + var c := stroke.color + var colorDelta: float = ( + abs(colorPicked.r - c.r) + abs(colorPicked.g - c.g) + abs(colorPicked.b - c.b) + ) + if colorDelta < minDelta: + bestColorMatch = c + minDelta = colorDelta + return bestColorMatch diff --git a/lorien/Main.gd b/lorien/Main.gd index 9d6d2c7a..f5b67ee2 100644 --- a/lorien/Main.gd +++ b/lorien/Main.gd @@ -52,6 +52,7 @@ func _ready() -> void: _brush_color_picker.closed.connect(_on_BrushColorPicker_closed) _brush_color_picker.color_changed.connect(_on_BrushColorPicker_color_changed) + GlobalSignals.connect("color_changed", self._on_BrushColorPicker_color_changed) _new_palette_dialog.new_palette_created.connect(_on_NewPaletteDialog_new_palette_created) _delete_palette_dialog.palette_deleted.connect(_on_DeletePaletteDialog_palette_deleted) diff --git a/lorien/Misc/GlobalSignals.gd b/lorien/Misc/GlobalSignals.gd index eec8aa1c..b1c9b8e9 100644 --- a/lorien/Misc/GlobalSignals.gd +++ b/lorien/Misc/GlobalSignals.gd @@ -3,3 +3,4 @@ extends Node # ------------------------------------------------------------------------------------------------- signal language_changed signal keybinding_changed(action: KeybindingsManager.Action) +signal color_changed(color: Color) diff --git a/lorien/Misc/Types.gd b/lorien/Misc/Types.gd index 46013c36..0da85497 100644 --- a/lorien/Misc/Types.gd +++ b/lorien/Misc/Types.gd @@ -9,6 +9,7 @@ enum Tool { LINE, ERASER, SELECT, + COLOR_PICKER } # -------------------------------------------------------------------------------------------------