Skip to content

Instantly share code, notes, and snippets.

@Shilo
Last active January 19, 2025 22:01
Show Gist options
  • Save Shilo/30c08aa1c902e1bfc3dc1cd345a29f66 to your computer and use it in GitHub Desktop.
Save Shilo/30c08aa1c902e1bfc3dc1cd345a29f66 to your computer and use it in GitHub Desktop.
Godot 4 Trail2D.
@tool
class_name Trail2D extends Node2D
@export var duration_sec: float = 0.2:
set(value):
_line.clear_points()
_point_times.clear()
duration_sec = value
@export var width: int = 10:
set(value):
_line.width = value
get:
return _line.width
@export_range(0, 1) var width_curve_start: float = 1:
set(value):
if width_curve_start == value:
return
width_curve_start = value
update_width_curve()
@export_range(0, 1) var width_curve_end: float = 0:
set(value):
if width_curve_end == value:
return
width_curve_end = value
update_width_curve()
@export var color_start: Color = Color(1, 1, 1, 0.5):
set(value):
if color_start == value:
return
color_start = value
update_color()
@export var color_end: Color = Color.TRANSPARENT:
set(value):
if color_end == value:
return
color_end = value
update_color()
@export_group("Advanced")
@export var emitting: bool = true
@export var min_point_distance: int = 0
@export var custom_width_curve: Curve:
set(value):
custom_width_curve = value
update_width_curve()
@export var disabled: bool = false:
set(value):
if value:
_line.clear_points()
_point_times.clear()
visible = !value
set_process(!value)
get:
return !visible
var _line: Line2D = Line2D.new()
var _point_times: Array[float] = []
func _ready() -> void:
_line.joint_mode = Line2D.LINE_JOINT_ROUND
add_child(_line, false, Node.INTERNAL_MODE_FRONT)
update_color()
update_width_curve()
disabled = !visible
visibility_changed.connect(func(): disabled = !visible)
func _process(delta: float) -> void:
var finite_duration: bool = duration_sec >= 0
var position: Vector2 = global_position
var point_count: int = _line.get_point_count()
var distance: float = position.distance_to(_line.get_point_position(0)) if point_count else -1
var time := Time.get_ticks_msec()
if emitting and (distance == -1 or (distance > 0 and distance >= min_point_distance)):
_line.add_point(position, 0)
_point_times.push_front(time)
point_count += 1
if finite_duration and point_count > 0 and\
_point_times[point_count - 1] < time - duration_sec * 1000:
_line.remove_point(point_count - 1)
_point_times.pop_back()
_line.global_transform = Transform2D()
func update_color() -> void:
_line.default_color = color_start
if color_start == color_end:
_line.gradient = null
return
var gradient = Gradient.new()
gradient.set_color(0, color_start)
gradient.set_color(1, color_end)
_line.gradient = gradient
func update_width_curve() -> void:
if custom_width_curve:
_line.width_curve = custom_width_curve
return
var curve := Curve.new()
curve.add_point(Vector2(0, width_curve_start))
curve.add_point(Vector2(1, width_curve_end))
_line.width_curve = curve
@tool
class_name MouseTrail2D extends Trail2D
func _process(delta: float) -> void:
global_position = get_global_mouse_position()
super(delta)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment