2025-10-10 03:01:08 -04:00
|
|
|
extends Node2D
|
|
|
|
|
class_name CursorPool
|
|
|
|
|
|
|
|
|
|
enum AnimationState {
|
|
|
|
|
Normal, # lerps box center and size to desired.
|
|
|
|
|
Exploding, # Normal but diff lerp speeds.
|
|
|
|
|
Area, # lerps each box side to desired box side
|
|
|
|
|
Fading, # standard box motion, opacity fades slowly.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Cursor:
|
|
|
|
|
var box: Rect2
|
|
|
|
|
var opacity: float
|
|
|
|
|
var desired_box: Rect2
|
|
|
|
|
var desired_opacity: float
|
|
|
|
|
var color: Color
|
|
|
|
|
var animation: AnimationState = AnimationState.Normal
|
|
|
|
|
|
|
|
|
|
var cursors: Array[Cursor] = []
|
|
|
|
|
var current_cursor: Cursor = null
|
|
|
|
|
|
2025-10-13 09:57:17 -04:00
|
|
|
var stored_color: Color = Color.WHITE
|
|
|
|
|
|
2025-10-10 03:01:08 -04:00
|
|
|
func new_cursor(color: Color) -> Cursor:
|
|
|
|
|
var cursor = Cursor.new()
|
|
|
|
|
cursors.append(cursor)
|
|
|
|
|
if cursors.size() > 10: cursors.remove_at(0)
|
|
|
|
|
cursor.box = get_viewport_rect()
|
|
|
|
|
cursor.box.size = Vector2.ONE * max(cursor.box.size.x, cursor.box.size.y)
|
|
|
|
|
cursor.box = Rect2(cursor.box.position + cursor.box.size / -2.0, cursor.box.size).grow(100)
|
|
|
|
|
cursor.opacity = -2.0
|
|
|
|
|
cursor.animation = AnimationState.Normal
|
|
|
|
|
cursor.desired_box = cursor.box
|
|
|
|
|
cursor.desired_opacity = 1.0
|
|
|
|
|
cursor.color = color
|
|
|
|
|
current_cursor = cursor
|
|
|
|
|
|
|
|
|
|
return cursor
|
|
|
|
|
|
2025-10-13 09:57:17 -04:00
|
|
|
func change_color(color: Color):
|
|
|
|
|
if current_cursor == null: return
|
|
|
|
|
if color == current_cursor.color: return
|
|
|
|
|
var box = current_cursor.box
|
|
|
|
|
var opacity = current_cursor.opacity
|
|
|
|
|
var animation_state = current_cursor.animation
|
|
|
|
|
var dbox = current_cursor.desired_box
|
|
|
|
|
var dopacity = current_cursor.desired_opacity
|
|
|
|
|
explode()
|
|
|
|
|
new_cursor(color)
|
|
|
|
|
current_cursor.box = box
|
|
|
|
|
current_cursor.desired_box = dbox
|
|
|
|
|
current_cursor.opacity = opacity
|
|
|
|
|
current_cursor.desired_opacity = dopacity
|
|
|
|
|
current_cursor.animation = animation_state
|
|
|
|
|
|
2025-10-10 03:01:08 -04:00
|
|
|
# cursor removal type beats.
|
|
|
|
|
func fade_out() -> void:
|
|
|
|
|
if current_cursor == null: return
|
|
|
|
|
current_cursor.animation = AnimationState.Fading
|
|
|
|
|
current_cursor.desired_opacity = 0.0
|
2025-10-13 09:57:17 -04:00
|
|
|
current_cursor = null
|
|
|
|
|
|
2025-10-10 03:01:08 -04:00
|
|
|
func explode() -> void:
|
|
|
|
|
if current_cursor == null: return
|
|
|
|
|
current_cursor.animation = AnimationState.Exploding
|
|
|
|
|
current_cursor.desired_box = current_cursor.desired_box.grow(10)
|
|
|
|
|
current_cursor.desired_opacity = 0.0
|
2025-10-13 09:57:17 -04:00
|
|
|
current_cursor = null
|
2025-10-10 03:01:08 -04:00
|
|
|
|
|
|
|
|
# override / util
|
|
|
|
|
func _process(delta) -> void:
|
|
|
|
|
for d in cursors:
|
|
|
|
|
match d.animation:
|
|
|
|
|
AnimationState.Normal: _update_display_animation_active(d, delta)
|
|
|
|
|
AnimationState.Exploding: _update_display_animation_exploding(d, delta)
|
|
|
|
|
AnimationState.Fading: _update_display_animation_fading(d, delta)
|
|
|
|
|
AnimationState.Area: _update_display_animation_area(d, delta)
|
|
|
|
|
queue_redraw()
|
|
|
|
|
func _draw():
|
|
|
|
|
for d in cursors:
|
|
|
|
|
draw_rect(d.box, _lerp_opacity(d.color, d.opacity), true)
|
|
|
|
|
func _lerp_opacity(c: Color, t: float) -> Color:
|
|
|
|
|
return Color(c.r, c.g, c.b, c.a * t)
|
|
|
|
|
|
|
|
|
|
# === Display Animations
|
|
|
|
|
func _update_display_animation_active(d: Cursor, delta):
|
|
|
|
|
var old_size = d.box.size
|
|
|
|
|
var desired_size = d.desired_box.size
|
|
|
|
|
var new_size = lerp(old_size, desired_size, delta * 30 * Util.animation_speed)
|
|
|
|
|
#if old_size.length_squared() > desired_size.length_squared():
|
|
|
|
|
#new_size = lerp(old_size, desired_size, delta * 30 * animation_speed)
|
|
|
|
|
#else:
|
|
|
|
|
#new_size = lerp(old_size, desired_size, delta * 30 * animation_speed)
|
|
|
|
|
var old_center = d.box.get_center()
|
|
|
|
|
var desired_center = d.desired_box.get_center()
|
|
|
|
|
var new_center = lerp(old_center, desired_center, delta * 50 * Util.animation_speed)
|
|
|
|
|
d.box = Rect2(new_center - new_size / 2.0, new_size)
|
|
|
|
|
d.opacity = lerp(d.opacity, d.desired_opacity, delta * 20 * Util.animation_speed)
|
|
|
|
|
func _update_display_animation_exploding(d: Cursor, delta):
|
|
|
|
|
var old_size = d.box.size
|
|
|
|
|
var desired_size = d.desired_box.size
|
|
|
|
|
var new_size = lerp(old_size, desired_size, delta * 20 * Util.animation_speed)
|
|
|
|
|
var old_center = d.box.get_center()
|
|
|
|
|
var desired_center = d.desired_box.get_center()
|
|
|
|
|
var new_center = lerp(old_center, desired_center, delta * 50 * Util.animation_speed)
|
|
|
|
|
d.box = Rect2(new_center - new_size / 2.0, new_size)
|
|
|
|
|
d.opacity = lerp(d.opacity, d.desired_opacity, delta * 15 * Util.animation_speed)
|
|
|
|
|
func _update_display_animation_fading(d: Cursor, delta):
|
|
|
|
|
var current_top = min(d.box.position.y, d.box.position.y + d.box.size.y)
|
|
|
|
|
var current_bottom = max(d.box.position.y, d.box.position.y + d.box.size.y)
|
|
|
|
|
var current_left = min(d.box.position.x, d.box.position.x + d.box.size.x)
|
|
|
|
|
var current_right = max(d.box.position.x, d.box.position.x + d.box.size.x)
|
|
|
|
|
|
|
|
|
|
var desired_top = min(d.desired_box.position.y, d.desired_box.position.y + d.desired_box.size.y)
|
|
|
|
|
var desired_bottom = max(d.desired_box.position.y, d.desired_box.position.y + d.desired_box.size.y)
|
|
|
|
|
var desired_left = min(d.desired_box.position.x, d.desired_box.position.x + d.desired_box.size.x)
|
|
|
|
|
var desired_right = max(d.desired_box.position.x, d.desired_box.position.x + d.desired_box.size.x)
|
|
|
|
|
|
|
|
|
|
var new_top = lerp(current_top, desired_top, delta * Util.animation_speed * 40)
|
|
|
|
|
var new_bottom = lerp(current_bottom, desired_bottom, delta * Util.animation_speed * 40)
|
|
|
|
|
var new_left = lerp(current_left, desired_left, delta * Util.animation_speed * 40)
|
|
|
|
|
var new_right = lerp(current_right, desired_right, delta * Util.animation_speed * 40)
|
|
|
|
|
|
|
|
|
|
d.box = Rect2(
|
|
|
|
|
new_left,
|
|
|
|
|
new_top,
|
|
|
|
|
new_right - new_left,
|
|
|
|
|
new_bottom - new_top
|
|
|
|
|
)
|
|
|
|
|
d.opacity = lerp(d.opacity, d.desired_opacity, delta * 10 * Util.animation_speed)
|
|
|
|
|
func _update_display_animation_area(d: Cursor, delta):
|
|
|
|
|
var current_top = min(d.box.position.y, d.box.position.y + d.box.size.y)
|
|
|
|
|
var current_bottom = max(d.box.position.y, d.box.position.y + d.box.size.y)
|
|
|
|
|
var current_left = min(d.box.position.x, d.box.position.x + d.box.size.x)
|
|
|
|
|
var current_right = max(d.box.position.x, d.box.position.x + d.box.size.x)
|
|
|
|
|
|
|
|
|
|
var desired_top = min(d.desired_box.position.y, d.desired_box.position.y + d.desired_box.size.y)
|
|
|
|
|
var desired_bottom = max(d.desired_box.position.y, d.desired_box.position.y + d.desired_box.size.y)
|
|
|
|
|
var desired_left = min(d.desired_box.position.x, d.desired_box.position.x + d.desired_box.size.x)
|
|
|
|
|
var desired_right = max(d.desired_box.position.x, d.desired_box.position.x + d.desired_box.size.x)
|
|
|
|
|
|
|
|
|
|
var new_top = lerp(current_top, desired_top, delta * Util.animation_speed * 40)
|
|
|
|
|
var new_bottom = lerp(current_bottom, desired_bottom, delta * Util.animation_speed * 40)
|
|
|
|
|
var new_left = lerp(current_left, desired_left, delta * Util.animation_speed * 40)
|
|
|
|
|
var new_right = lerp(current_right, desired_right, delta * Util.animation_speed * 40)
|
|
|
|
|
|
|
|
|
|
d.box = Rect2(
|
|
|
|
|
new_left,
|
|
|
|
|
new_top,
|
|
|
|
|
new_right - new_left,
|
|
|
|
|
new_bottom - new_top
|
|
|
|
|
)
|
|
|
|
|
d.opacity = lerp(d.opacity, d.desired_opacity, delta * 20 * Util.animation_speed)
|