I cant interact with my scrollbox widget using a controller

Hello guys i have a custom ui where i assembled a button and scrollbox widget

When player click on a button it shows the corresponding text with a scrollbox, the interaction with the buttons works perfectly but i cant get any interaction with the scrollbox using a controller

It works with my keyboard but not with the controller

Thanks and have a nice day

Hey! To add controller support enable this in your widget.

Thanks for your answer !

Unfortunately it doesnt work, when i click on my button, the text shows up but its not scrollable

tldr_hoverable_button := class:
    Widget : Resume_Button = Resume_Button{}
    CloseEvent<public> : event()
    var Owner<public> : ?player_rulebook_canvas = false

    GetButton<public>() : button =
        B := button:
            Slot := button_slot:
                HorizontalAlignment := horizontal_alignment.Fill
                VerticalAlignment := vertical_alignment.Fill
                Widget := Widget
        spawn{HandleButton(B)}
        B

    HandleButton(B : button)<suspends> : void =
        race:
            CloseEvent.Await()
            loop:
                B.HighlightEvent().Await()
                if (Canvas := Owner?):
                    Canvas.ResetAllHoverStates()
                set Widget.IsHovering = true
            loop:
                B.UnhighlightEvent().Await()
                set Widget.IsHovering = false

bonus_hoverable_button := class:
    Widget : Bonus_Button = Bonus_Button{}
    CloseEvent<public> : event()
    var Owner<public> : ?player_rulebook_canvas = false

    GetButton<public>() : button =
        B := button:
            Slot := button_slot:
                HorizontalAlignment := horizontal_alignment.Fill
                VerticalAlignment := vertical_alignment.Fill
                Widget := Widget
        spawn{HandleButton(B)}
        B

    HandleButton(B : button)<suspends> : void =
        race:
            CloseEvent.Await()
            loop:
                B.HighlightEvent().Await()
                if (Canvas := Owner?):
                    Canvas.ResetAllHoverStates()
                set Widget.IsHovering = true
            loop:
                B.UnhighlightEvent().Await()
                set Widget.IsHovering = false


rulebook_quit_hoverable_button := class:
    Widget : QUIT_Button = QUIT_Button{}
    CloseEvent<public> : event()

    GetButton<public>() : button =
        B := button:
            Slot := button_slot:
                HorizontalAlignment := horizontal_alignment.Fill
                VerticalAlignment := vertical_alignment.Fill
                Widget := Widget
        spawn{HandleButton(B)}
        B

    HandleButton(B : button)<suspends> : void =
        race:
            CloseEvent.Await()
            loop:
                B.HighlightEvent().Await()
                set Widget.isHovering = true
            loop:
                B.UnhighlightEvent().Await()
                set Widget.isHovering = false


rulebook_category<public> := enum:
    TLDR
    Bonus
    


rulebook_ui_device<public> := class(creative_device):


    @editable
    RulebookOpenTrigger : input_trigger_device = input_trigger_device{}

    @editable
    RulebookCloseTrigger : input_trigger_device = input_trigger_device{}

    @editable
    RulebookBackgroundTexture : ?texture = false

    @editable
    BackgroundMaterial : ?material = false


    @editable
    BackgroundColor : color = color{R := 0.0, G := 0.0, B := 0.0}

    @editable
    BorderColorStyle : color = color{R := 0.502, G := 0.0, B := 0.502}


    var PlayerCanvasMap : [player]player_rulebook_canvas = map{}


    OnBegin<override>()<suspends> : void =
        Print("=== Rulebook System Initializing ===")

        RulebookOpenTrigger.PressedEvent.Subscribe(OnOpenPressed)
        RulebookCloseTrigger.PressedEvent.Subscribe(OnClosePressed)

        GetPlayspace().PlayerAddedEvent().Subscribe(OnPlayerAdded)
        GetPlayspace().PlayerRemovedEvent().Subscribe(OnPlayerRemoved)

        for (Player : GetPlayspace().GetPlayers()):
            if (Agent := agent[Player]):
                RulebookOpenTrigger.Register(Agent)
                RulebookCloseTrigger.Register(Agent)

        Print("=== Rulebook System Ready ===")

    # === EVENT HANDLERS ===

    OnPlayerAdded(Player : player) : void =
        if (Agent := agent[Player]):
            RulebookOpenTrigger.Register(Agent)
            RulebookCloseTrigger.Register(Agent)

    OnPlayerRemoved(Player : player) : void =
        if (Canvas := PlayerCanvasMap[Player]):
            Canvas.CloseRulebook()

        var NewMap : [player]player_rulebook_canvas = map{}
        for (Key -> Value : PlayerCanvasMap, Key <> Player):
            if (set NewMap[Key] = Value) {}
        set PlayerCanvasMap = NewMap

    OnOpenPressed(Agent : agent) : void =
        if (Player := player[Agent]):
            if (Canvas := PlayerCanvasMap[Player]):
                Canvas.OpenRulebook()
            else:
                NewCanvas := player_rulebook_canvas{
                    Player := Player
                    RulebookDevice := Self
                }
                if (set PlayerCanvasMap[Player] = NewCanvas):
                    NewCanvas.OpenRulebook()

    OnClosePressed(Agent : agent) : void =
        if (Player := player[Agent]):
            if (Canvas := PlayerCanvasMap[Player]):
                Canvas.CloseRulebook()


