extends Control const VELOCITY_DECAYING_FACTOR: float = 5.5 const BINNING_THRESHOLD: float = 0.75 const BINNING_ADJUST_P: float = 5.0 export var min_value: int setget set_min_value export var max_value: int setget set_max_value var num_of_values: int func set_min_value(value: int): min_value = value num_of_values = max_value - min_value + 1 func set_max_value(value: int): max_value = value num_of_values = max_value - min_value + 1 var pointer: Dictionary var value: float = 0.0 var anchor: float = 0.0 var current_value_base_position: float var next_value_base_position: float var previous_value_base_position: float func _ready(): pointer = { index = -1, initial_position = Vector2.ZERO, current_position = Vector2.ZERO, velocity = Vector2.ZERO, is_active = false, } current_value_base_position = ($value as Label).rect_position.y next_value_base_position = ($value_next as Label).rect_position.y previous_value_base_position = ($value_previous as Label).rect_position.y func _process(delta: float): # @DAM TODO It's weird that we use '-value'... check maths. var scroll_unit_height := ($value as Label).rect_size.y var normalized_value := - value / scroll_unit_height var normalized_int_value := round(normalized_value) as int # $debug.text = "%s | %s" % [normalized_value, normalized_int_value] pointer.velocity *= clamp((1.0 - VELOCITY_DECAYING_FACTOR * delta), 0.0, 1.0) if pointer.is_active: value = anchor + (pointer.current_position.y - pointer.initial_position.y) elif is_zero_approx(pointer.velocity.y) == false: value += pointer.velocity.y * delta if abs(pointer.velocity.y) < BINNING_THRESHOLD * scroll_unit_height: var fix := ((normalized_int_value as float) - normalized_value) * scroll_unit_height value -= fix * BINNING_ADJUST_P * delta var logic_value := min_value + fposmod(normalized_int_value, num_of_values) var logic_next_value := min_value + fposmod(normalized_int_value + 1, num_of_values) var logic_previous_value := min_value + fposmod(normalized_int_value - 1, num_of_values) $value.text = "%d" % logic_value $value_next.text = "%d" % logic_next_value $value_previous.text = "%d" % logic_previous_value var normalized_displacement := normalized_value - normalized_int_value var displacement := normalized_displacement * scroll_unit_height ($value as Label).rect_position.y = current_value_base_position - displacement ($value_previous as Label).rect_position.y = previous_value_base_position - displacement ($value_next as Label).rect_position.y = next_value_base_position - displacement ($value_next as Label).modulate.a = normalized_displacement + 0.5 ($value_previous as Label).modulate.a = 0.5 - normalized_displacement var current_pos := value var turn_over := num_of_values * scroll_unit_height if current_pos >= turn_over || current_pos < 0.0: value = fposmod(current_pos, turn_over) func _gui_input(event: InputEvent): # @DAM TODO When we release the pointer, we will receive an event that will se the 'current_position' as the last 'touch.position'. if event is InputEventScreenTouch: # if (event is InputEventScreenTouch && pointer.is_active && pointer.index == event.index # || event is InputEventScreenTouch && pointer.is_active == false): var touch := event as InputEventScreenTouch pointer.is_active = event.pressed pointer.current_position = touch.position if pointer.is_active: pointer.index = touch.index pointer.initial_position = touch.position anchor = value else: pointer.index = -1 if event is InputEventScreenDrag && event.index == pointer.index: var drag := event as InputEventScreenDrag pointer.current_position = drag.position pointer.velocity = drag.speed func set_value(value: int): breakpoint # @DAM TODO func get_value() -> int: breakpoint # @DAM TODO return 0