Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions scenes/game_elements/fx/curly_trail/components/curly_trail.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# SPDX-FileCopyrightText: The Threadbare Authors
# SPDX-License-Identifier: MPL-2.0
class_name CurlyTrail
extends Node2D
## @experimental
##
## A curly trail effect for a [Line2D] node.
##
## Add points to the line in circle, so when this node moves, a curly effect is obtained. The circle
## radius becomes smaller the faster this node moves, as a simple way to achieve a thread stretching
## effect.
## [br][br]
## Note: For the effect to be achieved, this node must move. For example, by putting it as child of
## a [PathFollow2D] node.

## The line to use for the effect.
@export var line: Line2D

## The radius at zero velocity.
@export_range(10, 50, 1, "or_greater", "or_less") var radius: float = 30

## The velocity at which the thread stretches fully.
@export_range(0, 100, 1, "or_greater", "or_less") var stretched_velocity: float = 50

@export_range(-45, 45, 0.1, "radians", "or_greater", "or_less") var wheel_rotation: float = 0.2
@export_range(0, 1, 0.01) var radius_update: float = 0.1
@export var min_points_distance := 40

## How many points can the [member line] have.
@export var max_points := 100

## Draw the wheel circle and the tip for debugging.
@export var debug := false

## A value between 0 and 1 that is how stretched is the line.
var _stretching_amount := 0.0

var _last_position: Vector2

@onready var wheel: Node2D = %Wheel
@onready var tip: Node2D = %Tip


func _ready() -> void:
tip.position.x = radius


func _draw() -> void:
if debug:
draw_circle(Vector2.ZERO, tip.position.x, Color(1.0, 0.0, 0.0, 0.486))
draw_line(Vector2.ZERO, tip.position.rotated(wheel.rotation), Color(1.0, 1.0, 0.0, 0.486))


func _process(_delta: float) -> void:
var direction := Vector2.ZERO if not _last_position else _last_position - global_position
_last_position = global_position

var new_stretching_amount: float = (
(stretched_velocity - min(direction.length_squared(), stretched_velocity))
/ stretched_velocity
)
_stretching_amount = lerpf(_stretching_amount, new_stretching_amount, radius_update)

tip.position.x = radius * _stretching_amount
wheel.rotate(wheel_rotation * _stretching_amount * _stretching_amount)

if not line.get_point_count():
line.add_point(line.to_local(tip.global_position))
else:
var last_p := line.points[-1]
if last_p.distance_squared_to(tip.global_position) < min_points_distance:
line.remove_point(0)
return
line.add_point(line.to_local(tip.global_position))
while line.get_point_count() > max_points:
line.remove_point(0)

if debug:
queue_redraw()
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://w7ouog565l67
13 changes: 13 additions & 0 deletions scenes/game_elements/fx/curly_trail/curly_trail.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[gd_scene format=3 uid="uid://bs32ac1yj83ub"]

[ext_resource type="Script" uid="uid://w7ouog565l67" path="res://scenes/game_elements/fx/curly_trail/components/curly_trail.gd" id="1_siqvk"]

[node name="CurlyTrail" type="Node2D" unique_id=760772735]
script = ExtResource("1_siqvk")

[node name="Wheel" type="Node2D" parent="." unique_id=1902346593]
unique_name_in_owner = true

[node name="Tip" type="Node2D" parent="Wheel" unique_id=286815947]
unique_name_in_owner = true
position = Vector2(90, 0)
71 changes: 71 additions & 0 deletions scenes/game_elements/fx/stitch_trail/components/stitch_trail.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# SPDX-FileCopyrightText: The Threadbare Authors
# SPDX-License-Identifier: MPL-2.0
class_name StitchTrail
extends Node2D
## @experimental
##
## A stitching effect for a [Line2D] node.
##
## Add points to the line in zigzag, imitating a thread being stitched.
## [br][br]
## Note: For the effect to be achieved, this node must move. For example, by putting it as child of
## a [PathFollow2D] node.

## The line to use for the effect.
@export var line: Line2D

