Skip to content

Commit

Permalink
Added a new line tool
Browse files Browse the repository at this point in the history
One of the most requested tools has finally been added!
  • Loading branch information
OverloadedOrama committed May 12, 2021
1 parent 36652c6 commit 99ce07b
Show file tree
Hide file tree
Showing 16 changed files with 432 additions and 7 deletions.
Binary file added assets/graphics/blue_themes/tools/linetool.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 34 additions & 0 deletions assets/graphics/blue_themes/tools/linetool.png.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[remap]

importer="texture"
type="StreamTexture"
path="res://.import/linetool.png-4ed7f0aa497e149a9bb715508e7b79d1.stex"
metadata={
"vram_texture": false
}

[deps]

source_file="res://assets/graphics/blue_themes/tools/linetool.png"
dest_files=[ "res://.import/linetool.png-4ed7f0aa497e149a9bb715508e7b79d1.stex" ]

[params]

compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0
Binary file added assets/graphics/cursor_icons/linetool_cursor.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions assets/graphics/cursor_icons/linetool_cursor.png.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[remap]

importer="image"
type="Image"
path="res://.import/linetool_cursor.png-38c59a143cf71cc8a7903919aba16145.image"

[deps]

source_file="res://assets/graphics/cursor_icons/linetool_cursor.png"
dest_files=[ "res://.import/linetool_cursor.png-38c59a143cf71cc8a7903919aba16145.image" ]

[params]

Binary file added assets/graphics/dark_themes/tools/linetool.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 34 additions & 0 deletions assets/graphics/dark_themes/tools/linetool.png.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[remap]

importer="texture"
type="StreamTexture"
path="res://.import/linetool.png-49f0a0966a97070b2c54583188740fb8.stex"
metadata={
"vram_texture": false
}

[deps]

source_file="res://assets/graphics/dark_themes/tools/linetool.png"
dest_files=[ "res://.import/linetool.png-49f0a0966a97070b2c54583188740fb8.stex" ]

[params]

compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0
Binary file added assets/graphics/light_themes/tools/linetool.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 34 additions & 0 deletions assets/graphics/light_themes/tools/linetool.png.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[remap]

importer="texture"
type="StreamTexture"
path="res://.import/linetool.png-41d8bda5991aa6c858e29d67515cdd5f.stex"
metadata={
"vram_texture": false
}

[deps]

source_file="res://assets/graphics/light_themes/tools/linetool.png"
dest_files=[ "res://.import/linetool.png-41d8bda5991aa6c858e29d67515cdd5f.stex" ]

[params]

compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0
10 changes: 10 additions & 0 deletions project.godot
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,16 @@ alt={
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777240,"unicode":0,"echo":false,"script":null)
]
}
left_linetool_tool={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":76,"unicode":0,"echo":false,"script":null)
]
}
right_linetool_tool={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":true,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":76,"unicode":0,"echo":false,"script":null)
]
}

[locale]

Expand Down
11 changes: 11 additions & 0 deletions src/Autoload/Global.gd
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,17 @@ Hold %s to make a line""") % [InputMap.get_action_list("left_eraser_tool")[0].as
%s for left mouse button
%s for right mouse button""") % [InputMap.get_action_list("left_lightdark_tool")[0].as_text(), InputMap.get_action_list("right_lightdark_tool")[0].as_text()]

var linetool : BaseButton = find_node_by_name(root, "LineTool")
linetool.hint_tooltip = tr("""Line Tool
%s for left mouse button
%s for right mouse button
Hold %s to snap the angle of the line
Hold %s to center the shape on the click origin
Hold %s to displace the shape's origin""") % [InputMap.get_action_list("left_linetool_tool")[0].as_text(), InputMap.get_action_list("right_linetool_tool")[0].as_text(), "Shift", "Ctrl", "Alt"]


