class_name BubbleGradientBackground extends Control const CORNER_SEGMENTS: int = 8 var host_button: BaseButton var profile: BubbleMenuProfile func configure( button: BaseButton, menu_profile: BubbleMenuProfile, ) -> void: host_button = button profile = menu_profile mouse_filter = Control.MOUSE_FILTER_IGNORE show_behind_parent = true set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) queue_redraw() func _draw() -> void: if host_button == null or profile == null or size.x <= 0.0 or size.y <= 0.0: return var fill_color: Color = _get_fill_color() var top_color: Color = fill_color.lightened(profile.gradient_top_lift) var points := PackedVector2Array() _append_arc(points, Vector2(profile.corner_radius, profile.corner_radius), PI, PI * 1.5) _append_arc( points, Vector2(size.x - profile.corner_radius, profile.corner_radius), PI * 1.5, TAU, ) _append_arc( points, Vector2(size.x - profile.corner_radius, size.y - profile.corner_radius), 0.0, PI * 0.5, ) _append_arc( points, Vector2(profile.corner_radius, size.y - profile.corner_radius), PI * 0.5, PI, ) var colors := PackedColorArray() for point: Vector2 in points: colors.append(top_color.lerp(fill_color, clampf(point.y / size.y, 0.0, 1.0))) draw_polygon(points, colors) func _append_arc( points: PackedVector2Array, center: Vector2, start_angle: float, end_angle: float, ) -> void: var radius: float = minf( float(profile.corner_radius), minf(size.x, size.y) * 0.5, ) for index: int in range(CORNER_SEGMENTS + 1): var weight: float = float(index) / float(CORNER_SEGMENTS) var angle: float = lerpf(start_angle, end_angle, weight) points.append(center + Vector2(cos(angle), sin(angle)) * radius) func _get_fill_color() -> Color: if host_button.disabled: return profile.disabled_fill match host_button.get_draw_mode(): BaseButton.DRAW_PRESSED, BaseButton.DRAW_HOVER_PRESSED: return profile.pressed_fill BaseButton.DRAW_HOVER: return profile.hover_fill if host_button.has_focus(): return profile.hover_fill return profile.normal_fill