From 572bf851fa5cdead3bc2bf8fe80c48c2bf6c87a1 Mon Sep 17 00:00:00 2001 From: Nordup Date: Wed, 13 Aug 2025 15:09:29 +0700 Subject: [PATCH] carousel scroll --- .../components/onboarding/onboarding.tscn | 1 - app/scripts/ui/onboarding/carousel.gd | 87 ++++++++++++++++++- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/app/scenes/components/onboarding/onboarding.tscn b/app/scenes/components/onboarding/onboarding.tscn index be50e25..a0702a8 100644 --- a/app/scenes/components/onboarding/onboarding.tscn +++ b/app/scenes/components/onboarding/onboarding.tscn @@ -87,7 +87,6 @@ script = ExtResource("2_uhwdh") ui_events = ExtResource("3_jta5g") line = NodePath("Line") close = NodePath("Line/Close") -tween_duration = 0.3 [node name="Line" type="Control" parent="Root/Carousel"] layout_mode = 1 diff --git a/app/scripts/ui/onboarding/carousel.gd b/app/scripts/ui/onboarding/carousel.gd index 176cb7f..db88c65 100644 --- a/app/scripts/ui/onboarding/carousel.gd +++ b/app/scripts/ui/onboarding/carousel.gd @@ -3,12 +3,23 @@ extends Control @export var ui_events: UiEvents @export var line: Control @export var close: Button -@export var tween_duration: float + +@export var tween_duration: float = 0.3 +@export var drag_deadzone: float = 20.0 +@export var page_switch_threshold: float = 75.0 +@export var overscroll_softness: float = 30.0 +@export var overscroll_limit: float = 200.0 var boards: Array[OnboardingBoard] = [] var focused_page: int var tween: Tween +var dragging: bool +var drag_started: bool +var drag_start_position: Vector2 +var drag_start_line_x: float +var last_mouse_position: Vector2 + func _ready() -> void: setup_boards() @@ -59,3 +70,77 @@ func refresh_mouse_position() -> void: var event = InputEventMouseMotion.new() event.position = get_viewport().get_mouse_position() Input.parse_input_event(event) + + +func set_focus_buttons_disabled(disabled: bool) -> void: + close.disabled = disabled + for board in boards: + board.focus_button.disabled = disabled + + +func _gui_input(event: InputEvent) -> void: + if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT: + if event.pressed: + # Start dragging + dragging = true + drag_started = false + drag_start_position = event.position + last_mouse_position = event.position + drag_start_line_x = line.position.x + else: + # End dragging + if dragging: + dragging = false + if not drag_started: + # Treat as click: if no tween is playing, keep current focused page + if not (is_instance_valid(tween) and tween.is_running()): + move_line(focused_page) + return + + # Drag was active: consume release and re-enable focus buttons + set_focus_buttons_disabled(false) + accept_event() + + # Decide target page based on drag distance/direction + var total_drag_x: float = event.position.x - drag_start_position.x + var last_index: int = boards.size() - 1 + var target_index: int = focused_page + + if abs(total_drag_x) >= page_switch_threshold: + if total_drag_x < 0.0: + target_index = min(focused_page + 1, last_index) + else: + target_index = max(focused_page - 1, 0) + + move_line(target_index) + + elif event is InputEventMouseMotion: + if dragging: + var delta_x: float = event.position.x - last_mouse_position.x + if not drag_started: + var moved_enough: bool = abs(event.position.x - drag_start_position.x) >= drag_deadzone + if moved_enough: + drag_started = true + # Now that drag truly started, stop any ongoing tween + if is_instance_valid(tween): tween.stop() + set_focus_buttons_disabled(true) + accept_event() + + if drag_started: + var displacement: float = abs(line.position.x - drag_start_line_x) + var resistance: float = 1.0 / (1.0 + displacement / overscroll_softness) + var applied_dx: float = delta_x * resistance + var new_x: float = line.position.x + applied_dx + var delta_from_start: float = new_x - drag_start_line_x + + if delta_from_start > overscroll_limit: + new_x = drag_start_line_x + overscroll_limit + elif delta_from_start < -overscroll_limit: + new_x = drag_start_line_x - overscroll_limit + + line.position.x = new_x + + last_mouse_position = event.position + + if drag_started: + accept_event()