diff --git a/src/Autoload/ExtensionsApi.gd b/src/Autoload/ExtensionsApi.gd index 93b8a8897d3..2ef1820aaed 100644 --- a/src/Autoload/ExtensionsApi.gd +++ b/src/Autoload/ExtensionsApi.gd @@ -896,7 +896,7 @@ class SignalsAPI: # TOOL RELATED SIGNALS ## Connects/disconnects a signal to [param callable], that emits ## whenever a tool changes color.[br] - ## [b]Binds: [/b] It has two bind of type [Color] (indicating new color) + ## [b]Binds: [/b] It has two bind of type [Color] (a dictionary with keys "color" and "index") ## and [int] (Indicating button that tool is assigned to, see [enum @GlobalScope.MouseButton]) func signal_tool_color_changed(callable: Callable, is_disconnecting := false) -> void: _connect_disconnect(Tools.color_changed, callable, is_disconnecting) diff --git a/src/Autoload/Palettes.gd b/src/Autoload/Palettes.gd index 9e3a1ad9cd7..b24e060909c 100644 --- a/src/Autoload/Palettes.gd +++ b/src/Autoload/Palettes.gd @@ -300,9 +300,9 @@ func current_palette_select_color(mouse_button: int, index: int) -> void: match mouse_button: MOUSE_BUTTON_LEFT: - Tools.assign_color(color, mouse_button) + Tools.assign_color(color, mouse_button, true, left_selected_color) MOUSE_BUTTON_RIGHT: - Tools.assign_color(color, mouse_button) + Tools.assign_color(color, mouse_button, true, right_selected_color) func _select_color(mouse_button: int, index: int) -> void: diff --git a/src/Autoload/Tools.gd b/src/Autoload/Tools.gd index 48a0c3170e8..3a79882e1ae 100644 --- a/src/Autoload/Tools.gd +++ b/src/Autoload/Tools.gd @@ -1,7 +1,7 @@ # gdlint: ignore=max-public-methods extends Node -signal color_changed(color: Color, button: int) +signal color_changed(color_info: Dictionary, 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) @@ -509,7 +509,7 @@ func swap_color() -> void: assign_color(left, MOUSE_BUTTON_RIGHT, false) -func assign_color(color: Color, button: int, change_alpha := true) -> void: +func assign_color(color: Color, button: int, change_alpha := true, index: int = -1) -> void: var c: Color = _slots[button].color # This was requested by Issue #54 on GitHub if color.a == 0 and change_alpha: @@ -517,7 +517,8 @@ func assign_color(color: Color, button: int, change_alpha := true) -> void: color.a = 1 _slots[button].color = color Global.config_cache.set_value(_slots[button].kname, "color", color) - color_changed.emit(color, button) + var color_info := {"color": color, "index": index} + color_changed.emit(color_info, button) func get_assigned_color(button: int) -> Color: diff --git a/src/Classes/Drawers.gd b/src/Classes/Drawers.gd index caa005ebf36..bd021e01dfb 100644 --- a/src/Classes/Drawers.gd +++ b/src/Classes/Drawers.gd @@ -30,6 +30,8 @@ class SimpleDrawer: var color_new := op.process(Color(color_str), color_old) if not color_new.is_equal_approx(color_old): image.set_pixelv_custom(position, color_new) + else: + image.set_pixelv_custom(position, color_new, image.is_indexed) class PixelPerfectDrawer: diff --git a/src/Classes/ImageExtended.gd b/src/Classes/ImageExtended.gd index 338364729aa..fe79414eeea 100644 --- a/src/Classes/ImageExtended.gd +++ b/src/Classes/ImageExtended.gd @@ -139,7 +139,7 @@ func set_pixel_custom(x: int, y: int, color: Color) -> void: ## Equivalent of [method Image.set_pixelv], ## but also handles the logic necessary for indexed mode. -func set_pixelv_custom(point: Vector2i, color: Color) -> void: +func set_pixelv_custom(point: Vector2i, color: Color, index_image_only := false) -> void: var new_color := color if is_indexed: var color_to_fill := TRANSPARENT @@ -164,13 +164,15 @@ func set_pixelv_custom(point: Vector2i, color: Color) -> void: if dist < smaller_distance: smaller_distance = dist color_index = i - indices_image.set_pixelv(point, Color((color_index + 1) / 255.0, 0, 0, 0)) + if not indices_image.get_pixelv(point).r8 == color_index + 1: + indices_image.set_pixelv(point, Color((color_index + 1) / 255.0, 0, 0, 0)) color_to_fill = palette[color_index] new_color = color_to_fill else: indices_image.set_pixelv(point, TRANSPARENT) new_color = TRANSPARENT - set_pixelv(point, new_color) + if not index_image_only: + set_pixelv(point, new_color) ## Finds the distance between colors [param c1] and [param c2]. diff --git a/src/Palette/PaletteGrid.gd b/src/Palette/PaletteGrid.gd index abe89448246..89b4633fbf6 100644 --- a/src/Palette/PaletteGrid.gd +++ b/src/Palette/PaletteGrid.gd @@ -83,25 +83,38 @@ func scroll_palette(origin: Vector2i) -> void: ## Called when the color changes, either the left or the right, determined by [param mouse_button]. ## If current palette has [param target_color] as a [Color], then select it. ## This is helpful when we select color indirectly (e.g through colorpicker) -func find_and_select_color(target_color: Color, mouse_button: int) -> void: +func find_and_select_color(color_info: Dictionary, mouse_button: int) -> void: + var target_color: Color = color_info.get("color", Color(0, 0, 0, 0)) + var palette_color_index: int = color_info.get("index", -1) if not is_instance_valid(current_palette): return var selected_index := Palettes.current_palette_get_selected_color_index(mouse_button) - if get_swatch_color(selected_index) == target_color: # Color already selected + if palette_color_index != -1: # If color has a defined index in palette then priortize index + if selected_index == palette_color_index: # Index already selected + return + select_swatch(mouse_button, palette_color_index, selected_index) + match mouse_button: + MOUSE_BUTTON_LEFT: + Palettes.left_selected_color = palette_color_index + MOUSE_BUTTON_RIGHT: + Palettes.right_selected_color = palette_color_index return - for color_ind in swatches.size(): - if ( - target_color.is_equal_approx(swatches[color_ind].color) - or target_color.to_html() == swatches[color_ind].color.to_html() - ): - var index := convert_grid_index_to_palette_index(color_ind) - select_swatch(mouse_button, index, selected_index) - match mouse_button: - MOUSE_BUTTON_LEFT: - Palettes.left_selected_color = index - MOUSE_BUTTON_RIGHT: - Palettes.right_selected_color = index + else: # If it doesn't then select the first match in the palette + if get_swatch_color(selected_index) == target_color: # Color already selected return + for color_ind in swatches.size(): + if ( + target_color.is_equal_approx(swatches[color_ind].color) + or target_color.to_html() == swatches[color_ind].color.to_html() + ): + var index := convert_grid_index_to_palette_index(color_ind) + select_swatch(mouse_button, index, selected_index) + match mouse_button: + MOUSE_BUTTON_LEFT: + Palettes.left_selected_color = index + MOUSE_BUTTON_RIGHT: + Palettes.right_selected_color = index + return # Unselect swatches when tools color is changed var swatch_to_unselect := -1 if mouse_button == MOUSE_BUTTON_LEFT: diff --git a/src/Tools/BaseDraw.gd b/src/Tools/BaseDraw.gd index a045aeb2005..2a1e74f016b 100644 --- a/src/Tools/BaseDraw.gd +++ b/src/Tools/BaseDraw.gd @@ -104,7 +104,7 @@ func _on_InterpolateFactor_value_changed(value: float) -> void: save_config() -func _on_Color_changed(_color: Color, _button: int) -> void: +func _on_Color_changed(_color_info: Dictionary, _button: int) -> void: update_brush() diff --git a/src/Tools/BaseTool.gd b/src/Tools/BaseTool.gd index 27fbf48e388..73baaac0cef 100644 --- a/src/Tools/BaseTool.gd +++ b/src/Tools/BaseTool.gd @@ -347,15 +347,21 @@ func _pick_color(pos: Vector2i) -> void: return var color := Color(0, 0, 0, 0) + var palette_index = -1 var curr_frame: Frame = project.frames[project.current_frame] for layer in project.layers.size(): var idx := (project.layers.size() - 1) - layer if project.layers[idx].is_visible_in_hierarchy(): - image = curr_frame.cels[idx].get_image() + var cel := curr_frame.cels[idx] + image = cel.get_image() color = image.get_pixelv(pos) - if not is_zero_approx(color.a): + # If image is indexed then get index as well + if cel is PixelCel: + if cel.image.is_indexed: + palette_index = cel.image.indices_image.get_pixel(pos.x, pos.y).r8 - 1 + if not is_zero_approx(color.a) or palette_index > -1: break - Tools.assign_color(color, tool_slot.button, false) + Tools.assign_color(color, tool_slot.button, false, palette_index) func _flip_rect(rect: Rect2, rect_size: Vector2, horiz: bool, vert: bool) -> Rect2: diff --git a/src/Tools/DesignTools/Shading.gd b/src/Tools/DesignTools/Shading.gd index e18ce0615ef..74faea35a38 100644 --- a/src/Tools/DesignTools/Shading.gd +++ b/src/Tools/DesignTools/Shading.gd @@ -324,8 +324,8 @@ func update_brush() -> void: $ColorInterpolation.visible = false -## this function is also used by a signal, this is why there is _color = Color.TRANSPARENT in here. -func _refresh_colors_array(_color = Color.TRANSPARENT, mouse_button := tool_slot.button) -> void: +## this function is also used by a signal, this is why there is _color_info = {} in here. +func _refresh_colors_array(_color_info = {}, mouse_button := tool_slot.button) -> void: if mouse_button != tool_slot.button: return if _shading_mode == ShadingMode.COLOR_REPLACE: diff --git a/src/Tools/UtilityTools/ColorPicker.gd b/src/Tools/UtilityTools/ColorPicker.gd index f77cf2e05f3..d04f705024e 100644 --- a/src/Tools/UtilityTools/ColorPicker.gd +++ b/src/Tools/UtilityTools/ColorPicker.gd @@ -67,22 +67,33 @@ func _pick_color(pos: Vector2i) -> void: if pos.x < 0 or pos.y < 0: return - var color := Color(0, 0, 0, 0) var image := Image.new() image.copy_from(_get_draw_image()) if pos.x > image.get_width() - 1 or pos.y > image.get_height() - 1: return + + var color := Color(0, 0, 0, 0) + var palette_index = -1 match _mode: TOP_COLOR: var curr_frame := project.frames[project.current_frame] for layer in project.layers.size(): var idx := (project.layers.size() - 1) - layer if project.layers[idx].is_visible_in_hierarchy(): - image = curr_frame.cels[idx].get_image() + var cel := curr_frame.cels[idx] + image = cel.get_image() color = image.get_pixelv(pos) + # If image is indexed then get index as well + if cel is PixelCel: + if cel.image.is_indexed: + palette_index = cel.image.indices_image.get_pixel(pos.x, pos.y).r8 - 1 if not is_zero_approx(color.a): break CURRENT_LAYER: color = image.get_pixelv(pos) + var current_cel = Global.current_project.get_current_cel() + if current_cel is PixelCel: + if current_cel.image.is_indexed: + palette_index = current_cel.image.index_image.get_pixel(pos.x, pos.y).r8 - 1 var button := MOUSE_BUTTON_LEFT if _color_slot == 0 else MOUSE_BUTTON_RIGHT - Tools.assign_color(color, button, false) + Tools.assign_color(color, button, false, palette_index) diff --git a/src/Tools/UtilityTools/Text.gd b/src/Tools/UtilityTools/Text.gd index 3a96b4189d2..b1128de663f 100644 --- a/src/Tools/UtilityTools/Text.gd +++ b/src/Tools/UtilityTools/Text.gd @@ -204,7 +204,7 @@ func _textedit_text_changed() -> void: text_edit._on_text_changed() -func _on_color_changed(_color: Color, _button: int) -> void: +func _on_color_changed(_color_info: Dictionary, _button: int) -> void: if is_instance_valid(text_edit): text_edit.add_theme_color_override(&"font_color", tool_slot.color) diff --git a/src/UI/Canvas/color_index.gd b/src/UI/Canvas/color_index.gd index a7804ab71d0..098c72ce02f 100644 --- a/src/UI/Canvas/color_index.gd +++ b/src/UI/Canvas/color_index.gd @@ -23,23 +23,18 @@ func _draw() -> void: if zoom_percentage < Global.pixel_grid_show_at_zoom: return var project = ExtensionsApi.project.current_project + var size: Vector2i = project.size var cel: BaseCel = project.frames[project.current_frame].cels[project.current_layer] if not cel is PixelCel: return var index_image: Image = cel.image.indices_image - if index_image.get_size() != project.size or not cel.image.is_indexed: + if index_image.get_size() != size or not cel.image.is_indexed: return - var used_rect: Rect2i = cel.image.get_used_rect() - if used_rect.size != Vector2i.ZERO: - # use smaller image for optimization - index_image = index_image.get_region(used_rect) - var font: Font = ExtensionsApi.theme.get_theme().default_font - var offset = position + Vector2(used_rect.position) - draw_set_transform(offset, rotation, Vector2(0.05, 0.05)) - for x in range(index_image.get_size().x): - for y in range(index_image.get_size().y): + draw_set_transform(position, rotation, Vector2(0.05, 0.05)) + for x in range(size.x): + for y in range(size.y): var index := index_image.get_pixel(x, y).r8 if index == 0: continue diff --git a/src/UI/ColorPickers/ColorPicker.gd b/src/UI/ColorPickers/ColorPicker.gd index 0a95997637e..3dcae76f2cd 100644 --- a/src/UI/ColorPickers/ColorPicker.gd +++ b/src/UI/ColorPickers/ColorPicker.gd @@ -128,7 +128,8 @@ func reset_options() -> void: expand_button.button_pressed = false -func update_color(color: Color, button: int) -> void: +func update_color(color_info: Dictionary, button: int) -> void: + var color = color_info.get("color", Color.WHITE) if Tools.picking_color_for == button: color_picker.color = color if button == MOUSE_BUTTON_RIGHT: