Add integration test for response curve action plugin#620
Conversation
|
That looks nice and definitely will allow covering awkward combinations, which Gremlin now allows with the arbitrary nesting of actions. As for how to configure, yeah I think Python might be easier and more concise. Creating XML files with the UI works but is awkward and reading/modifying them is a pain with the number of indirections now present. Also doing it with Python would give more control should we want to vary a base action or similar. |
Let me give another stab at creating a profile in Python - I might be missing something, but it looks like I'd have to duplicate some of the logic that's currently in the QML files, and it seemed like it would end up being a lot of code overall. |
|
I think I'm a little too deep in the weeds here, trying to create the profile from Python. So far I have this fixture: Is this generally the right idea? What should happen next? |
Yes, that is one way that should work. The other way which one could take (not sure it's better or easier at all though) is to directly work with the Once you have a valid profile, you should be able to run something like this to get Gremlin into the "active" state. After that, all events should be processed by the profile, and the corresponding actions be executed. And then we hit a snag I just discovered :-) Currently, there is no way to emit events (Qt Signals) directly from the IO system. The I hope that all makes sense, if not let me know. I can also draw up a diagram of how the whole Profile thing connects together, as the entire Library, Input, InputBinding, etc. are quite a handful to wrap one's head around. |
|
Thanks for the outline! That does help. I've been a little busy but I do plan to get this PR sorted out; for now can you confirm a few things:
so I think I need to add something to the "inputs" section, but as far as I can tell, the code to do that is across a few files including the QMLs? |
|
For the first point, it's probably easier if I take a look at it as I know that part of the code better so don't have to first understand what the goal was to begin with. Yes Qt may be unhappy to emit signals if certain aspects of the stack are missing. I haven't looked into what the minimal components are that one needs to get the signal/slot mechanism to work. A bare bones QApplication instance might be sufficient though. The profile is a bit (lot) convoluted, and quirky to handle all the things I want and that's before the UI has to make sense of it and handle user interactions :-) The As a preface, you have to think of actions as a tree structure that can be nested arbitrarily deep but does not allow cycles (the code should check for that iirc). Library has one entry for each action that has been configured. Actions themselves can refer to other actions if they need that for their functionality, examples include condition, tempo, chain, etc, effectively everything that was a container in R13 plus some others. There is a special action called InputItem refers to an individual physical input (axis, button, hat). They don't do much other than letting Gremlin know which input has been configured (avoiding the endless empty lists in R13). They are tied to actions via one or more InputItemBinding Gremlin lets you define multiple independent sets of "reactions" to run for events on an input. For example, on an axis one set of actions applies a response curve before remapping the value to a vJoy axis while a second set of actions treats the input as a button and triggers a macro. Each of those two "behaviors" are captured by an Each action has an id (UUID) that is used to refer to it from other actions or the InputItemBinding. The actual code of adding the needed entry to the
An example of what happens when an action is added is shown in |
a427adb to
fd47272
Compare
|
Thanks for the help! I have the code working now, and I think it is "as it should be". Let me know what you think. I will add more tests cases to this PR tomorrow, ran out of time for today. Meanwhile if you have any thoughts let me know. |
|
Today I was looking at how to change the response curve for testing purposes; part of this logic is implemented in
I think I should do (4), but in that case I should probably go about that in a separate PR. Otherwise, (1) could also work and could probably be done with less code changes. I don't think the other options are promising/desirable. Thoughts? |
|
I'll try to take a look at it later today. As for the response curve, it depends a bit on what parts you want to test. Though that entire action is probably the most complex one because it has high demands on being really fast so it gives instant feedback without lagging the UI out but also awkward coordinate frame conversions. The I'd say depending on what level you want to test to be at I'd either try to refactor the "coordinate conversion logic" into the |
| def profile_setup() -> None: | ||
| # This is important for locally-run tests where the last used profile could | ||
| # get loaded, if present in configuration. | ||
| backend.Backend().profile = pr = profile.Profile() |
There was a problem hiding this comment.
You could also see if using Backend.newProfile works as that ensures everything Gremlin does for a new profile is also done here.
|
Looks good to me. Obviously writing the set for the profile is a bit awkward but I don't think there is much in the way of making it simpler other than having a bunch of helper functions. Though should those become useful they can always be added later. Just as a heads up, I'll likely rename the |
…cation during test
fd47272 to
8023a45
Compare
|
Let's go ahead and merge this PR, if you don't mind; I just rebased it on top of your latest commits. Integration tests are passing, although one unit test is broken, presumably because of commit e2c1694; unrelated to this PR. I'll try approach 4 this weekend and expand the test coverage. IO rename sounds good to me, agreed that it was confusing earlier. But consider that |
|
Yeah naming things is hard and had similar thoughts about similarity to vJoy but that's kind of what the thing is but yeah more pondering :-) |

Along the lines of what we discussed earlier for testing one or more actions using IntermediateOutputs, here's a PR!
It runs on GitHub actions
What's your preference on how to test different configurations of the action(s)? E.g. for response curve, change the curve type and the control points. We could modify the action plugin instance via Python, or load a different profile for each case from the
xmldirectory. I'm leaning towards modifying via Python - somewhat less code coverage, but more maintainable.