var recttool : BaseButton = find_node_by_name(root, "RectangleTool")
recttool.hint_tooltip = tr("""Rectangle Tool
Expand Down
1 change: 1 addition & 0 deletions src/Autoload/Tools.gd
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ var _tools = {
"Eraser" : "res://src/Tools/Eraser.tscn",
"Bucket" : "res://src/Tools/Bucket.tscn",
"LightenDarken" : "res://src/Tools/LightenDarken.tscn",
"LineTool" : "res://src/Tools/LineTool.tscn",
"RectangleTool" : "res://src/Tools/RectangleTool.tscn",
"EllipseTool" : "res://src/Tools/EllipseTool.tscn",
}
Expand Down
188 changes: 188 additions & 0 deletions src/Tools/LineTool.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
extends "res://src/Tools/Draw.gd"


var _original_pos := Vector2.ZERO
var _start := Vector2.ZERO
var _offset := Vector2.ZERO
var _dest := Vector2.ZERO
var _drawing := false
var _displace_origin := false
var _thickness := 1


func _init() -> void:
_drawer.color_op = Drawer.ColorOp.new()


func _on_Thickness_value_changed(value: int) -> void:
_thickness = value
update_config()
save_config()


func get_config() -> Dictionary:
var config := .get_config()
config["thickness"] = _thickness
return config


func set_config(config: Dictionary) -> void:
.set_config(config)
_thickness = config.get("thickness", _thickness)


func update_config() -> void:
.update_config()
$ThicknessSlider.value = _thickness
$ShapeThickness/ThicknessSpinbox.value = _thickness


func _get_shape_points(_size: Vector2) -> PoolVector2Array:
return PoolVector2Array()


func _get_shape_points_filled(_size: Vector2) -> PoolVector2Array:
return PoolVector2Array()


func _input(event : InputEvent) -> void:
if _drawing:
if event.is_action_pressed("alt"):
_displace_origin = true
elif event.is_action_released("alt"):
_displace_origin = false


func draw_start(position : Vector2) -> void:
Global.canvas.selection.transform_content_confirm()
update_mask()

_original_pos = position
_start = position
_offset = position
_dest = position
_drawing = true


func draw_move(position : Vector2) -> void:
if _drawing:
if _displace_origin:
_original_pos += position - _offset
var d = _line_angle_constraint(_original_pos, position)
_dest = d.position
if Tools.control:
_start = _original_pos - (_dest - _original_pos)
else:
_start = _original_pos
cursor_text = d.text
_offset = position


func draw_end(_position : Vector2) -> void:
if _drawing:
_draw_shape()

_original_pos = Vector2.ZERO
_start = Vector2.ZERO
_dest = Vector2.ZERO
_drawing = false
_displace_origin = false
cursor_text = ""


func draw_preview() -> void:
if _drawing:
var canvas : CanvasItem = Global.canvas.previews
var indicator := BitMap.new()
var start := _start
if _start.x > _dest.x:
start.x = _dest.x
if _start.y > _dest.y:
start.y = _dest.y

var points := _get_points()
var t_offset := _thickness - 1
var t_offsetv := Vector2(t_offset, t_offset)
indicator.create((_dest - _start).abs() + t_offsetv * 2 + Vector2.ONE)

for point in points:
var p : Vector2 = point - start + t_offsetv
indicator.set_bit(p, 1)

canvas.draw_set_transform(start - t_offsetv, canvas.rotation, canvas.scale)

for line in _create_polylines(indicator):
canvas.draw_polyline(PoolVector2Array(line), tool_slot.color)

canvas.draw_set_transform(canvas.position, canvas.rotation, canvas.scale)


func _draw_shape() -> void:
# var rect := _get_result_rect(origin, dest)
var points := _get_points()
prepare_undo()
for point in points:
# Reset drawer every time because pixel perfect sometimes breaks the tool
_drawer.reset()
# Draw each point offseted based on the shape's thickness
draw_tool(point)

commit_undo("Draw Shape")


func _get_points() -> PoolVector2Array:
var array := []
var dx := int(abs(_dest.x - _start.x))
var dy := int(-abs(_dest.y - _start.y))
var err := dx + dy
var e2 := err << 1
var sx = 1 if _start.x < _dest.x else -1
var sy = 1 if _start.y < _dest.y else -1
var x = _start.x
var y = _start.y

var start := _start - Vector2.ONE * (_thickness >> 1)
var end := start + Vector2.ONE * _thickness
for yy in range(start.y, end.y):
for xx in range(start.x, end.x):
array.append(Vector2(xx, yy))

while !(x == _dest.x && y == _dest.y):
e2 = err << 1
if e2 >= dy:
err += dy
x += sx
if e2 <= dx:
err += dx
y += sy

var pos := Vector2(x, y)
start = pos - Vector2.ONE * (_thickness >> 1)
end = start + Vector2.ONE * _thickness
for yy in range(start.y, end.y):
for xx in range(start.x, end.x):
array.append(Vector2(xx, yy))

return PoolVector2Array(array)


func _line_angle_constraint(start : Vector2, end : Vector2) -> Dictionary:
var result := {}
var angle := rad2deg(end.angle_to_point(start))
var distance := start.distance_to(end)
if Tools.shift:
angle = stepify(angle, 22.5)
if step_decimals(angle) != 0:
var diff := end - start
var v := Vector2(2 , 1) if abs(diff.x) > abs(diff.y) else Vector2(1 , 2)
var p := diff.project(diff.sign() * v).abs().round()
var f := p.y if abs(diff.x) > abs(diff.y) else p.x
end = start + diff.sign() * v * f - diff.sign()
angle = rad2deg(atan2(sign(diff.y) * v.y, sign(diff.x) * v.x))
else:
end = start + Vector2.RIGHT.rotated(deg2rad(angle)) * distance
angle *= -1
angle += 360 if angle < 0 else 0
result.text = str(stepify(angle, 0.01)) + "°"
result.position = end.round()
return result
Loading

0 comments on commit 99ce07b

Please sign in to comment.