Dynamic List Control
-
Is there any way in Isadora to influence the contents of a list item in the control view, like a Radio Button, at runtime? My use case is needing to populate a selectable list of Zoom usernames after ZoomOSC sends the list of participants to Isadora via OSC. I would need some method of pushing these names to the Radio Button so that the user could later select the username from the list for the purpose of then calling an action upon that user. If I had this ability, and the ability to remove an element from the list, I could also have a relatively easy way of implementing searchable lists.
I have a client who needs this capability in a studio controller, and while I would love to use Isadora for this, I may need to punt it to Universe or Node Red.
-
Currently no. There is no way to change the contents of interface elements from within the Actor overview.
-
well the only interface element where you can change its content from an actor is the "edit text". Maybe use the edit text to label buttons etc.
Best Michel
-
I can see how some kind of dynamic labels could be useful in the control panel. If dynamic labels could be associated with buttons or lists that would be great actually.
Best wishes
Russell
-
As @Michel said, you could use a Data Array actor hooked up to Edit Text Controls showing values of linked properties to make Edit Text Controls next to buttons. ou could use a Data Array actor hooked up to Edit Text Controls showing values of linked properties to make Edit Text Controls next to buttons.
You can also use Text Formatter to create a numbered list in an Edit Text Control and then use a Number Control to select which user you want.
Number Control Method 1
Number Control Method 2
The problem with all of these is that to see the list as a whole, you need to make connections between the OSC Multi Listener/Data Array actor that gives you the full list of names and something (either to Controls, Selector, or Text Formatter) so that you can see the list as a whole and linking in this manner cannot be done dynamically so you need to create all those links ahead of time as placeholders, then create the patch in such a way that it replaces the placeholder names with real ones when you refresh the list. The only thing I can think of to do is to make to pre-make a bunch of connections for a reasonable amount of participants (say 100) and then pre-set those 100 connections so that the logic will work the way you want. (Like how I pre-made 100 entries in the Data Array actor in Number Control Method 2 and all new names just replace one of those placeholders when the list gets refreshed.)
Here's my example file: 2021-02-25 - 3.0.7 - ZoomOSC Name Select.zip
-
@michel said:
the only interface element where you can change its content from an actor is the "edit text".
Re-reading this made me realize that there are actually two more Controls that you can change the contents of from an actor; Stage Preview and Monitor.
- Do everything I mentioned above (or a combination or variation of it)
- Instead of sending the list from a Text Formatter actor to an Edit Text Control, send the list from the Text Formatter actor to a Text Draw Text actor
- Connect the Text Draw actor's video output to a Monitor Control (or connect the Text Draw actor's video output to a Projector actor aimed at a Virtual Stage, then use a Stage Preview Control to see the list).
- Using this method you'll have many more formatting options to customize how you want the list to appear (because you can control more formatting in the Text Draw actor than you can in the Edit Text Control).
-
@woland said:
do is to make to pre-make a bunch of connections for a reasonable amount of participants (say 100) and then pre-set those 100 connections so that the logic will work the way you want. (Like how I pre-made
marvellous!
However, the buttons and labels remain unlinked programmatically. And while there may be a convoluted backend process that could facilitate such a link its expensive in terms of patching and time dividend overall. A request to consider dynamic button labels in the control panel feature set still makes sense to me, despite your exquisite and lateral patching prowess. Frankly I am awestruck by it. but somehow remain unconvinced that I would choose that route over a simpler implementation if offered by other OSC control software options.
Besides that your amazing Lucas!
best wishes
Russell
-
@bonemap said:
However, the buttons and labels remain unlinked programmatically. And while there may be a convoluted backend process that could facilitate such a link its expensive in terms of patching and time dividend overall. A request to consider dynamic button labels in the control panel feature set still makes sense to me, despite your exquisite and lateral patching prowess. Frankly I am awestruck by it. but somehow remain unconvinced that I would choose that route over a simpler implementation if offered by other OSC control software options.
Yes, I just wanted to figure out what's possible now with the current version. I'm already brainstorming a feature request to make this far easier and much less tedious.
-
@woland @michel @bonemap @liminal_andy @juriaan
Very good discussion here and it's clear that the ability to adjust the contents of the Radio Button control would be a super good new addition to that plugin's capabilities. To that end, I've just made Andy a version of the Radio Button control that I'm calling List Selector. This version of the plugin allows you to change the list by sending a list of carriage return separated strings into a second controller number.
Now, it will be easy to update the Radio Control control to have this functionality once the we've gotten the Big Sur release out and the code is unfrozen. But right now I can't make any changes or @DusX and @Woland will slap me. ;-) In the meantime I've sent Andy the plugin so he won't have to abandon Isadora for this project.
Best Wishes,
Mark -
@mark I will keep an eye out for this and look forward to checking it out! I'll be sure to share what I end up doing with it for this client.
-
@mark based on how you built List Selector, how easy would a search option be for it? Or will that need to be handled by a JS actor doing substring checks?
-
@liminal_andy said:
@mark based on how you built List Selector, how easy would a search option be for it? Or will that need to be handled by a JS actor doing substring checks?
I suppose a third input could be added where you gave a sub string and it searched the list. But what is the exact functionality here? You type a substring and it selects an item from the list?
Best Wishes,
Mark -
@mark To be specific:
There will be several hundred entries on the list, too many to scroll through for navigation. I need to be able to start entering a username into an input field and cull the dynamic list to only names containing the substring of what I am entering into the search box, exactly how the actor search feature functions. Then, I will still make a click to select the correct user from the reduced list. Finally, I will click a button to call the action on the selected user (pin, spotlight, etc.)
-
We're so close! Thanks to @mark's speedy brilliance, we now have a method of controlling the list from the node editor. Mark also provided a javascript actor to do the searching function. Now the last step is reconciliation with the data array when search is enabled. Any ideas on how to achieve this? Do we need a change so that when the dynamic list element knows it is being connected to a text input, it passes by label instead of by value? Or is there some trickery we can do to find the correct username from the data array actor even when search is culling the list?
-
@liminal_andy said:
Thanks to @mark's speedy brilliance
cue the superhero theme music.
I don't know if I have the best solution for your unresolved procedure, because as you suggest a trigger sending the string as a parameter from the button list would be the most efficient and safest solution... But I would have thought you could deploy a text comparator comparing the search results from the JS search actor to the output of a second data array. If this data array cycled rapidly through its data while comparing the javascript search string it might stop at the matching line and provide a line reference number. I guess this requires you to have completely unique names for each line entry in the array data.
best wishes
Russell
-
@bonemap said:
<p>@liminal_andy said:</p> <blockquote>Thanks to @mark's speedy brilliance</blockquote> <p> cue the superhero theme music.</p><p>I don't know if I have the best solution for your unresolved procedure, because as suggested accessing the string parameter would be the most efficient and safest solution... But I would have thought you could deploy a second data array to write temporary assignments that precede your search event and output the string required for the next step in the chain.</p><p>best wishes</p><p>Russell</p>
clever, I wonder if there is a simple way for me to re-use the JS code that culls the dynamic list to act upon a copy database, simultaneously pruning it so the list and the database remain in sync.
-
-
@liminal_andy said:
clever, I wonder if there is a simple way for me to re-use the JS code that culls the dynamic list to act upon a copy database, simultaneously pruning it so the list and the database remain in sync.
There is. You just need to store the index of the items with the lines in JS, do the filtering, and then split the outputs to give a list of the indexes and a list of the text. You can then use the list of indexes to look up the item in the original list.
Sending the test file that includes this functionality to you now.
function main()
{
var outStringIndexes = "";
var outStringLines = "";
var inputLines = arguments[0].match(/[^\r\n]+/g);
var i;
var indexedLines = [ ];
for (i=0; i<inputLines.length; i++) {
var rec = [ i+1, inputLines[i] ];
// print(rec[0] + " " + rec[1] + "\n");
indexedLines.push(rec);
}
for (i=0; i<inputLines.length; i++) {
var needle = arguments[1].toLowerCase();
var haystack = indexedLines[i][1].toLowerCase();
if (haystack.includes(needle)) {
outStringIndexes += indexedLines[i][0] + "\n";
outStringLines += indexedLines[i][1] + "\n";
}
}
return [outStringIndexes, outStringLines];
}Best Wishes,
Mark