diff options
Diffstat (limited to 'ui/touch_vertical_container')
| -rw-r--r-- | ui/touch_vertical_container/touch_vertical_container.gd | 118 | ||||
| -rw-r--r-- | ui/touch_vertical_container/touch_vertical_container.tscn | 19 |
2 files changed, 137 insertions, 0 deletions
diff --git a/ui/touch_vertical_container/touch_vertical_container.gd b/ui/touch_vertical_container/touch_vertical_container.gd new file mode 100644 index 0000000..8f87338 --- /dev/null +++ b/ui/touch_vertical_container/touch_vertical_container.gd @@ -0,0 +1,118 @@ +extends ScrollContainer +class_name TouchVerticalContainer + +const POINTER_VELOCITY_DECAYING_FACTOR: float = PI +const POINTER_VELOCITY_BOOST_FACTOR: float = 1.25 + +var is_pointer_dragging := false +var pointer_drag_velocity := 0.0 +var when_last_dragged := 0 +var exclude_controls := [] + +onready var controls = get_node("controls") + + +func _ready(): + assert(controls != null, "TouchVerticalContainer failed to get 'controls' node.") + + var item_list_separation := float(controls.get_constant("separation")) + + for it in controls.get_children(): + it = it as Control + if exclude_controls.has(it.name): + continue + + var sensor = PointerInputSensor.new() + it.add_child(sensor) + + sensor.name = "sensor" + sensor.anchor_right = 1.0 + sensor.anchor_bottom = 1.0 + sensor.margin_top = - item_list_separation / 2.0 + sensor.margin_bottom = item_list_separation / 2.0 + + 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 _process(delta: float): + # 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) + self.scroll_vertical -= pointer_drag_velocity * delta + + +func pointer_input_on_press_handler(pointer: PointerInputSensor.PointerInputData): + is_pointer_dragging = true + grab_focus() + + +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 + self.scroll_vertical -= 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): + # Get last leaf node. + var root := pointer.target.get_parent() as Control + var leaf := root as Node + while leaf.get_child_count() > 0: + leaf = leaf.get_child(leaf.get_child_count() - 1) + + # Navigate backwards from leaf to root until we find a node accepting the input. + var tried_leaf_as_root := false + while leaf != root || tried_leaf_as_root == false: + tried_leaf_as_root = leaf == root # Allow a final iteration cycle when leaf reaches root. + var node := leaf + + if node is PointerInputSensor \ + || node is Control == false \ + || node.mouse_filter == MOUSE_FILTER_IGNORE \ + || node.visible == false \ + || node.get_global_rect().has_point(pointer.current_position) == false: + # Get next node to be processed. + var leaf_index_in_parent := leaf.get_position_in_parent() + var parent := leaf.get_parent() + if leaf_index_in_parent == 0: + leaf = parent + else: + leaf = parent.get_child(leaf_index_in_parent - 1) + # Drill down into the new tree branch. + while leaf.get_child_count() > 0: + leaf = leaf.get_child(leaf.get_child_count() - 1) + continue + + var control: Control = node + if control is CheckBox || control is CheckButton || (control is Button && control.toggle_mode == true): + control.pressed = !control.pressed + + control.grab_focus() + control.emit_signal("button_down") + control.emit_signal("pressed") + control.emit_signal("button_up") + control.connect("focus_exited", pointer.target, "set_visible", [true], CONNECT_ONESHOT) + pointer.target.visible = false + break + + +func pointer_input_on_scroll_handler(pointer: PointerInputSensor.PointerInputData): + var target := self + target._gui_input(pointer.event) + + diff --git a/ui/touch_vertical_container/touch_vertical_container.tscn b/ui/touch_vertical_container/touch_vertical_container.tscn new file mode 100644 index 0000000..e741e8a --- /dev/null +++ b/ui/touch_vertical_container/touch_vertical_container.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://ui/touch_vertical_container/touch_vertical_container.gd" type="Script" id=1] + +[node name="touch_vertical_container" type="ScrollContainer"] +anchor_right = 1.0 +anchor_bottom = 1.0 +mouse_filter = 2 +scroll_horizontal_enabled = false +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="controls" type="VBoxContainer" parent="."] +margin_right = 1080.0 +margin_bottom = 1920.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 |
