mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-03-13 06:45:17 +00:00
* fix mirror previews * Fix incorredt selection resizing of selection in mirror mode * Fix mirror previews (selection tools) * typo
239 lines
6.2 KiB
GDScript
239 lines
6.2 KiB
GDScript
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()
|
|
update_indicator()
|
|
|
|
|
|
func update_brush() -> void:
|
|
pass
|
|
|
|
|
|
func _on_Thickness_value_changed(value: int) -> void:
|
|
_thickness = value
|
|
|
|
update_indicator()
|
|
update_config()
|
|
save_config()
|
|
|
|
|
|
func update_indicator() -> void:
|
|
var bitmap := BitMap.new()
|
|
bitmap.create(Vector2.ONE * _thickness)
|
|
bitmap.set_bit_rect(Rect2(Vector2.ZERO, Vector2.ONE * _thickness), true)
|
|
_indicator = bitmap
|
|
_polylines = _create_polylines(_indicator)
|
|
|
|
|
|
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
|
|
|
|
|
|
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("shape_displace"):
|
|
_displace_origin = true
|
|
elif event.is_action_released("shape_displace"):
|
|
_displace_origin = false
|
|
|
|
|
|
func draw_start(position: Vector2) -> void:
|
|
position = snap_position(position)
|
|
.draw_start(position)
|
|
if Input.is_action_pressed("shape_displace"):
|
|
_picking_color = true
|
|
_pick_color(position)
|
|
return
|
|
_picking_color = false
|
|
|
|
Global.canvas.selection.transform_content_confirm()
|
|
update_mask()
|
|
|
|
if Global.mirror_view:
|
|
# mirroring position is ONLY required by "Preview"
|
|
position.x = Global.current_project.size.x - position.x - 1
|
|
_original_pos = position
|
|
_start = position
|
|
_offset = position
|
|
_dest = position
|
|
_drawing = true
|
|
|
|
|
|
func draw_move(position: Vector2) -> void:
|
|
position = snap_position(position)
|
|
.draw_move(position)
|
|
if _picking_color: # Still return even if we released Alt
|
|
if Input.is_action_pressed("shape_displace"):
|
|
_pick_color(position)
|
|
return
|
|
|
|
if _drawing:
|
|
if Global.mirror_view:
|
|
# mirroring position is ONLY required by "Preview"
|
|
position.x = Global.current_project.size.x - position.x - 1
|
|
if _displace_origin:
|
|
_original_pos += position - _offset
|
|
var d := _line_angle_constraint(_original_pos, position)
|
|
_dest = d.position
|
|
|
|
if Input.is_action_pressed("shape_center"):
|
|
_start = _original_pos - (_dest - _original_pos)
|
|
else:
|
|
_start = _original_pos
|
|
cursor_text = d.text
|
|
_offset = position
|
|
|
|
|
|
func draw_end(position: Vector2) -> void:
|
|
position = snap_position(position)
|
|
.draw_end(position)
|
|
if _picking_color:
|
|
return
|
|
|
|
if _drawing:
|
|
if Global.mirror_view:
|
|
# now we revert back the coordinates from their mirror form so that line can be drawn
|
|
_original_pos.x = (Global.current_project.size.x - 1) - _original_pos.x
|
|
_start.x = (Global.current_project.size.x - 1) - _start.x
|
|
_offset.x = (Global.current_project.size.x - 1) - _offset.x
|
|
_dest.x = (Global.current_project.size.x - 1) - _dest.x
|
|
if _thickness % 2 == 0:
|
|
_original_pos.x += 1
|
|
_start.x += 1
|
|
_offset.x += 1
|
|
_dest.x += 1
|
|
_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), Color.black)
|
|
|
|
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("Draw Shape")
|
|
for point in points:
|
|
# Reset drawer every time because pixel perfect sometimes breaks the tool
|
|
_drawer.reset()
|
|
# Draw each point offsetted based on the shape's thickness
|
|
draw_tool(point)
|
|
|
|
commit_undo()
|
|
|
|
|
|
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 Input.is_action_pressed("shape_perfect"):
|
|
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
|