## Flatten the effect vertically so it looks like it's on the floor, matching
## the Threadbare top-down isometric perspective.
@export var on_floor: bool = true

## How thick is the effect.
@export_range(0, 150, 1.0, "suffix:px") var width: float = 50

## How many stitches per second.
@export_range(0, 1, 0.01) var stitches_per_second: float = 0.03

## Weight of the direction lerp interpolation. To smooth the zigzag direction as this node moves.
## This wouldn't be necessary if moving along a predefined path. But if moving abruptly using the
## mouse position (for instance) this smoothing is better.
@export_range(0, 1, 0.01) var direction_weight: float = 0.1

## MANUQ TODO
@export var min_points_distance := 40

## How many points can the [member line] have.
@export var max_points := 100

var _last_stitch_seconds: float = 0
var _last_position: Vector2
var _stitch_direction: Vector2
var _stitch_sign := 1


func _do_stitch() -> void:
var new_point := global_position + (_stitch_direction * width / 2) * _stitch_sign
line.add_point(line.to_local(new_point))
_stitch_sign *= -1
_last_position = global_position


func _process(delta: float) -> void:
if _last_stitch_seconds < stitches_per_second:
_last_stitch_seconds += delta
return
_last_stitch_seconds = 0

var direction := Vector2.ZERO if not _last_position else _last_position - global_position
var orthogonal := direction.orthogonal().normalized()
if on_floor:
orthogonal *= Vector2(1, 0.5)
_stitch_direction = _stitch_direction.lerp(orthogonal, direction_weight)

if not line.get_point_count():
_do_stitch()
else:
if _last_position.distance_squared_to(global_position) < min_points_distance:
line.remove_point(0)
return
_do_stitch()
while line.get_point_count() > max_points:
line.remove_point(0)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://c4oww6rkbqfxc
6 changes: 6 additions & 0 deletions scenes/game_elements/fx/stitch_trail/stitch_trail.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[gd_scene format=3 uid="uid://nnqyfbc80vpw"]

[ext_resource type="Script" uid="uid://c4oww6rkbqfxc" path="res://scenes/game_elements/fx/stitch_trail/components/stitch_trail.gd" id="1_7empc"]

[node name="StitchTrail" type="Node2D" unique_id=1085823885]
script = ExtResource("1_7empc")
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[remap]

importer="texture"
type="CompressedTexture2D"
uid="uid://drlsbgxh5e6vv"
path="res://.godot/imported/fabric_texture.png-75b56e12718e160760eb7d37d429c546.ctex"
metadata={
"vram_texture": false
}

[deps]

source_file="res://scenes/game_elements/fx/world_reweaven/components/fabric_texture.png"
dest_files=["res://.godot/imported/fabric_texture.png-75b56e12718e160760eb7d37d429c546.ctex"]

[params]

compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
SPDX-FileCopyrightText: The Threadbare Authors
SPDX-License-Identifier: CC-BY-SA-4.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# SPDX-FileCopyrightText: The Threadbare Authors
# SPDX-License-Identifier: MPL-2.0
extends Node2D

@onready var mouse_tracker: Node2D = %MouseTracker
@onready var curly_mouse: CurlyTrail = %CurlyMouse
@onready var stitch_mouse: StitchTrail = %StitchMouse


func _process(_delta: float) -> void:
var mouse_pos := get_global_mouse_position()
mouse_tracker.global_position = lerp(mouse_tracker.global_position, mouse_pos, 0.1)


func _unhandled_input(event: InputEvent) -> void:
if event is not InputEventMouseButton:
return
if event.pressed:
curly_mouse.process_mode = Node.PROCESS_MODE_DISABLED
curly_mouse.visible = false
stitch_mouse.process_mode = Node.PROCESS_MODE_INHERIT
stitch_mouse.visible = true
else:
curly_mouse.process_mode = Node.PROCESS_MODE_INHERIT
curly_mouse.visible = true
curly_mouse.wheel_rotation *= -1
stitch_mouse.process_mode = Node.PROCESS_MODE_DISABLED
stitch_mouse.visible = false
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://cc08dqkf7umf5
Loading