mirror of
https://github.com/thegatesbrowser/thegates.git
synced 2025-08-23 08:17:34 -04:00
carousel code cleanup
This commit is contained in:
parent
572bf851fa
commit
a2e1121fec
2 changed files with 95 additions and 80 deletions
|
@ -6,12 +6,12 @@ extends Control
|
|||
|
||||
@export var tween_duration: float = 0.3
|
||||
@export var drag_deadzone: float = 20.0
|
||||
@export var page_switch_threshold: float = 75.0
|
||||
@export var board_switch_threshold: float = 50.0
|
||||
@export var overscroll_softness: float = 30.0
|
||||
@export var overscroll_limit: float = 200.0
|
||||
|
||||
var boards: Array[OnboardingBoard] = []
|
||||
var focused_page: int
|
||||
var current_board: int
|
||||
var tween: Tween
|
||||
|
||||
var dragging: bool
|
||||
|
@ -22,57 +22,65 @@ var last_mouse_position: Vector2
|
|||
|
||||
|
||||
func _ready() -> void:
|
||||
setup_boards()
|
||||
collect_boards()
|
||||
assert(boards.size() > 0, "Carousel must have at least one board")
|
||||
|
||||
ui_events.ui_size_changed.connect(on_ui_size_changed)
|
||||
move_line(0)
|
||||
animate_to_board(0)
|
||||
|
||||
|
||||
func setup_boards() -> void:
|
||||
func collect_boards() -> void:
|
||||
for child in line.get_children():
|
||||
if child is not OnboardingBoard: continue
|
||||
boards.append(child)
|
||||
|
||||
for i in range(boards.size()):
|
||||
boards[i].request_focus.connect(move_line.bind(i))
|
||||
boards[i].request_focus.connect(animate_to_board.bind(i))
|
||||
|
||||
|
||||
func on_ui_size_changed(ui_size: Vector2) -> void:
|
||||
var screen_center = ui_size.y / 2
|
||||
line.position.y = screen_center - line.size.y / 2
|
||||
|
||||
move_line(focused_page)
|
||||
animate_to_board(current_board)
|
||||
|
||||
|
||||
func move_line(board_index: int) -> void:
|
||||
var board = boards[board_index]
|
||||
focused_page = board_index
|
||||
func animate_to_board(board_index: int) -> void:
|
||||
board_index = clamp(board_index, 0, boards.size() - 1)
|
||||
current_board = board_index
|
||||
|
||||
var screen_center = ui_events.current_ui_size.x / 2
|
||||
var wanted_board_position = screen_center - board.size.x / 2
|
||||
var line_position = Vector2(wanted_board_position - board.position.x, line.position.y)
|
||||
var target_position := compute_line_position_for_board(board_index)
|
||||
|
||||
if is_instance_valid(tween): tween.stop()
|
||||
tween = create_tween()
|
||||
tween.tween_property(line, "position", line_position, tween_duration).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
tween.tween_property(line, "position", target_position, tween_duration).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
|
||||
for i in range(boards.size()):
|
||||
if i == board_index:
|
||||
boards[i].focus(tween_duration)
|
||||
else: boards[i].unfocus(tween_duration)
|
||||
else:
|
||||
boards[i].unfocus(tween_duration)
|
||||
|
||||
await tween.finished
|
||||
refresh_mouse_position()
|
||||
|
||||
|
||||
func compute_line_position_for_board(board_index: int) -> Vector2:
|
||||
var board := boards[board_index]
|
||||
var screen_center_x := ui_events.current_ui_size.x / 2.0
|
||||
var wanted_board_position := screen_center_x - board.size.x / 2.0
|
||||
return Vector2(wanted_board_position - board.position.x, line.position.y)
|
||||
|
||||
|
||||
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:
|
||||
#region Dragging
|
||||
|
||||
func set_buttons_disabled(disabled: bool) -> void:
|
||||
close.disabled = disabled
|
||||
for board in boards:
|
||||
board.focus_button.disabled = disabled
|
||||
|
@ -81,66 +89,79 @@ func set_focus_buttons_disabled(disabled: bool) -> void:
|
|||
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)
|
||||
begin_drag(event.position)
|
||||
elif dragging:
|
||||
end_drag()
|
||||
|
||||
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 event is InputEventMouseMotion and dragging:
|
||||
if not drag_started:
|
||||
var moved_enough: bool = abs(event.position.x - drag_start_position.x) >= drag_deadzone
|
||||
|
||||
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 moved_enough:
|
||||
drag_started = true
|
||||
|
||||
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
|
||||
if is_instance_valid(tween):
|
||||
tween.stop()
|
||||
|
||||
line.position.x = new_x
|
||||
|
||||
last_mouse_position = event.position
|
||||
|
||||
if drag_started:
|
||||
set_buttons_disabled(true)
|
||||
accept_event()
|
||||
|
||||
if drag_started:
|
||||
var delta_x: float = event.position.x - last_mouse_position.x
|
||||
apply_drag(delta_x)
|
||||
accept_event()
|
||||
|
||||
last_mouse_position = event.position
|
||||
|
||||
|
||||
func begin_drag(mouse_pos: Vector2) -> void:
|
||||
dragging = true
|
||||
drag_started = false
|
||||
drag_start_position = mouse_pos
|
||||
last_mouse_position = mouse_pos
|
||||
drag_start_line_x = line.position.x
|
||||
|
||||
|
||||
func end_drag() -> void:
|
||||
dragging = false
|
||||
|
||||
if not drag_started:
|
||||
# Treat as click, keep current board
|
||||
if not (is_instance_valid(tween) and tween.is_running()):
|
||||
animate_to_board(current_board)
|
||||
return
|
||||
|
||||
set_buttons_disabled(false)
|
||||
accept_event()
|
||||
|
||||
var line_delta_x := line.position.x - drag_start_line_x
|
||||
var target_index := determine_target_board(line_delta_x)
|
||||
animate_to_board(target_index)
|
||||
|
||||
|
||||
func determine_target_board(line_delta_x: float) -> int:
|
||||
if abs(line_delta_x) < board_switch_threshold:
|
||||
return current_board
|
||||
|
||||
if line_delta_x < 0.0:
|
||||
return min(current_board + 1, boards.size() - 1)
|
||||
else:
|
||||
return max(current_board - 1, 0)
|
||||
|
||||
|
||||
func apply_drag(delta_x: float) -> void:
|
||||
# Scale input movement by resistance that grows with displacement
|
||||
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
|
||||
|
||||
# Prevent overscroll
|
||||
var delta_from_start: float = new_x - drag_start_line_x
|
||||
delta_from_start = clamp(delta_from_start, -overscroll_limit, overscroll_limit)
|
||||
new_x = drag_start_line_x + delta_from_start
|
||||
|
||||
line.position.x = new_x
|
||||
|
||||
#endregion Dragging
|
||||
|
|
|
@ -18,7 +18,6 @@ func _ready() -> void:
|
|||
visible = true
|
||||
root.visible = false
|
||||
root.modulate = HIDDEN
|
||||
root.mouse_filter = Control.MOUSE_FILTER_PASS
|
||||
|
||||
await get_tree().create_timer(INITIAL_DELAY).timeout
|
||||
show_onboarding()
|
||||
|
@ -32,16 +31,11 @@ func show_onboarding() -> void:
|
|||
if is_instance_valid(tween): tween.stop()
|
||||
tween = create_tween()
|
||||
tween.tween_property(root, "modulate", SHOWN, fade_in)
|
||||
await tween.finished
|
||||
|
||||
root.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
|
||||
|
||||
func hide_onboarding() -> void:
|
||||
if not root.visible: return
|
||||
|
||||
root.mouse_filter = Control.MOUSE_FILTER_PASS
|
||||
|
||||
if is_instance_valid(tween): tween.stop()
|
||||
tween = create_tween()
|
||||
tween.tween_property(root, "modulate", HIDDEN, fade_out)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue