tc.preset: a new companion to pattrstorage
Hey,
I've already posted this on the discord channel and facebook page, but I assume some of us don't use these things, and I feel like this forum is a better place to put my work in, so people can find about it more easily in the future.
So tc.preset is basically a jsui replacement for the preset object, when linked to a pattrstorage, but with extra features:
Same click + modifier key behavior as the vanilla object to store and delete presets
Drag and drop presets to re-organize
Display presets as a grid (preset-like) or a list (chooser-like)
Scrollable (requires Max 8.6.2)
Shows active preset even if recalled directly from pattrstorage
Shows previously active preset, with the ability to ignore preset 0 if it being used as an intermediary step
Shows presets being interpolated (using recall or recallmulti)
Shows preset name and lock state
Outputs active preset name and lock state from third and fourth outlet
Ability to rewrite json file automatically every time a preset is stored/moved/deleted/renamed/(un)locked
Helps keeping in sync a umenu with the list of stored slots
More look customization
Dynamically adapts to resize both in Edit and Presentation mode (just like the regular preset, but it is not obvious with jsui, so worth mentioning here)
Select mode: simple click selects the slot, double click recalls it (allows for organizing/renaming presets without recalling them)
3 color modes to assign a color to each preset: cycle (preset automatically colorized depending on its slot number), select (manually for each preset among the 6 defined colors), custom (set any color you want for each preset)
It comes as a Max package, with full documentation and a helper file.
I hope you'll like it!
I hope you'll like it!
For sure ;-)
It looks great!
Just a small update to highlight new features:
New "Select" and "Custom" color modes, allowing to define a color for each preset, either by selecting one of the 6 re-assignable colors from the color_wheel, either by defining a completely custom color.
Now both grid and list layouts are scrollable
and various bug fixes
I've updated the main post with these changes.
Hello
Your preset object is wonderful !
I have an issue/question.
I have a pattrstorage that is structured in this maner :
presets numbers 1xxx are only controlling one bpatcher
presets numbers 2xxx are only controlling another bpatcher
....
presets numbers 10xxx are the last controlled bpatcher
So, some of my presets has a number superior to 10000, even If only few presets are stored in the pattrstorage.
For example, even with 6 presets, their slots can be : 1001, 1002, 2001, 6003, 8127, 10034.
I don't know if it's the cullprit, but eachtime I tried to connect tc.preset to this pattrstorage, max freezes and crashs...
Any idea ? SOrry I cannot post you an example for now..
thank you again
EDIT : I managed to use tc.preset with this pattrstorage.
the umenu below the snippet is well filled with my presets
(without the thousands empty ones, great!)
The freeze does not occur when I set "layout 1" in the inspector but when I ckeck "scrollable 1".
At the end, If I manage to have my presets in your tc.preset @layout 1 @scrollable 1, is there a way (maybe a feature request) that the list doesn"t show empty slots (like the Umenu below)... ?
Maybe it is already possible, but I cannot know since max crash as soon as I check "scrollable"...
Julien
Bonjour Julien, merci pour tes retours! I'm pleased to see people is using it.
Your case is interesting, I never thought of this kind of use and actually never tested the code with preset numbers above 1000.
The way it works is that the preset grid (or list) is pre-drawn (think of it as a background), so that only the filled slots are dynamically redrawn when something changes. When 'scrollable' is enabled, that background is the size required to display all filled slots. So when you have presets in very high slots, the pre-drawn rectangle is a very tall rectangle, hence the possible crash I guess.
However, you should be able to display more presets with layout 0 (grid) than layout 1 (list), given that it displays several presets per line. On my computer, with 'scrollable' enabled, I can store a preset in slot 50000 without issue when in grid layout, but it crashes in list layout.
Anyway, I doubt it is very practical and convenient to display and scroll through a list/grid of 10000+ presets, am I right?
I could definitely optimize that pre-drawing thing. Now that I think about it, I could actually just pre-draw just the right number of lines to fill the object's dimensions, and then duplicate this pattern as the user is scrolling. It could even allow for endless scrolling. But I won't have time to do it soon.
In the meantime, I'm glad you found a way to still make it work!
Also, if that's of any help, there's a new feature in the the latest version available on github. It is undocumented yet but here's how it works: it simply sends a dictionary of all filled slots, with their slot number, name, lock state and color values. It might be easy to build a custom way from this dict to display your filled presets, other than a umenu. Here's how it works:
Eventually, I wanted to switch to v8ui, but sadly these new v8 objects have a new read
method which doesn't play well with pattrstorage output sending a 'read' message when a preset file is loaded, as I make use of this message for syncing tc.preset. There would be some workaround by substituting 'read' by another method name but that needs another object in the patcher, so for now I stay away from v8ui for tc.preset.
Merci TFL de ta réponse rapide !
I find very useful to use 1xxx, 2xxx slots for presets when differents bpatchers has to be saved independently but within the same pattrstorage.
I will try to investigate how to easily " build a custom way from this dict to display [my] filled presets, other than a umenu"...I don't know If I am able to/have the time to be able to =)
Maybe, one day, there will be an update with the possibility of
[tc.preset @layout 1 @scrollable 1 @hideempty] =)
Waiting for that, I maybe found a bug with the resync message:
For info, in my (big) patch, when I want to store a preset I need to perform some operations between my "store button" and the real (store xxx) message sent to pattrstorage. So I cannot send (store xxx) directly to tc.preset
So, after sending (store xxx) to pattrsrtorage, I send a resync message to tc.preset.
then, all the umenu is well filled with all the presets but the name of each is :
"[number] jsobject 0" So the message "setsymbol [number] [name]" cannot reach the good entry
So the first item is selected : "0 (tmp)" (even if ignoreslotzero = 1)
"0 (tmp)" stays there whatever I recall a preset
The good preset is well checked when you open the umenu and the field with the name is good
everything restrart to work if I change the name of the preset
Can you reproduce ?
thank you again !
Julien
When I send a store message to pattrstorage then a resync to tc.preset, I get the umenu properly updated (no "[number] jsobject 0") but it gets back to the first item (1) and has no check mark. Makes me realize that this ignoreslotzero attribute seems broken though (I don't get preset 0 even if disabled).
To me it makes sense that you loose which preset has been lastly recalled, because you likely don't know what happened before the user sent a resync message. You should be able to re-select this preset either by recalling it (which you might not want), or using the select message to tc.preset. But that makes me realize that it updates correctly the umenu but not the jsui.
Could you isolate the problem in a simple patch?
I'll will think about a @hideempty feature, but won't be for anytime soon as I guess it would require a deep restructuration of some of the code.
I find very useful to use 1xxx, 2xxx slots for presets when differents bpatchers has to be saved independently but within the same pattrstorage
Not sure I understand the logic here. When you recall a preset, does it recall parameters for all bpatchers or only one? Because you could use 'recall bpatcher_name 3' messages for example to recall preset 3 only for bpatcher_name.
Maybe I found the culprit. It seems related to the process you described about the "predrawing".
Even If I only use the umenu, the "gui" of tc.preset has already to be as big as the number of the newly stored preset for the umenu to reflect the good preset..
you can reproduce ?
Not sure what you mean. In most cases, the object gets redrawn after all the processing (including updating umenu) has been done. Is it what you described?
just paste the snippet, resize the GUI of tc.preset to only 4 slots.
If you store a preset in store 5 (not viewable) directly with (store 5) in tc.preset, the blue umenu reflects the newly created preset.
If you store the preset via pattrstorage, and then send "resync" and "select 5" , the blue umenu doesnt reflect the state if the preset number is superior to the number of visible slots .
Thanks for the clear explanation and demo! It is indeed not the expected behavior.
I'll try to get this fixed soon.
I just pushed an update that should fix this and hopefully don't break anything else. I actually had to remove some code to fix that. Here's the link to get the latest version from github.
Apparently I forgot to push after my update for the filled slots dict. It's now part of the repo.
I also made a small change (also resulting in code simplification) allowing to use [chooser] instead of [umenu]. This way, you have all the filled slots in list fashion, if that's what you're looking for. For some reason, [chooser] need some time before a newly set menu itemcan be selected, hence the [deferlow] for the select
message. You don't need it for [umenu] though.
Hello,
The update is working perfectly for my use case.
Your preset object is really cool.
I noticed another behaviour I would like to know if there is something to do with it..
The scrollable attribute is working with mouse wheel perfectly but when I use Live with a touch screen (which is my main use case) the tc.preset doesn't react to "2fingers" scrolling, Live 's menus and max's menus do. ..
Thank you again from Sète !
Julien
Happy new year !
Hey Julien, thanks again for your feedback, et que ton année soit bonne également!
Interesting case! It seems that only v8ui on Windows can supports multitouch events, which is a bit of a challenge for me as I still use jsui (only because of one methode, 'read', that is now part of v8/v8ui so I cannot get the 'read' messages from pattrstorage), I don't have a Windows-compatible multitouch device, and my windows device is buried in a closet as I barely use it now.
I'm wondering how Max handles multitouch scrolling in its UI then... If someone from C74 see this! I guess there is an intermediate layer to handle scrolling with double-touches, but that get avoided in jsui/v8ui to allow for custom handling of these gesture events, even though jsui doesn't support multitouch.
Making a v8ui-compatible tc.preset is not too much of a problem, given that you're fine adding an object between pattrstorage and tc.preset (most likely a [substitute]). But implementing the multitouch scroll blindly can be... funny!
If no one comes with suggestions in a few days I'll try to do something about it.
Just to be sure, can you confirm that scrolling doesn't work both in M4L and in standalone Max?
Maybe you can send me an email (see my profile here) so we can keep discussing this more easily. Thanks!