diff options
Diffstat (limited to 'option_set')
| -rw-r--r-- | option_set/option_set_list.gd | 142 |
1 files changed, 87 insertions, 55 deletions
diff --git a/option_set/option_set_list.gd b/option_set/option_set_list.gd index cad9e9c..7a61161 100644 --- a/option_set/option_set_list.gd +++ b/option_set/option_set_list.gd @@ -1,25 +1,34 @@ extends Control class_name OptionSetList +const POINTER_VELOCITY_DECAYING_FACTOR: float = PI +const POINTER_VELOCITY_BOOST_FACTOR: float = 1.25 +const EXACT_SELECTION: bool = false + signal item_selected # (idx: int, text: String) signal nothing_selected # () -export var autowrap := true +export var autowrap := true + +var v_scroll_bar : VScrollBar +var sensor : PointerInputSensor +var is_pointer_dragging := false +var pointer_drag_velocity := 0.0 +var when_last_dragged := 0 -var vscrollbar : VScrollBar -var labels : Control -var labels_end_positions: Array -var labels_sizes : Array +var labels : Control +var labels_end_positions: Array +var labels_sizes : Array -var items : Array -var selected_idx := -1 -var is_dirty := true +var items : Array +var selected_idx := -1 +var is_dirty := true -var normal_style : StyleBoxFlat -var selected_style : StyleBoxFlat -var border_size := 5 +var normal_style : StyleBoxFlat +var selected_style : StyleBoxFlat +var border_size := 5 -onready var font : Font = get_font("font") +onready var font : Font = get_font("font") func _init(): @@ -27,19 +36,25 @@ func _init(): self.anchor_bottom = 1.0 self.rect_clip_content = true - labels = Control.new() + labels = Control.new() labels.anchor_right = 1.0 labels.anchor_bottom = 1.0 labels.mouse_filter = Control.MOUSE_FILTER_IGNORE labels.name = "labels" add_child(labels) - vscrollbar = VScrollBar.new() - vscrollbar.anchor_left = 1.0 - vscrollbar.anchor_bottom = 1.0 - vscrollbar.grow_horizontal = Control.GROW_DIRECTION_BEGIN - vscrollbar.name = "vscrollbar" - add_child(vscrollbar) + v_scroll_bar = VScrollBar.new() + v_scroll_bar.anchor_left = 1.0 + v_scroll_bar.anchor_bottom = 1.0 + v_scroll_bar.grow_horizontal = Control.GROW_DIRECTION_BEGIN + v_scroll_bar.name = "v_scroll_bar" + add_child(v_scroll_bar) + + sensor = PointerInputSensor.new() + sensor.anchor_right = 1.0 + sensor.anchor_bottom = 1.0 + sensor.name = "sensor" + add_child(sensor) normal_style = StyleBoxFlat.new() normal_style.border_width_bottom = border_size @@ -52,6 +67,12 @@ func _init(): selected_style.bg_color = Color.dimgray connect("resized", self, "mark_as_dirty") + + sensor.connect("on_press", self, "pointer_input_on_press_handler") + sensor.connect("on_drag", self, "pointer_input_on_drag_handler") + sensor.connect("on_end_drag", self, "pointer_input_on_end_drag_handler") + sensor.connect("on_click", self, "pointer_input_on_click_handler") + sensor.connect("on_scroll", self, "pointer_input_on_scroll_handler") func mark_as_dirty(): @@ -150,14 +171,14 @@ func _process(delta): var ratio := 1.0 if items.size() > 0: - ratio = vscrollbar.max_value / float(labels_end_positions.back()) + ratio = v_scroll_bar.max_value / float(labels_end_positions.back()) - vscrollbar.min_value = 0 - vscrollbar.max_value = labels.rect_size.y - vscrollbar.visible = ratio < 1.0 - vscrollbar.page = ratio * (vscrollbar.max_value - vscrollbar.min_value) + v_scroll_bar.min_value = 0 + v_scroll_bar.max_value = labels.rect_size.y + v_scroll_bar.visible = ratio < 1.0 + v_scroll_bar.page = ratio * (v_scroll_bar.max_value - v_scroll_bar.min_value) - var scrollbar_offset := vscrollbar.value + var scrollbar_offset := v_scroll_bar.value var labels_offset := scrollbar_offset / ratio var idx_offset := labels_end_positions.bsearch(labels_offset) @@ -180,7 +201,12 @@ func _process(delta): idx += 1 - labels.margin_right = -vscrollbar.rect_size.x if vscrollbar.visible else 0.0 + labels.margin_right = - v_scroll_bar.rect_size.x if v_scroll_bar.visible else 0.0 + + # Apply drag movement inertia. + if is_pointer_dragging == false && abs(pointer_drag_velocity) > 0.5: + pointer_drag_velocity *= clamp((1.0 - POINTER_VELOCITY_DECAYING_FACTOR * delta), 0.0, 1.0) + v_scroll_bar.value -= pointer_drag_velocity * delta func get_item_at_position(mouse_position: Vector2) -> int: @@ -190,9 +216,9 @@ func get_item_at_position(mouse_position: Vector2) -> int: var ratio := 1.0 if items.size() > 0: - ratio = vscrollbar.max_value / float(labels_end_positions.back()) + ratio = v_scroll_bar.max_value / float(labels_end_positions.back()) - var scrollbar_offset := vscrollbar.value + var scrollbar_offset := v_scroll_bar.value var labels_offset := scrollbar_offset / ratio var position := mouse_position.y + labels_offset var item_idx := labels_end_positions.bsearch(position) @@ -210,34 +236,40 @@ func unselect(): emit_signal("nothing_selected") -#func _input(event: InputEvent): -## @DAM Test and debug code. Delete when ready. -# if event is InputEventKey: -# if event.pressed && event.scancode == KEY_C: -# clear_items() -# if event.pressed && event.scancode == KEY_F: -# for idx in range(1, 26): -# if idx % 10 == 0: -# add_item("-- item %06d : This is the longest item of all, but eventually stops. --" % idx) -# else: -# add_item("-- item %06d --" % idx) +func pointer_input_on_press_handler(pointer: PointerInputSensor.PointerInputData): + is_pointer_dragging = true + grab_focus() -func _gui_input(event: InputEvent): - - # @DAM A bug on GODOT-3.X makes events from non-mouse-emulated pointers (index > 0) unreliable. - if event is InputEventScreenTouch || event is InputEventScreenDrag: - if event.index != 0: - return - - if event is InputEventMouseButton == false: - return - - if event is InputEventScreenTouch && event.pressed == false: - return - - var item_idx := get_item_at_position(get_local_mouse_position()) - if item_idx >= 0 && item_idx < items.size(): - select(item_idx) +func pointer_input_on_drag_handler(pointer: PointerInputSensor.PointerInputData): + is_pointer_dragging = true + var reported_velocity_abs := abs(pointer.velocity.y) + var relative_velocity := pointer.relative_position.y * Engine.get_frames_per_second() + var relative_velocity_abs := abs(relative_velocity) + pointer_drag_velocity = pointer.velocity.y if reported_velocity_abs > relative_velocity_abs else relative_velocity + v_scroll_bar.value -= pointer.relative_position.y + when_last_dragged = OS.get_ticks_msec() + + +func pointer_input_on_end_drag_handler(pointer: PointerInputSensor.PointerInputData): + is_pointer_dragging = false + if OS.get_ticks_msec() - when_last_dragged > 20: + pointer_drag_velocity = 0.0 + else: + pointer_drag_velocity *= POINTER_VELOCITY_BOOST_FACTOR + + +func pointer_input_on_click_handler(pointer: PointerInputSensor.PointerInputData): + var selected_idx := get_item_at_position(pointer.current_position - rect_global_position) + if selected_idx >= 0: + select(selected_idx) + emit_signal("item_selected", selected_idx) + else: + unselect() + emit_signal("nothing_selected") + + +func pointer_input_on_scroll_handler(pointer: PointerInputSensor.PointerInputData): + pointer_drag_velocity -= pointer.scroll * POINTER_VELOCITY_BOOST_FACTOR * float(OS.get_screen_dpi()) / 2.54 |
