Author Topic: Subroutines  (Read 2187 times)

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4787
  • RTFM
Subroutines
« on: March 21, 2018, 10:05:10 AM »
I believe this has been requested or at least talked about previously, but I'd like to put forward a few ideas on the subject of subroutines in VoiceAttack.


A subroutine would be a set of actions that executes as part of a command, but is not in itself a command.

The main reasons I feel this would be a worthwhile feature are these:

They would allow editing of all occurrences of the same set of actions within a profile, without having to close the command, find the subroutine in the command list, open it, edit it, save it, then open the original command again to further edit that.

They wouldn't have the overhead of actually executing another command(which is proven to be relatively slow, especially back when people used them for dynamic keybindings).
This would also mean command-scoped variables("~" prefix) would be accessible by the subroutine.



From an implementation standpoint, I believe it could be done by adding an identifier to actions that are part of a subroutine.

This identifier would be used to update the actions in any command that uses the same subroutine when editing(and to highlight or otherwise mark the actions in the action list to visually distinguish them from regular actions), but otherwise allow the subroutine to be part of the command, and thus require no additional logic during command execution.

E.G. subroutine "1" consists of two actions:
Code: [Select]
Begin Subroutine:  test
    Write '[Blue] action 1' to log
    Write '[Blue] action 2' to log
End Subroutine
I propose using actions to define the bounds of the subroutine because it fits with the current workflow within VoiceAttack.
This also allows assigning of a name(which would function as the identifier), from the action adding/editing dialog.

If the subroutine is edited this always happens within a single command, as it's not possible to edit multiple commands at the same time. Thus when the subroutine changes, the entire thing could be copied across to any other commands that contain it(possibly checking which actions actually changed and only copying those, if that's faster than blindly overwriting).


I will say, because I don't know how unsaved profile changes are stored, I don't know how feasible it is to do it this way, but even if only the changes are stored(Instead of making a full copy of the profile to use a working copy), I hope searching the profile for subroutines within the commands in the profile makes sense, from both an implementation and a performance standpoint.



One caveat of using actions for this is that if a subroutine is used multiple times within the same command, the action list has to be updated for each change made within that subroutine.

My original idea was to link to a separate entity, where the subroutine would only be visible as
Code: [Select]
Subroutine:  test
This would not require updating of the action list of the command, as I envisioned the subroutine having its own editing window, basically containing an action list and the related editing buttons.

That would also save on profile space, as actions within a subroutine aren't duplicated for each command that contains them, however I switched my thinking to the linked actions system because I figure that doesn't require a whole new method of loading in subroutines when a command is executed without the delay of executing another command with the "Execute Another Command" action, plus it doesn't require nearly as much new UI.

One possible option of having subroutines as a separate entity would be cross-profile accessibility, which I don't think is workable with the linked action system.



A worthwhile addition would be warning before saving an edited subroutine, possibly including a count of the commands that contain the subroutine.

More necessary would be a warning when attempting to create a new subroutine with a name that's already in use by another subroutine, to prevent unintentionally overwriting unrelated subroutines.

E.G. if a subroutine named "test" already exists(either in another command or the same one), and you try to add another "Begin Subroutine" action also using the name "test", VoiceAttack would warn the user with a message like "Subroutine 'test' is used in 5 other commands, save changes?" so that the existing function isn't overwritten by the new one(which could easily happen, especially when you use "test" as a name everywhere you test stuff, like I lazily do :-X).



Subroutines could be embedded into eachother:

Code: [Select]
Begin Subroutine :  test
    Write '[Blue] action 1' to log
    Begin Subroutine :  test 2
        Write '[Blue] action 1' to log
        Write '[Blue] action 2' to log
    End Subroutine
    Write '[Blue] action 2' to log
End Subroutine

This would add some extra overhead to check all subroutines in a given chain, when more than one is embedded in a command. Otherwise I'm hoping it's similar enough to having multiple different subroutines in the same command(as you have to check them for changes anyways).



A feature to list the commands that use a particular subroutine would come in handy.

This would likely be possible without specific implementation by using the search feature in the command list, E.G. "Begin Subroutine: test" would return and commands containing that subroutine.



A "make local" option that replaces the subroutine action in a single command with the contents of said subroutine, in case there is no other option but to make a custom version for one particular command.

If a subroutine is framed by "Begin" and "End" actions, this would simply be a matter of removing those to "unsubscribe" the actions between them from the subroutine they were in(excluding any other subroutines embedded within, of course).



Another handy option would be to have expandable/collapsible entries in the action list; This would be a feature request in itself(to allow grouping of actions and collapse them, possibly with a name that's displayed on the collapsed item), but I feel is especially relevant in this context:

It would function exactly like grouped commands in the "Edit a Profile" window when the grouping by category option is turned on.
The entry would be something like "+ Subroutine:  test", which when clicked expands into "- Subroutine:  test" and displays all the actions within the subroutine while also allowing editing.
This combines with the "make local" option above to go from an embedded subroutine to a collapsible section of actions.



I've attempted to think about this from a practical standpoint, making use of what's already present and keeping with the existing workflow, but I should mention that this was put together in pieces and mutated from one idea into another, so while I've attempted to proofread some things may not make as much sense as I hope ::)

I do realize "Ideas are a Dime a Dozen. People Who Implement Them are Priceless" :P