0 votes

Hello,

currently i am trying to scroll trough a list of entries via mousewheel up or down. First i looked for code that would go through the different buttons focus and in the end i found this https://godotengine.org/qa/5990/follow-focus-going-through-entries-inside-scroll-container . Now i can go through the different buttons with the tab key or shitf+tab. But i want to cycle trough them with the mousewheel. I found out that you can simulate a keypress via code https://godotengine.org/qa/53622/how-to-sumalate-a-key-press
The problem here now is that the key can only be pressed once and then never again.
Next problem is that i can't combine they KEYSHIFT + KEYTAB keys so i go to the previous focus.

How can i simulate the keypress so i can use the mousewheel? How do i combine the different keys? Is this even the right approach?


Scene Setup

Container
    -ScrollContainer
        -VboxContainer
            -Button1
            -Button2
            -Button3

Code

extends VBoxContainer



onready var _scroll_container = get_parent()
onready var button_1 = $Button


func _ready():
    button_1.grab_focus()
    for child in get_children():
        child.connect("focus_entered", self, "_on_focus_change")

func _input(event):
    if event is InputEventMouseButton and event.pressed:
        if event.button_index == BUTTON_WHEEL_UP :
            simulate_keypress_tab_shift()
        elif event.button_index == BUTTON_WHEEL_DOWN:
            simulate_keypress_tab()


func _on_focus_change():
    var focused = get_focus_owner()
    var focus_size = focused.rect_size.y
    var focus_top = focused.rect_position.y

    var scroll_size = _scroll_container.rect_size.y
    var scroll_top = _scroll_container.get_v_scroll()
    var scroll_bottom = scroll_top + scroll_size - focus_size

    if focus_top < scroll_top:
        _scroll_container.set_v_scroll(focus_top)

    if focus_top > scroll_bottom:
        var scroll_offset = scroll_top + focus_top - scroll_bottom
        _scroll_container.set_v_scroll(scroll_offset)

func simulate_keypress_tab():
    var a = InputEventKey.new()
    a.scancode = KEY_TAB
    a.pressed = true # change to false to simulate a key release
    Input.parse_input_event(a)

func simulate_keypress_tab_shift():
    var a = InputEventKey.new()
    a.scancode = KEY_SHIFT + KEY_TAB 
    a.pressed = true # change to false to simulate a key release
    Input.parse_input_event(a)
Godot version 3.2.2.stable
in Engine by (21 points)

2 Answers

0 votes
Best answer

Well i got it to work now. Was again way simpler then i thought it should be. I now can scroll through my entries of the vboxcontainer via mousewheel

extends VBoxContainer


onready var _scroll_container = get_parent()
onready var button_1 = $Button
onready var label_1 = get_parent().get_parent().get_node("Label")

var input = InputEventAction.new()

var scroll_up : bool = false
var scroll_down : bool = false


func _ready():
    button_1.grab_focus()
    for child in get_children():
        child.connect("focus_entered", self, "_on_focus_change")


func _input(event):
    if event is InputEventMouseButton:
        if event.button_index == BUTTON_WHEEL_UP :
            scroll_up = true
        elif event.button_index == BUTTON_WHEEL_DOWN:
            scroll_down = true


func _process(_delta):
    if scroll_up:
        input.action = "ui_focus_prev"
        input.pressed = true
        scroll_up = false
    elif scroll_down:
        input.action = "ui_focus_next"
        input.pressed = true
        scroll_down = false
    else:
        input.pressed = false
    Input.parse_input_event(input)


func _on_focus_change():
    var focused = get_focus_owner()
    var focus_size = focused.rect_size.y
    var focus_top = focused.rect_position.y

    var scroll_size = _scroll_container.rect_size.y
    var scroll_top = _scroll_container.get_v_scroll()
    var scroll_bottom = scroll_top + scroll_size - focus_size

    if focus_top < scroll_top:
        _scroll_container.set_v_scroll(focus_top)

    if focus_top > scroll_bottom:
        var scroll_offset = scroll_top + focus_top - scroll_bottom
        _scroll_container.set_v_scroll(scroll_offset)
by (21 points)
selected by
+1 vote

You can map the mousewheel to the ui_up and ui_down Actions. To do that, go to your project settings, second tab (InputMap), locate ui_up and down, and add the right entries with the +.

Alternatively, if you only want the mousewheel to behave like that in some circumstances. You could make two new inputs, Fruit_up and Fruit_down, map them to the wheel, and then listen to them :
func _unhandled_input(event):
. if event.is_action_pressed("Fruit_up") && time_is_right:
. . get_tree().set_input_as_handled() //stop event propagation
. . var action := InputEventAction.new()
. . action.action = "ui_up"
. . action.pressed = true
. . Input.parse_input_event(action)
. elif event.is_action_pressed("Fruit_down") && time_is_right:
. . get_tree().set_input_as_handled()
. . var action := InputEventAction.new()
. . action.action = "ui_down"
. . action.pressed = true
. . Input.parse_input_event(action)
With time_is_right being a variable telling you if you want the scrollwheel to handle focus.

by (2,276 points)

i tried binding the mouswheel up/down to the ui_up/down actions at first but sadly that does not work because the mousewheel is never really being pressed. This gets explained in this post i found https://github.com/godotengine/godot/issues/3340
this seem especiall weird to me since you are even allowed to assign the mousewheel up/down to any action but it does not work in the end


the problem more lies in this part of the code. and i don't know how to do that multiple times. because right now if i press mousewheel down it only executes this func once. what i mean by that is that i can set the focus from button1 to button2 but not from buttton2 to button3. it stops at button2

func simulate_keypress_tab():
    var a = InputEventKey.new()
    a.scancode = KEY_TAB
    a.pressed = true # change to false to simulate a key release
    Input.parse_input_event(a)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.