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 var stored_color: Color = Color.WHITE 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 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 # cursor removal type beats. func fade_out() -> void: if current_cursor == null: return current_cursor.animation = AnimationState.Fading current_cursor.desired_opacity = 0.0 current_cursor = null 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 current_cursor = null # 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)