WhiteMagic / JoystickGremlin

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

Altering virtual axis input via plugins #394

Open Ryuk47 opened 2 years ago

Ryuk47 commented 2 years ago

I am trying to create a plugin that works as a kind of moving deadzone to counter the at times unstable output of my X56 rotaries. I based this on a previous edit of yours being a moving average, however I cannot seem to find a way about "catching" the unwanted signals before they are already put out. From my very limited understanding of Python (C# guy), I can hook onto the callback of an axis input and spawn a thread that regularly updates the value. Even with an update rate of 10 milliseconds the unwanted signal gets through still. Is there any way to alter a physical axis input before it reaches the virtual output axis?

WhiteMagic commented 2 years ago

I'm not really clear what you actually want to do, but some information.

Ryuk47 commented 2 years ago

So my problem is that I have a physical input that occasionally starts to jitter within a very small margin of +- 0.02, which is extremely annoying when binding it to e.g. the in-game zoom. What I would like to achieve is to have a plugin detect and smooth out this jittering before the physical input is processed to the virtual axis.

Upon another inspection of my setup I think I have identified the issue: While using the attached script to filter the physical Z axis to the virtual one, I still had the physical z axis set up to remap to the virtual z axis, so I assume my moving deadzone plugin was fighting with the remapped input. The code below now seems to do as I wished for.


from gremlin.user_plugin import *

mode = ModeVariable("Mode", "The mode in which to use this mapping")

virtual_axis = VirtualInputVariable(
        "Virtual output axis",
        "The vJoy axis to send the filtered output to.",
        [gremlin.common.InputType.JoystickAxis]
)

physical_axis = PhysicalInputVariable(
        "Physical input axis",
        "The physical input axis being filtered.",
        [gremlin.common.InputType.JoystickAxis]
)

deadzone = IntegerVariable(
        "Deadzone size",
        "Size of the deadzone around the cached value.",
        5,
        0,
        100
)

# Decorator for the physical axis 
dec_physical_axis = physical_axis.create_decorator(mode.value)

# Global variables
# The cached physical input
g_cached_value = 0.0
# The current input
g_current_value = 0.0
g_vjoy = gremlin.joystick_handling.VJoyProxy()

def apply_deadzone():
    global g_current_value, g_cached_value
    if(abs(g_current_value - g_cached_value) > deadzone.value/100):
        g_cached_value = g_current_value
    return g_cached_value

def update_vjoy():
    global g_vjoy
    g_vjoy[virtual_axis.vjoy_id].axis(virtual_axis.input_id).value = apply_deadzone()

@dec_physical_axis.axis(physical_axis.input_id)
def axis_cb(event):
    global g_current_value
    g_current_value = event.value
    update_vjoy()