DAT as menuSource

The new menuSource attribute of the Par class is really useful.
It would be great if you could specify a DAT as a source (e.g. with ‘name’,‘value’ columns).
Alternatively, it could accept expressions that evaluate to a list of tuples [(‘name1’,‘Label1’), (‘etc’,‘Etc’)]. That would make it possible to use a DAT with expressions like “op(‘table’).rows()”.

Hello.

Actually menuSource is very open ended, so you just need to define a class with members: menuNames and menuLabels

I’ve attached an example that dynamically reads from a DAT table.

Basically the class is:

[code]
class MyDATMenu:

def __init__(self, path):
	self.myPath = path

@property		
def menuNames(self):
	return [x.val for x in op(self.myPath).col('name')][1:]

@property
def menuLabels(self):
	return [x.val for x in op(self.myPath).col('label')][1:][/code]

And the menu initialization looks like:

n = op('base1')
page = n.appendCustomPage('Custom')
par = page.appendMenu('M')[0]
par.menuSource = "op('text1').module.MyDATMenu('table1')"

The paths are all relative, so cutting and pasting the custom component would require cutting and pasting a table DAT to match.
datmenu.tox (734 Bytes)

1 Like

awesome! thanks!

Great technique. Should this work with StrMenu instead of Menu? With build 60880 I get this error after creating base2 and running the script.
datmenu.1.toe (3.65 KB)
2016-06-30 14_52_26-TouchDesigner_ C__Users_gen_Downloads_datmenu.1.toe_.png

Thanks for pointing that out, this is now fixed in an upcoming build.

I know widgets are the new way, and the dropDown Widget works by just plugging in a DAT directly, but the above method doesn’t seem to work with relative parent/child paths. So for example, if you were to put the custom menu on the “datmenu” tox/component and use:

op('./text1').module.MyDATMenu('./table1')

as the source, it doesn’t work.

However using an absolute path like:

op('/datmenu/text1').module.MyDATMenu('/datmenu/table1')

works.

hey rob

i just added a couple of print() statement and it seems that:

  • if I hover over the menu par name >> the class is constantly initialized (while mouse moves)
  • if I open the menu it always checks the menuNames property 4 times

Is that intended behavior?

datmenu.toe (3.6 KB)

Thanks Achim, we’ll have a look.

any news on this one?

I’ve confirmed the issue as you’ve described, but still requires a fix.
It’s on our list.
Thanks for the concise example.

Hi Achim.
Sorry for the delay.

So the behavior is because menuSource is an expression that is evaluated each time the entries are fetched.
In your case, the expression itself instantiates a class, which is why you’re seeing multiple ‘init’ calls.

One way around this is to create the class in your module:
m = MyDATMenu('table1')

Then your original expression would be:
par.menuSource = "op('text1').module.m"

A more ideal solution would be having the menuSource expression just evaluate when its dependencies change, though this would involve some more research to avoid refresh bugs.

I’ll think about it further.
Thanks for the example,
Rob.

This also works nicely with extensions btw, skipping the whole init every time you fetch the data.


And even better, this works with static properties also!

we can even go one step further and import a menu-object into our extension and add aditional functionality.

1 Like