unvestigate
Topic Author
Posts: 32
Joined: 17 Jan 2018, 09:55

Pause menu gamepad input suddenly stops working

21 Oct 2020, 13:30

Hi!

I have a pause menu with a few buttons. I'll post the XAML code for the pause menu user control below. The pause menu has a few buttons, namely Resume, Load Game and Exit. The pause menu works great 95% of the time, but occasionally I run into a problem where pressing a button on the gamepad no longer causes any of the buttons on the pause menu to be pressed. I can still use the gamepad to move the selection up/down among the buttons, but pressing A no longer executes the button code. Using the mouse or keyboard to press the buttons continues to work fine.

What makes the issue annoying is that it is hard to reproduce and usually only occurs after playing the game for a few minutes. I haven't been able to reliably reproduce it ever. I have traced the input from my own code in the debugger and made sure that Noesis::Key_GamepadAccept is sent to KeyDown and KeyUp.

I don't know exactly how to continue investigating this issue. Any ideas? I am currently on Noesis 2.2.6 if that matters. I am looking into updating to version 3 later, but that is not possible right now.
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
             xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
             xmlns:local="clr-namespace:Slide"
             xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions"
             mc:Ignorable="d"
             x:Class="Slide.PauseMenu"
             x:Name="PauseMenuControl"
             d:DesignHeight="1080" d:DesignWidth="1920" Background="#88000000"
             FontSize="20">

    <UserControl.Resources>
        <ResourceDictionary>
            <!-- We use this to convert the IsCampaignActive bool property to a visibility value. -->
            <BooleanToVisibilityConverter x:Key="BoolToVis" />
            
            <Storyboard x:Key="ShowPauseMenu">
                <ObjectAnimationUsingKeyFrames
                    Storyboard.TargetProperty="(UIElement.Visibility)"
                    Storyboard.TargetName="PauseMenuControl">
                    <!-- Visibility is an enum. This is how we set it to the "Visible" value. -->
                    <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
                </ObjectAnimationUsingKeyFrames>

                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="PauseMenuControl">
                    <LinearDoubleKeyFrame KeyTime="0" Value="0"/>
                    <LinearDoubleKeyFrame KeyTime="0:0:0.1" Value="1"/>
                </DoubleAnimationUsingKeyFrames>
            </Storyboard>

            <Storyboard x:Key="HidePauseMenu">
                <ObjectAnimationUsingKeyFrames
                    Storyboard.TargetProperty="(UIElement.Visibility)"
                    Storyboard.TargetName="PauseMenuControl">
                    <!-- Visibility is an enum. This is how we set it to the "Collapsed" value. -->
                    <DiscreteObjectKeyFrame KeyTime="0:0:0.1" Value="{x:Static Visibility.Collapsed}"/>
                </ObjectAnimationUsingKeyFrames>

                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="PauseMenuControl">
                    <LinearDoubleKeyFrame KeyTime="0" Value="1"/>
                    <LinearDoubleKeyFrame KeyTime="0:0:0.1" Value="0"/>
                </DoubleAnimationUsingKeyFrames>
            </Storyboard>
        </ResourceDictionary>
    </UserControl.Resources>

    <i:Interaction.Triggers>
        <!-- When State changes to PauseMenu, play the ShowPauseMenu storyboard. -->
        <ei:DataTrigger Binding="{Binding State}" Value="{x:Static local:InGameUIState.PauseMenu}">
            <!--<local:DebugOutputAction Output="Show pause menu"/>-->
            <ei:ControlStoryboardAction Storyboard="{StaticResource ShowPauseMenu}"/>
        </ei:DataTrigger>
        <!-- When State changes to something other than PauseMenu, play the HidePauseMenu storyboard. -->
        <ei:DataTrigger Binding="{Binding State}" Comparison="NotEqual" Value="{x:Static local:InGameUIState.PauseMenu}">
            <!--<local:DebugOutputAction Output="Hide pause menu"/>-->
            <ei:ControlStoryboardAction Storyboard="{StaticResource HidePauseMenu}"/>
        </ei:DataTrigger>
    </i:Interaction.Triggers>

    <Grid x:Name="LayoutRoot">
        <i:Interaction.Triggers>
            <ei:StoryboardCompletedTrigger Storyboard="{StaticResource ShowPauseMenu}">
                <noesis:SetFocusAction TargetName="ResumeButton"/>
            </ei:StoryboardCompletedTrigger>
        </i:Interaction.Triggers>
        
        <Grid.RowDefinitions>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="2*"/>
            <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>

        <Border Grid.Row="1" Grid.Column="1" Background="#FF474F54" BorderBrush="#FF2F3538" BorderThickness="2" CornerRadius="5">
            <StackPanel Margin="5" KeyboardNavigation.DirectionalNavigation="Cycle">
                <TextBlock HorizontalAlignment="Center" Margin="0,0,0,20" Foreground="#FFC9CCCF"
                           FontSize="30" Text="{Binding UILanguage.Resources[TEXT_UI_PAUSED], FallbackValue='Paused'}"/>
                <Button x:Name="ResumeButton" Margin="0,0,0,10" Command="{Binding PauseResume}" Content="{Binding UILanguage.Resources[TEXT_UI_RESUME], FallbackValue='Resume'}"/>
                <Button x:Name="LoadButton" Margin="0,0,0,10" Command="{Binding PauseLoadGame}" Content="{Binding UILanguage.Resources[TEXT_UI_LOAD_GAME], FallbackValue='Load game'}"
                        Visibility="{Binding IsCampaignActive, Converter={StaticResource BoolToVis}}"/>
                <Button x:Name="ExitButton" Command="{Binding PauseExit}" Content="{Binding UILanguage.Resources[TEXT_UI_EXIT], FallbackValue='Exit'}"/>
            </StackPanel>
        </Border>
    </Grid>
