aboutsummaryrefslogtreecommitdiff
path: root/option_set
diff options
context:
space:
mode:
Diffstat (limited to 'option_set')
-rw-r--r--option_set/option_set_list.gd142
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