WhiteMagic / JoystickGremlin

A tool for configuring and managing joystick devices.
http://whitemagic.github.io/JoystickGremlin/
GNU General Public License v3.0
313 stars 45 forks source link

Hat state stuck when condition changes before release #203

Open mmayers12 opened 5 years ago

mmayers12 commented 5 years ago

This seems similar to previous issues that look fixed, but I've found it persisting in conditional hat presses in release 12.

For example, I have dual Sticks, and I use the left trigger as a shift-state by binding it to LEFT ALT. Then I have my hats bound to a button on vJoy1 if LEFT ALT is released, and the same button on vJoy2 if LEFT ALT is pressed.

If I want to use a shift-state on my hat, but I release the shift button before I release the hat, the virtual button that the hat is mapped to will be stuck on. Specifically, If I move the hat up with LEFT ALT pressed, then release LEFT ALT before releasing the hat, the vJoy2 button hat up is mapped to will remain stuck in pressed until I re-initiate the combo of LEFT ALT and hat up again, this time releasing the hat up before releasing LEFT ALT.

Similarly, the reverse is true. If I initiate the hat, then activate the shift state, the mapped button (or hat) on vJoy1 will be stuck in pressed until I re-press and release that hat direction while the shift state is not active.

As the user, the behavior that I'd expect is: when I activate the hat, produces the virtual action dependent upon the shift-state at the time of activation. Then when I release the hat, it releases that virtual action independent of the current shift-state (the virtual action remaining held as long as the hat is active, even if there is a change in shift-state). I believe this is how it works with mapping physical buttons to virtual buttons and a conditional shift-state.

Here's a snippet of the relevant section of my config.

                <hat description="" id="1">
                    <container type="basic">
                        <action-set>
                            <remap button="12" vjoy="1">
                                <activation-condition rule="all">
                                    <condition comparison="released" extended="False" input="keyboard" scan_code="56"/>
                                </activation-condition>
                            </remap>
                        </action-set>
                        <virtual-button north="1" north-east="1" north-west="1"/>
                    </container>
                    <container type="basic">
                        <action-set>
                            <remap button="13" vjoy="1">
                                <activation-condition rule="all">
                                    <condition comparison="released" extended="False" input="keyboard" scan_code="56"/>
                                </activation-condition>
                            </remap>
                        </action-set>
                        <virtual-button east="1" north-east="1" south-east="1"/>
                    </container>
                    <container type="basic">
                        <action-set>
                            <remap button="14" vjoy="1">
                                <activation-condition rule="all">
                                    <condition comparison="released" extended="False" input="keyboard" scan_code="56"/>
                                </activation-condition>
                            </remap>
                        </action-set>
                        <virtual-button south="1" south-east="1" south-west="1"/>
                    </container>
                    <container type="basic">
                        <action-set>
                            <remap button="15" vjoy="1">
                                <activation-condition rule="all">
                                    <condition comparison="released" extended="False" input="keyboard" scan_code="56"/>
                                </activation-condition>
                            </remap>
                        </action-set>
                        <virtual-button north-west="1" south-west="1" west="1"/>
                    </container>
                    <container type="basic">
                        <action-set>
                            <remap button="12" vjoy="2">
                                <activation-condition rule="all">
                                    <condition comparison="pressed" extended="False" input="keyboard" scan_code="56"/>
                                </activation-condition>
                            </remap>
                        </action-set>
                        <virtual-button north="1" north-east="1" north-west="1"/>
                    </container>
                    <container type="basic">
                        <action-set>
                            <remap button="13" vjoy="2">
                                <activation-condition rule="all">
                                    <condition comparison="pressed" extended="False" input="keyboard" scan_code="56"/>
                                </activation-condition>
                            </remap>
                        </action-set>
                        <virtual-button east="1" north-east="1" south-east="1"/>
                    </container>
                    <container type="basic">
                        <action-set>
                            <remap button="14" vjoy="2">
                                <activation-condition rule="all">
                                    <condition comparison="pressed" extended="False" input="keyboard" scan_code="56"/>
                                </activation-condition>
                            </remap>
                        </action-set>
                        <virtual-button south="1" south-east="1" south-west="1"/>
                    </container>
                    <container type="basic">
                        <action-set>
                            <remap button="15" vjoy="2">
                                <activation-condition rule="all">
                                    <condition comparison="pressed" extended="False" input="keyboard" scan_code="56"/>
                                </activation-condition>
                            </remap>
                        </action-set>
                        <virtual-button north-west="1" south-west="1" west="1"/>
                    </container>
                </hat>

For the sake of thoroughness, I've tested a direct mapping of physical hat to virtual hat, with a conditional shift-state, and encounter the same issue.

WhiteMagic commented 5 years ago

I agree the behaviour you're seeing is not ideal as far as typical intent goes. The reason button remaps don't have this problem is that they get added to a system that ensures they get release no whenever the triggering button is released. The same issue was also happening when switching modes.

The underlying reason is that as far as Gremlin is concerned the press / release or various hat directions are completely independent and additional links have to be added to have Gremlin react "sensibly" to them. The current way that handles this for buttons works but is a bit awkward and has it's own issues with causing problems. So I think I may just have to look into a more intelligent way to decide when two actions are linked.