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

Possible to execute user plugins after UI code is executed? #397

Open marcaddeo opened 2 years ago

marcaddeo commented 2 years ago

Hi,

I'm wondering if it's possible to set a user plugins priority so that it executes after actions/containers/etc from the UI.

For example, I'd like to use the active_device_switcher.py plugin, but I'd also like to be able to add curves and invert my input before the plugin code executes. Currently it seems to bypass the UI actions.

Looking at the code, it doesn't seem possible but maybe I'm missing something.

WhiteMagic commented 2 years ago

No, there is no way to order things, as by design everything is independent and actions do not interfere with each other. However, for your specific scenario, it should be solvable by assigning a response curve to the actual vJoy device.

marcaddeo commented 2 years ago

Hey @WhiteMagic, thanks for the response.

The problem I'm facing with assigning the response curve on the actual vJoy device is that when I'm mapping my two physical devices is only one device needs to be inverted. So it doesn't work in my case, unless there's another way. Another caveat with doing it that way is that I can't have conditions on the response curve... Which probably isn't a big deal and isn't something I've got a use-case for, but I was just trying to implement my setup in the most flexible way.

Currently I've worked around the issue by updating the active_device_switcher.py user script to add the option to invert an axis as such:

import gremlin
from gremlin.user_plugin import *

# Plugin variables
mode = ModeVariable("Mode", "Mode in which to use these settings")
phys_axis1 = PhysicalInputVariable(
        "First physical axis",
        "First physical axis",
        [gremlin.common.InputType.JoystickAxis]
)

phys_axis1_invert = BoolVariable(
        "Invert first physical axis?",
        "Invert first physical axis?"
)

phys_axis2 = PhysicalInputVariable(
        "Second physical axis",
        "Second physical axis",
        [gremlin.common.InputType.JoystickAxis]
)

phys_axis2_invert = BoolVariable(
        "Invert second physical axis?",
        "Invert second physical axis?"
)

virt_axis = VirtualInputVariable(
        "vJoy output",
        "Virtual output axis",
        [gremlin.common.InputType.JoystickAxis]
)

threshold = FloatVariable(
        "Activity threshold",
        "Value above which an axis is considered as being used",
        0.0,
        0.0,
        1.0
)

# Decorators for the two physical axes
dec_1 = phys_axis1.create_decorator(mode.value)
dec_2 = phys_axis2.create_decorator(mode.value)

# State variables
g_active_index = -1
g_last_value = [0.0, 0.0]

def update_vjoy(vjoy, index, value):
    global g_active_index
    global g_last_value

    if g_active_index != index:
        delta = abs(value - g_last_value[index])
        if delta > threshold.value:
            g_active_index = index

    if g_active_index == index:
        vjoy[virt_axis.vjoy_id].axis(virt_axis.input_id).value = value
        g_last_value[index] = value

@dec_1.axis(phys_axis1.input_id)
def axis1_cb(event, vjoy):
    value = event.value
    if phys_axis1_invert.value:
        value = -value

    update_vjoy(vjoy, 0, value)

@dec_2.axis(phys_axis2.input_id)
def axis2_cb(event, vjoy):
    value = event.value
    if phys_axis2_invert.value:
        value = -value

    update_vjoy(vjoy, 1, value)

It would be nice to be able to maybe set a priority on the decorator or something but I'm sure that's not an easy ask with however the code architecture is currently set up. Not sure how viable of an idea you think it is, or if I'm just not doing it "the right way".

WhiteMagic commented 2 years ago

For those situations, you will have to work with self-written plugins. Adding priorities would not change anything, as all containers execute independently of each other and won't under any circumstances affect each other. Thus, even if they could be ordered there would be no way for this to matter.