</UserControl>

Tags:
 
User avatar
sfernandez
Site Admin
Posts: 2254
Joined: 22 Dec 2011, 19:20

Re: Pause menu gamepad input suddenly stops working

21 Oct 2020, 13:57

We recently detected this behavior and found it was related to how we implemented horizontal scroll events.
We were manually creating a fake Shift key press and this was affecting the normal Button code for clicks.

For next 3.1 version we changed how we deal with scroll events to avoid this, unfortunately it is not merged to older versions because it can break user code.

A workaround is to increment the dead zone of the gamepad axis, that is, don't inject Scroll events if axis values range from -0.265 to 0.265 (we do that in our Win32 display implementation).
 
unvestigate
Topic Author
Posts: 32
Joined: 17 Jan 2018, 09:55

Re: Pause menu gamepad input suddenly stops working

21 Oct 2020, 14:18

Huh, interesting.

Do you mean the gamepad axis that scrolls between the buttons? In this case the D-pad up/down scrolls between the items, not an analogue axis. In fact, I don't think I have done anything besides adding the KeyboardNavigation.DirectionalNavigation="Cycle" attribute to the StackPanel to get the behavior I expect. I am not sure where to prevent the injection in this case.
 
unvestigate
Topic Author
Posts: 32
Joined: 17 Jan 2018, 09:55

Re: Pause menu gamepad input suddenly stops working

21 Oct 2020, 14:21

One more thing. I just checked my code and I have never called the Scroll() or HScroll() methods on the view, since I was getting some unexpected behavior earlier (Don't remember exactly what, this was years ago...)

So it seems like I never inject any scroll event at all (unless you meant something else) and I am still getting this issue. Any clues?
 
User avatar
sfernandez
Site Admin
Posts: 2254
Joined: 22 Dec 2011, 19:20

Re: Pause menu gamepad input suddenly stops working

21 Oct 2020, 16:30

Yes, I was referring to the Scroll/HScroll events you should inject to the View when right thumb axis changes. Those are the problematic ones, in fact only HScroll and MouseHWheel, so if you are not using them then what you are seeing is a different issue. Please check no MouseHWheel event is being injected to the View while using the pause menu.

Could you also verify what element has the Keyboard Focus when you press the GamepadAccept button?
 
unvestigate
Topic Author
Posts: 32
Joined: 17 Jan 2018, 09:55

Re: Pause menu gamepad input suddenly stops working

21 Oct 2020, 16:50

By "HWheel()" I assume you mean "MouseHWheel()", right? Regardless, I don't inject any horizontal scrolling at all so it should not be the problem. Regarding the focus, what would be the easiest way to check that? When the bug occurs, I can see the highlighted button on the pause menu since it is rendered differently from the others, and pressing Enter does indeed execute the button callback. I guess, that is enough to determine that it has keyboard focus...?
 
User avatar
sfernandez
Site Admin
Posts: 2254
Joined: 22 Dec 2011, 19:20

Re: Pause menu gamepad input suddenly stops working

22 Oct 2020, 10:05

By "HWheel()" I assume you mean "MouseHWheel()", right?
Yes, that's right (I'm gonna edit my previous answer to avoid confusion).
Regarding the focus, what would be the easiest way to check that?
Focused element can be obtained by calling on any UI element of the tree the following:
element->GetKeyboard()->GetFocused();
pressing Enter does indeed execute the button callback. I guess, that is enough to determine that it has keyboard focus...?
As you said pressing Space (or Enter if AcceptsReturn is set to true in the Button) only has effect on the focused element, so if the Button is reacting to the keyboard it means it had focus.

And Noesis::Key_GamepadAccepts is directly converted to a Noesis::Key_Space when raising KeyDown/Up events, so both respond to the same code.

The only difference then would be focus engagement, if for some reason the Button has IsFocusEngagementEnabled property set to true, then pressing Gamepad Accept will set IsFocusEngaged to true and handle the KeyDown event, not allowing the Button click code to execute. Can you check the value of IsFocusEngagementEnabled property of the Button before injecting the KeyDown and KeyUp events into the view?
 
unvestigate
Topic Author
Posts: 32
Joined: 17 Jan 2018, 09:55

Re: Pause menu gamepad input suddenly stops working

22 Oct 2020, 20:19

Thanks for your suggestions, been a busy day. I'll try to get to this tomorrow...
 
unvestigate
Topic Author
Posts: 32
Joined: 17 Jan 2018, 09:55

Re: Pause menu gamepad input suddenly stops working

23 Oct 2020, 12:48

How Typical. I put in the checks to see if the focus engagement is enabled and now I cannot reproduce the bug. I'll report back when it happens again.
 
unvestigate
Topic Author
Posts: 32
Joined: 17 Jan 2018, 09:55

Re: Pause menu gamepad input suddenly stops working

11 Nov 2020, 09:30

Hi, Sorry for taking a long time to get back to you. I finally had time to properly debug this and found that the Resume/Exit buttons stop working with the gamepad after Alt-Tabbing away from the game and back. I also checked what GetIsFocusEngagementEnabled() returns and it is false both before and after the buttons stop working.

Let me just reiterate that moving between the buttons using the gamepad works, but pressing them (using the A button on the gamepad) no longer works after Alt-Tabbing away. After this you can still select the correct button with the gamepad and press it by hitting Enter on the keyboard, which tells me that selecting the currently focused button still works correctly with the gamepad, even after Alt-Tabbing away and back.

Does this narrow the issue down?

Thanks!

Who is online

Users browsing this forum: No registered users and 3 guests