openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

76 lines
2.8 KiB

import pyray as rl
from enum import IntEnum
MOUSE_WHEEL_SCROLL_SPEED = 30
INERTIA_FRICTION = 0.95 # The rate at which the inertia slows down
MIN_VELOCITY = 0.1 # Minimum velocity before stopping the inertia
class ScrollState(IntEnum):
IDLE = 0
DRAGGING_CONTENT = 1
DRAGGING_SCROLLBAR = 2
class GuiScrollPanel:
def __init__(self, show_vertical_scroll_bar: bool = False):
self._scroll_state: ScrollState = ScrollState.IDLE
self._last_mouse_y: float = 0.0
self._offset = rl.Vector2(0, 0)
self._view = rl.Rectangle(0, 0, 0, 0)
self._show_vertical_scroll_bar: bool = show_vertical_scroll_bar
self._velocity_y = 0.0 # Velocity for inertia
def handle_scroll(self, bounds: rl.Rectangle, content: rl.Rectangle) -> rl.Vector2:
mouse_pos = rl.get_mouse_position()
# Handle dragging logic
if rl.check_collision_point_rec(mouse_pos, bounds) and rl.is_mouse_button_pressed(rl.MouseButton.MOUSE_BUTTON_LEFT):
if self._scroll_state == ScrollState.IDLE:
self._scroll_state = ScrollState.DRAGGING_CONTENT
if self._show_vertical_scroll_bar:
scrollbar_width = rl.gui_get_style(rl.GuiControl.LISTVIEW, rl.GuiListViewProperty.SCROLLBAR_WIDTH)
scrollbar_x = bounds.x + bounds.width - scrollbar_width
if mouse_pos.x >= scrollbar_x:
self._scroll_state = ScrollState.DRAGGING_SCROLLBAR
self._last_mouse_y = mouse_pos.y
self._velocity_y = 0.0 # Reset velocity when drag starts
if self._scroll_state != ScrollState.IDLE:
if rl.is_mouse_button_down(rl.MouseButton.MOUSE_BUTTON_LEFT):
delta_y = mouse_pos.y - self._last_mouse_y
if self._scroll_state == ScrollState.DRAGGING_CONTENT:
self._offset.y += delta_y
else:
delta_y = -delta_y
self._last_mouse_y = mouse_pos.y
self._velocity_y = delta_y # Update velocity during drag
else:
self._scroll_state = ScrollState.IDLE
# Handle mouse wheel scrolling
wheel_move = rl.get_mouse_wheel_move()
if self._show_vertical_scroll_bar:
self._offset.y += wheel_move * (MOUSE_WHEEL_SCROLL_SPEED - 20)
rl.gui_scroll_panel(bounds, rl.ffi.NULL, content, self._offset, self._view)
else:
self._offset.y += wheel_move * MOUSE_WHEEL_SCROLL_SPEED
# Apply inertia (continue scrolling after mouse release)
if self._scroll_state == ScrollState.IDLE:
self._offset.y += self._velocity_y
self._velocity_y *= INERTIA_FRICTION # Slow down velocity over time
# Stop scrolling when velocity is low
if abs(self._velocity_y) < MIN_VELOCITY:
self._velocity_y = 0.0
# Ensure scrolling doesn't go beyond bounds
max_scroll_y = max(content.height - bounds.height, 0)
self._offset.y = max(min(self._offset.y, 0), -max_scroll_y)
return self._offset