player_rulebook_canvas<public> := class:
    Player<public> : player
    RulebookDevice<public> : rulebook_ui_device

    var MainCanvas : ?canvas = false
    var MainOverlay : ?overlay = false
    var TextContainer : ?overlay = false
    var ActiveTextWidget : ?widget = false
    var SidebarWidget : ?widget = false
    var CurrentCategory : rulebook_category = rulebook_category.TLDR
    var CategoryButtons : [rulebook_category]button = map{}
    var CloseBtn : ?button = false
    var IsOpen : logic = false
    ButtonCloseEvent : event() = event(){}

    # Button widgets from Regles module — toggled via Is[X]Clicked
    TLDRBtnWidget : Resume_Button = Resume_Button{}
    BonusBtnWidget : Bonus_Button = Bonus_Button{}

    QuitBtnWidget : QUIT_Button = QUIT_Button{}

    # Text widgets from Regles module — toggled via Show[X]Text
    TLDRTextWidget : TLDR_Text = TLDR_Text{}

    BonusTextWidget : Bonus_Text = Bonus_Text{}
    RoadmapTextWidget : Roadmap_Text = Roadmap_Text{}


    ToggleRulebook<public>() : void =
        if (IsOpen = true):
            CloseRulebook()
        else:
            OpenRulebook()

    OpenRulebook<public>() : void =
        if (IsOpen = true):
            return

        if (PlayerUI := GetPlayerUI[Player]):
            Canvas := BuildRulebookCanvas()
            set MainCanvas = option{Canvas}
            set IsOpen = true

            PlayerUI.AddWidget(Canvas, player_ui_slot{InputMode := ui_input_mode.All, ZOrder := 100})

            FocusActiveTextWidget()
            spawn{HandleButtonClicks()}

    CloseRulebook<public>() : void =
        if (IsOpen = false):
            return

        ButtonCloseEvent.Signal()
        if (PlayerUI := GetPlayerUI[Player]):
            if (Canvas := MainCanvas?):
                PlayerUI.RemoveWidget(Canvas)

        set MainCanvas = false
        set MainOverlay = false
        set TextContainer = false
        set ActiveTextWidget = false
        set IsOpen = false
        set CategoryButtons = map{}

    # ==================== UI BUILDING ====================

    BuildRulebookCanvas() : canvas =
        MainOvl := BuildMainOverlay()

        canvas{
            Slots := array{
                canvas_slot{
                    Anchors := anchors{Minimum := vector2{X := 0.5, Y := 0.5}, Maximum := vector2{X := 0.5, Y := 0.5}}
                    Alignment := vector2{X := 0.5, Y := 0.5}
                    SizeToContent := true
                    Widget := MainOvl
                }
            }
        }

    BuildMainOverlay() : overlay =
        CurrentWidth := 1012.0
        CurrentHeight := 805.0

        BgWidth := CurrentWidth
        BgHeight := CurrentHeight
        BackgroundWidget := if (BgMaterial := RulebookDevice.BackgroundMaterial?):
            material_block{
                DefaultImage := BgMaterial
                DefaultDesiredSize := vector2{X := BgWidth, Y := BgHeight}
            }
        else:
            color_block{
                DefaultColor := RulebookDevice.BackgroundColor
                DefaultDesiredSize := vector2{X := BgWidth, Y := BgHeight}
                DefaultOpacity := 1.0
            }

        PanelBorder := color_block{
            DefaultColor := RulebookDevice.BorderColorStyle
            DefaultOpacity := 1.0
            DefaultDesiredSize := vector2{X := BgWidth + 10.0, Y := BgHeight + 10.0}
        }

        Header := BuildHeader()

        SeparatorLine := color_block{
            DefaultColor := RulebookDevice.BorderColorStyle
            DefaultOpacity := 1.0
            DefaultDesiredSize := vector2{X := BgWidth + 10.0, Y := 5.0}
        }

        ButtonBar := BuildCategorySidebar()
        set SidebarWidget = option{ButtonBar}

        InitTextWidgets()
        TextOverlay := BuildTextOverlay()
        set TextContainer = option{TextOverlay}

        CloseBtnWidget := BuildCloseButton()
        set CloseBtn = option{CloseBtnWidget}

        CompactPanel := overlay{
            Slots := array{
                overlay_slot{
                    Widget := PanelBorder
                    HorizontalAlignment := horizontal_alignment.Center
                    VerticalAlignment := vertical_alignment.Center
                },
                overlay_slot{
                    Widget := BackgroundWidget
                    HorizontalAlignment := horizontal_alignment.Center
                    VerticalAlignment := vertical_alignment.Center
                },
                overlay_slot{
                    Widget := Header
                    HorizontalAlignment := horizontal_alignment.Center
                    VerticalAlignment := vertical_alignment.Top
                    Padding := margin{Left:= 15.0, Top := 15.0}
                },
                 overlay_slot{
                    Widget := CloseBtnWidget
                    HorizontalAlignment := horizontal_alignment.Right
                    VerticalAlignment := vertical_alignment.Top
                    Padding := margin{ Right := 10.0}
                },
                overlay_slot{
                    Widget := SeparatorLine
                    HorizontalAlignment := horizontal_alignment.Center
                    VerticalAlignment := vertical_alignment.Top
                    Padding := margin{Top := 90.0}
                },
                overlay_slot{
                    Widget := ButtonBar
                    HorizontalAlignment := horizontal_alignment.Center
                    VerticalAlignment := vertical_alignment.Top
                    Padding := margin{Top := 130.0}
                },
                overlay_slot{
                    Widget := TextOverlay
                    HorizontalAlignment := horizontal_alignment.Center
                    VerticalAlignment := vertical_alignment.Top
                    Padding := margin{Top := 310.0}
                }

            }
        }

        MainOvl := overlay{
            Slots := array{
                overlay_slot{
                    Widget := CompactPanel
                    HorizontalAlignment := horizontal_alignment.Center
                    VerticalAlignment := vertical_alignment.Center
                }
            }
        }
        set MainOverlay = option{CompactPanel}
        MainOvl

    BuildHeader() : Rulebook_text =
        Rulebook_text{}

    BuildCategorySidebar() : stack_box =
        TLDRHandler := tldr_hoverable_button{Widget := TLDRBtnWidget, CloseEvent := ButtonCloseEvent}
        TLDRBtn := TLDRHandler.GetButton()
        if (set CategoryButtons[rulebook_category.TLDR] = TLDRBtn) {}

        BonusHandler := bonus_hoverable_button{Widget := BonusBtnWidget, CloseEvent := ButtonCloseEvent}
        BonusBtn := BonusHandler.GetButton()
        if (set CategoryButtons[rulebook_category.Bonus] = BonusBtn) {}

        RoadmapHandler := roadmap_hoverable_button{Widget := RoadmapBtnWidget, CloseEvent := ButtonCloseEvent}
        RoadmapBtn := RoadmapHandler.GetButton()
        if (set CategoryButtons[rulebook_category.Roadmap] = RoadmapBtn) {}

        Spacing := margin{Left := 3.0, Right := 3.0}

        Row1 := stack_box{
            Orientation := orientation.Horizontal
            Slots := array{
                stack_box_slot{Widget := TLDRBtn, HorizontalAlignment := horizontal_alignment.Center, VerticalAlignment := vertical_alignment.Center, Padding := Spacing}
        }

        Row2 := stack_box{
            Orientation := orientation.Horizontal
            Slots := array{
 
                stack_box_slot{Widget := BonusBtn, HorizontalAlignment := horizontal_alignment.Center, VerticalAlignment := vertical_alignment.Center, Padding := Spacing}

            }
        }

        stack_box{
            Orientation := orientation.Vertical
            Slots := array{
                stack_box_slot{
                    Widget := Row1
                    HorizontalAlignment := horizontal_alignment.Center
                    Padding := margin{Bottom := 3.0}
                }
                stack_box_slot{
                    Widget := Row2
                    HorizontalAlignment := horizontal_alignment.Center
                }
            }
        }

    BuildCloseButton() : button =
        QuitHandler := rulebook_quit_hoverable_button{Widget := QuitBtnWidget, CloseEvent := ButtonCloseEvent}
        QuitHandler.GetButton()

    InitTextWidgets() : void =
        ResetAllButtons()
        ActivateButtonForCategory(CurrentCategory)
        ResetAllTextWidgets()
        ActivateTextForCategory(CurrentCategory)

    BuildTextOverlay() : overlay =
        ActiveText := GetTextWidgetForCategory(CurrentCategory)
        set ActiveTextWidget = option{ActiveText}
        overlay{
            Slots := array{
                overlay_slot{Widget := ActiveText}
            }
        }

    ResetAllButtons() : void =
        set TLDRBtnWidget.IsTLDRClicked = 0.0
        set BonusBtnWidget.IsBonusClicked = 0.0
   
        ResetAllHoverStates()

    ResetAllHoverStates() : void =
        set TLDRBtnWidget.IsHovering = false
        set BonusBtnWidget.IsHovering = false
        set QuitBtnWidget.isHovering = false

    ActivateButtonForCategory(Category : rulebook_category) : void =
        case (Category):
            rulebook_category.TLDR =>
                set TLDRBtnWidget.IsTLDRClicked = 1.0
            rulebook_category.Bonus =>
                set BonusBtnWidget.IsBonusClicked = 1.0
 

    GetTextWidgetForCategory(Category : rulebook_category) : widget =
        case (Category):
            rulebook_category.TLDR => TLDRTextWidget 
            rulebook_category.Bonus => BonusTextWidget


    ResetAllTextWidgets() : void =
        set TLDRTextWidget.ShowTLDRText = 0.0     
        set BonusTextWidget.ShowBonusText = 0.0


    ActivateTextForCategory(Category : rulebook_category) : void =
        case (Category):
            rulebook_category.TLDR =>
                set TLDRTextWidget.ShowTLDRText = 1.0
            rulebook_category.Bonus =>
                set BonusTextWidget.ShowBonusText = 1.0
            
    SwapActiveText() : void =
        if (Container := TextContainer?):
            if (OldText := ActiveTextWidget?):
                Container.RemoveWidget(OldText)
            ResetAllTextWidgets()
            ActivateTextForCategory(CurrentCategory)
            NewText := GetTextWidgetForCategory(CurrentCategory)
            Container.AddWidget(overlay_slot{Widget := NewText})
            set ActiveTextWidget = option{NewText}
            FocusActiveTextWidget()

    
    FocusWidgetDelayed(PlayerUI : player_ui, Target : widget)<suspends> : void =
        Sleep(0.2)
        PlayerUI.SetFocus(Target)

    FocusActiveTextWidget() : void =
        if (PlayerUI := GetPlayerUI[Player]):
            Print("text focused")
            Target := GetTextWidgetForCategory(CurrentCategory)
            spawn{FocusWidgetDelayed(PlayerUI, Target)}


    HandleButtonClicks()<suspends> : void =
        if:
            TLDRBtn := CategoryButtons[rulebook_category.TLDR]
            BonusBtn := CategoryButtons[rulebook_category.Bonus]
     
            CloseBtnRef := CloseBtn?
        then:
            race:
                ButtonCloseEvent.Await()

                loop:
                    CloseBtnRef.OnClick().Await()
                    CloseRulebook()

                loop:
                    TLDRBtn.OnClick().Await()
                    set CurrentCategory = rulebook_category.TLDR
                    ResetAllButtons()
                    ActivateButtonForCategory(CurrentCategory)
                    SwapActiveText()

                loop:
                    BonusBtn.OnClick().Await()
                    set CurrentCategory = rulebook_category.Bonus
                    ResetAllButtons()
                    ActivateButtonForCategory(CurrentCategory)
                    SwapActiveText()


This my code (i have more buttons, i just deleted 7 of them for better lisibility