extends "res://src/Tools/Draw.gd" var _prev_mode := false var _last_position := Vector2i(Vector2.INF) var _changed := false var _overwrite := false var _fill_inside := false var _draw_points := PackedVector2Array() var _old_spacing_mode := false ## Needed to reset spacing mode in case we change it class PencilOp: extends Drawer.ColorOp var changed := false var overwrite := false func process(src: Color, dst: Color) -> Color: changed = true src.a *= strength if overwrite: return src return dst.blend(src) func _init() -> void: _drawer.color_op = PencilOp.new() func _on_Overwrite_toggled(button_pressed: bool) -> void: _overwrite = button_pressed update_config() save_config() func _on_FillInside_toggled(button_pressed: bool) -> void: _fill_inside = button_pressed update_config() save_config() func _on_SpacingMode_toggled(button_pressed: bool) -> void: # This acts as an interface to access the intrinsic spacing_mode feature # BaseTool holds the spacing system, but for a tool to access them it's recommended to do it in # their own script _spacing_mode = button_pressed update_config() save_config() func _on_Spacing_value_changed(value: Vector2) -> void: _spacing = value func _input(event: InputEvent) -> void: var overwrite_button: CheckBox = $Overwrite 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 = overwrite_button.button_pressed if event.is_action_released("change_tool_mode"): overwrite_button.button_pressed = _prev_mode _overwrite = overwrite_button.button_pressed func get_config() -> Dictionary: var config := super.get_config() config["overwrite"] = _overwrite config["fill_inside"] = _fill_inside config["spacing_mode"] = _spacing_mode config["spacing"] = _spacing return config func set_config(config: Dictionary) -> void: super.set_config(config) _overwrite = config.get("overwrite", _overwrite) _fill_inside = config.get("fill_inside", _fill_inside) _spacing_mode = config.get("spacing_mode", _spacing_mode) _spacing = config.get("spacing", _spacing) func update_config() -> void: super.update_config() $Overwrite.button_pressed = _overwrite $FillInside.button_pressed = _fill_inside $SpacingMode.button_pressed = _spacing_mode $Spacing.visible = _spacing_mode $Spacing.value = _spacing func draw_start(pos: Vector2i) -> void: _old_spacing_mode = _spacing_mode pos = snap_position(pos) super.draw_start(pos) if Input.is_action_pressed("draw_color_picker"): _picking_color = true _pick_color(pos) return _picking_color = false Global.canvas.selection.transform_content_confirm() var can_skip_mask := true if tool_slot.color.a < 1 and !_overwrite: can_skip_mask = false update_mask(can_skip_mask) _changed = false _drawer.color_op.changed = false _drawer.color_op.overwrite = _overwrite _draw_points = [] prepare_undo("Draw") _drawer.reset() _draw_line = Input.is_action_pressed("draw_create_line") if _draw_line: _spacing_mode = false # spacing mode is disabled during line mode if Global.mirror_view: # mirroring position is ONLY required by "Preview" pos.x = (Global.current_project.size.x - 1) - pos.x _line_start = pos _line_end = pos update_line_polylines(_line_start, _line_end) else: if _fill_inside: _draw_points.append(pos) draw_tool(pos) _last_position = pos Global.canvas.sprite_changed_this_frame = true cursor_text = "" 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"): _pick_color(pos) return if _draw_line: _spacing_mode = false # spacing mode is disabled during line mode if Global.mirror_view: # mirroring position is ONLY required by "Preview" pos.x = (Global.current_project.size.x - 1) - pos.x var d := _line_angle_constraint(_line_start, pos) _line_end = d.position cursor_text = d.text update_line_polylines(_line_start, _line_end) else: draw_fill_gap(_last_position, pos) _last_position = pos cursor_text = "" Global.canvas.sprite_changed_this_frame = true if _fill_inside: _draw_points.append(pos) func draw_end(pos: Vector2i) -> void: pos = snap_position(pos) super.draw_end(pos) if _picking_color: return if _draw_line: _spacing_mode = false # spacing mode is disabled during line mode if Global.mirror_view: # now we revert back the coordinates from their mirror form so that line can be drawn _line_start.x = (Global.current_project.size.x - 1) - _line_start.x _line_end.x = (Global.current_project.size.x - 1) - _line_end.x draw_tool(_line_start) draw_fill_gap(_line_start, _line_end) _draw_line = false else: if _fill_inside: _draw_points.append(pos) if _draw_points.size() > 3: var v := Vector2i() var image_size := Global.current_project.size for x in image_size.x: v.x = x for y in image_size.y: v.y = y if Geometry2D.is_point_in_polygon(v, _draw_points): if _spacing_mode: # use of get_spacing_position() in Pencil.gd is a rare case # (you would ONLY need _spacing_mode and _spacing in most cases) v = get_spacing_position(v) draw_tool(v) commit_undo() cursor_text = "" update_random_image() _spacing_mode = _old_spacing_mode func _draw_brush_image(image: Image, src_rect: Rect2i, dst: Vector2i) -> void: _changed = true var images := _get_selected_draw_images() if _overwrite: for draw_image in images: draw_image.blit_rect(image, src_rect, dst) else: for draw_image in images: draw_image.blend_rect(image, src_rect, dst)