diff --git a/README.md b/README.md index 7585fb7..9128a8f 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,10 @@ A [jsui] replacement for the [preset] object in Cycling'74 Max. ## 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 or a list -- Scrollable (requires Max 8.6.2) +- Scrollable list layout (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) @@ -14,24 +15,27 @@ A [jsui] replacement for the [preset] object in Cycling'74 Max. - 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 slotstlet - More look customization -- Same click + modifier key behavior as the vanilla object to store or delete presets +- Dynamically adapts to resize both in Edit and Presentation mode +- Select mode: simple click selects the slot, double click recalls it (allows for organizing presets without recalling them) +- Color mode: ability to color sstored presets with 6 customizable colors (currently colors are only assigned automatically depending on slot number) + ## How to use - Place `tc.preset.js` in the same directory as your patch, or somewhere in the Max search path -- Create a [`jsui @filename tc.preset.js`]. You can either add `@jsarguments` followed by the name of the pattrstorage you want to communicate with, or set that later by sending a `pattrstorage` (followed by the pattrstorage name) message to the [jsui]. +- Create a [`jsui @filename tc.preset.js`]. - Connect the [pattrstorage] outlet to the [jsui] inlet +- Set the jsui attribute named "pattrstorage" to the name of the pattrstorage you just connected (or send a message like "pattrstorage my_pattrstorage_name") + ## Limitations -- Resize doesn't work in Presentation mode (jsui limitation) - Due to the way [pattrstorage] works, some pattrstorage-specific messages should be sent to the [jsui] instead of the [pattrstorage]. Some to both: - - `recall`, `delete`: send to [pattrstorage] only + - `recall`: send to [pattrstorage] only - `recallmulti`, `slotname`: send to [pattrstorage] first (for better timing), then to the [jsui] - `store`: send to [jsui] only - Some messages to pattrstorage causes the jsui to be out of sync (`clear`, `insert`, `lockall`, `read`, `readagain`, `remove`, `renumber`). If you use any of these messages, make sure to then send a `resync` to the jsui. - The js program send a lot of message to the [pattrstorage] (using `maxobj.message()`syntax, so without patch cord), which in return send (using a patch cord) a lot of messages required for the [jsui] to stay in sync. Using one of the above messages incorrectly, or sending `getslotlist`, `getslotnamelist`, or any message that will impact the presets might cause the [pattrstorage] to get out of sync. In case something like that happens, you can send the `resync` message to the [jsui]. -## Desired features (for someday) -- Select mode: simple click selects the slot, double click recalls it +## Desired features (for someday, if ever) - No need for a patch cord (programmatically create a [send]/[receive] pair?) - Ability to lock/unlock and rename directly in the jsui without the need of external objects - Ability to target a [pattrstorage] in a different patcher level diff --git a/tc.preset.js b/tc.preset.js index 9c66221..b48d3f1 100644 --- a/tc.preset.js +++ b/tc.preset.js @@ -106,18 +106,26 @@ var is_interpolating = 0; var is_dragging = 0; // Drag flag var drag_slot = -1; // Stores the slot that's being dragged -if (jsarguments.length>1) { +var has_loaded = false; + +// Allows for dynamic resizing even in presentation mode (addressing the limitation of onresize()) +var pres_rect = new MaxobjListener(this.box,"presentation_rect",get_prect); +function get_prect(prect) { + onresize(prect.value[2], prect.value[3]) +} + +if (jsarguments.length>1) { // Depreciated, use "pattrstorage" attribute instead of jsarguments. pattrstorage_name = jsarguments[1]; } function loadbang() { + has_loaded = true; + post("loadbang\n"); outlet(2, "set"); find_pattrstorage(pattrstorage_name); calc_rows_columns(); } -// loadbang(); - function calc_rows_columns() { half_margin = margin / 2; half_spacing = spacing / 2; @@ -246,6 +254,7 @@ function draw_text_bubble(x, y, w, h, text, cont) { cont.move_to(txt_pos_x, txt_pos_y); cont.show_text(text.toString()); } +draw_text_bubble.local = 1; function format_slot_name(id) { var text = id; @@ -264,7 +273,7 @@ format_slot_name.local = 1; function paint_base() { // We draw all slots (empty and stored ones) so we don't have to for every redraw - + // post("paint_base\n"); is_painting_base = 1; // Background @@ -305,167 +314,174 @@ paint_base.local = 1; function paint() { // post("redraw\n"); - with (mgraphics) { - select_font_face(font_name); - set_font_size(font_size); - translate(0, y_offset); - // Draw the base, which includes empty and filled slots - // It is first rendered at twice the size in order to make texts look nice and cripsy on hidpi discplays - // So we need to scale it down here - scale(0.5, 0.5); - image_surface_draw(base_drawing); - scale(2, 2); - - set_line_width(1); - - // Active slot - if (is_dragging == 0 && active_slot > 0 && active_slot <= slots_count_display) { - set_source_rgba(active_slot_color); - if (color_mode) { - draw_slot_bubble(slots[active_slot][0]+1.5, slots[active_slot][1]+1.5, slot_size-3, slot_size-3); - set_line_width(3); - stroke(); - } else { - draw_slot_bubble(slots[active_slot][0], slots[active_slot][1], slot_size, slot_size); - fill(); - } - } - // Previous active slot - if (is_dragging == 0 && previous_active_slot > 0 && previous_active_slot <= slots_count_display) { - // set_source_rgba(active_slot_color); - // draw_slot_bubble(slots[previous_active_slot][0]+0.75, slots[previous_active_slot][1]+0.75, slot_size-1.5, slot_size-1.5); - // set_line_width(1.5); - // stroke(); - set_source_rgba(active_slot_color[0], active_slot_color[1], active_slot_color[2], active_slot_color[3] * 0.5); - if (color_mode) { - draw_slot_bubble(slots[previous_active_slot][0]+1.5, slots[previous_active_slot][1]+1.5, slot_size-3, slot_size-3); - set_line_width(3); - stroke(); - } else { - draw_slot_bubble(slots[previous_active_slot][0], slots[previous_active_slot][1], slot_size, slot_size); - fill(); - } - } - - // Selected slot - if (select_mode && selected_slot > 0 && selected_slot <= slots_count_display) { - set_source_rgba(active_slot_color); + // Handling Presentation mode enable/disable + var cur_size = mgraphics.size; + if (cur_size[0] != ui_width || cur_size[1] != ui_height) { + onresize(cur_size[0], cur_size[1]); + } else { + with (mgraphics) { + select_font_face(font_name); + set_font_size(font_size); + translate(0, y_offset); + // Draw the base, which includes empty and filled slots + // It is first rendered at twice the size in order to make texts look nice and cripsy on hidpi discplays + // So we need to scale it down here + scale(0.5, 0.5); + image_surface_draw(base_drawing); + scale(2, 2); + set_line_width(1); - draw_slot_bubble(slots[selected_slot][0] - 0.5, slots[selected_slot][1] - 0.5, slot_size + 1, slot_size + 1); - stroke(); - } - - // Interpolated slots - if (is_dragging == 0 && display_interp && is_interpolating) { - for (var i = 1; i <= slots_count_display; i++) { - var interp = slots[i][6]; - if (interp >= 0) { - set_source_rgba(interp_slot_color); - draw_slot_bubble(slots[i][0], slots[i][1], slot_size, slot_size); + // Active slot + if (is_dragging == 0 && active_slot > 0 && active_slot <= slots_count_display) { + set_source_rgba(active_slot_color); + if (color_mode) { + draw_slot_bubble(slots[active_slot][0]+1.5, slots[active_slot][1]+1.5, slot_size-3, slot_size-3); + set_line_width(3); + stroke(); + } else { + draw_slot_bubble(slots[active_slot][0], slots[active_slot][1], slot_size, slot_size); + fill(); + } + } + + // Previous active slot + if (is_dragging == 0 && previous_active_slot > 0 && previous_active_slot <= slots_count_display) { + // set_source_rgba(active_slot_color); + // draw_slot_bubble(slots[previous_active_slot][0]+0.75, slots[previous_active_slot][1]+0.75, slot_size-1.5, slot_size-1.5); + // set_line_width(1.5); + // stroke(); + set_source_rgba(active_slot_color[0], active_slot_color[1], active_slot_color[2], active_slot_color[3] * 0.5); + if (color_mode) { + draw_slot_bubble(slots[previous_active_slot][0]+1.5, slots[previous_active_slot][1]+1.5, slot_size-3, slot_size-3); + set_line_width(3); stroke(); - draw_slot_bubble(slots[i][0], slots[i][1] + slot_size * (1-interp), slot_size, slot_size * interp); + } else { + draw_slot_bubble(slots[previous_active_slot][0], slots[previous_active_slot][1], slot_size, slot_size); fill(); } } - } - // Hovered slot - if (last_hovered > -1) { - if (shift_hold) { - if (option_hold) { - // About to delete - set_source_rgba(empty_slot_color[0], empty_slot_color[1], empty_slot_color[2], 0.8); - draw_slot_bubble(slots[last_hovered][0] + 1, slots[last_hovered][1] + 1, slot_size-2, slot_size-2); - fill(); - } else { - // About to store - set_source_rgba(active_slot_color[0], active_slot_color[1], active_slot_color[2], 0.7); - draw_slot_bubble(slots[last_hovered][0] + 1, slots[last_hovered][1] + 1, slot_size-2, slot_size-2); - fill(); - } - } - // Slot border - set_source_rgba(1, 1, 1, 0.8); - draw_slot_bubble(slots[last_hovered][0], slots[last_hovered][1], slot_size, slot_size); - stroke(); - - if (layout == 0) { - //Text (slot number and name) - var text = format_slot_name(last_hovered); - var text_dim = text_measure(text); - // If the text is too big or a slot is being dragged, display the text on top of the next slot. - // Otherwise, it gets displayed on the hovered slot. - - var bg_txt_dim_w = text_dim[0] > slot_size ? text_dim[0] + 4 : slot_size + 4; - var bg_txt_dim_h = text_dim[1] > slot_size ? text_dim[1] + 4 : slot_size + 4; - var bg_txt_pos_x = text_dim[0] > slot_size || is_dragging ? slots[last_hovered][0] + slot_size + 2: slots[last_hovered][0] - 2; - var bg_txt_pos_y = text_dim[1] > slot_size || is_dragging ? slots[last_hovered][1] - 2 : slots[last_hovered][1] - 2; + // Selected slot + if (selected_slot > 0 && selected_slot <= slots_count_display) { + set_source_rgba(active_slot_color); + set_line_width(1); + draw_slot_bubble(slots[selected_slot][0] - 0.5, slots[selected_slot][1] - 0.5, slot_size + 1, slot_size + 1); + stroke(); + } + + // Interpolated slots + if (is_dragging == 0 && display_interp && is_interpolating) { + for (var i = 1; i <= slots_count_display; i++) { + var interp = slots[i][6]; + if (interp >= 0) { + set_source_rgba(interp_slot_color); + draw_slot_bubble(slots[i][0], slots[i][1], slot_size, slot_size); + stroke(); + draw_slot_bubble(slots[i][0], slots[i][1] + slot_size * (1-interp), slot_size, slot_size * interp); + fill(); + } + } + } - // If there is not enough place, text is displayed on the left - if (bg_txt_pos_x + bg_txt_dim_w > ui_width) { - bg_txt_pos_x = slots[last_hovered][0] - half_spacing - bg_txt_dim_w; + // Hovered slot + if (last_hovered > -1) { + if (shift_hold) { + if (option_hold) { + // About to delete + set_source_rgba(empty_slot_color[0], empty_slot_color[1], empty_slot_color[2], 0.8); + draw_slot_bubble(slots[last_hovered][0] + 1, slots[last_hovered][1] + 1, slot_size-2, slot_size-2); + fill(); + } else { + // About to store + set_source_rgba(active_slot_color[0], active_slot_color[1], active_slot_color[2], 0.7); + draw_slot_bubble(slots[last_hovered][0] + 1, slots[last_hovered][1] + 1, slot_size-2, slot_size-2); + fill(); + } } + // Slot border + set_source_rgba(1, 1, 1, 0.8); + draw_slot_bubble(slots[last_hovered][0], slots[last_hovered][1], slot_size, slot_size); + stroke(); - var txt_pos_x = text_dim[0] > slot_size ? bg_txt_pos_x + half_spacing : bg_txt_pos_x + (bg_txt_dim_w / 2) - (text_dim[0]/2); - var txt_pos_y = bg_txt_pos_y + (bg_txt_dim_h + text_dim[1]) / 2 - text_dim[1]*0.18; + if (layout == 0) { + //Text (slot number and name) + var text = format_slot_name(last_hovered); + var text_dim = text_measure(text); + // If the text is too big or a slot is being dragged, display the text on top of the next slot. + // Otherwise, it gets displayed on the hovered slot. + + var bg_txt_dim_w = text_dim[0] > slot_size ? text_dim[0] + 4 : slot_size + 4; + var bg_txt_dim_h = text_dim[1] > slot_size ? text_dim[1] + 4 : slot_size + 4; + var bg_txt_pos_x = text_dim[0] > slot_size || is_dragging ? slots[last_hovered][0] + slot_size + 2: slots[last_hovered][0] - 2; + var bg_txt_pos_y = text_dim[1] > slot_size || is_dragging ? slots[last_hovered][1] - 2 : slots[last_hovered][1] - 2; + - // Bubble background - set_source_rgba(text_bg_color); - rectangle_rounded(bg_txt_pos_x, bg_txt_pos_y, bg_txt_dim_w, bg_txt_dim_h, 4, 4); - fill(); + // If there is not enough place, text is displayed on the left + if (bg_txt_pos_x + bg_txt_dim_w > ui_width) { + bg_txt_pos_x = slots[last_hovered][0] - half_spacing - bg_txt_dim_w; + } - // Buble text - set_source_rgba(text_color); - move_to(txt_pos_x, txt_pos_y); - show_text(text.toString()); - } - - } + var txt_pos_x = text_dim[0] > slot_size ? bg_txt_pos_x + half_spacing : bg_txt_pos_x + (bg_txt_dim_w / 2) - (text_dim[0]/2); + var txt_pos_y = bg_txt_pos_y + (bg_txt_dim_h + text_dim[1]) / 2 - text_dim[1]*0.18; - // Drag slot - if (is_dragging) { - if (layout == 0) { - translate(last_x, last_y ); - rotate(0.15); - scale(1.1, 1.1); - - // Slot shadow - set_source_rgba(0, 0, 0, 0.15); - for (var i = 0; i<4; i++) { - draw_slot_bubble( i*0.4 + 1-slot_size/2, i*0.4 + 1-slot_size/2, slot_size + i*0.8, slot_size+i*0.8); + // Bubble background + set_source_rgba(text_bg_color); + rectangle_rounded(bg_txt_pos_x, bg_txt_pos_y, bg_txt_dim_w, bg_txt_dim_h, 4, 4); fill(); - } - draw_slot_bubble( 2-slot_size/2, 2-slot_size/2, slot_size, slot_size); - fill(); - //Flying slot - set_source_rgba(active_slot_color); - draw_slot_bubble( -slot_size/2, -slot_size/2, slot_size, slot_size); - fill(); - } else { - translate(last_x, last_y ); - // rotate(0.15); - set_source_rgba(active_slot_color); + // Buble text + set_source_rgba(text_color); + move_to(txt_pos_x, txt_pos_y); + show_text(text.toString()); + } - draw_slot_bubble( -slot_size/2, -slot_size/2, slot_size, slot_size); - fill(); - // slot name - var text = format_slot_name(drag_slot); - var bg_txt_pos_x = slot_size/2+ spacing; - var bg_txt_pos_y = -slot_size/2; - var bg_txt_dim_w = ui_width - (2*margin + slot_size + spacing); - var bg_txt_dim_h = slot_size; - set_source_rgba(stored_slot_color); - draw_text_bubble(bg_txt_pos_x, bg_txt_pos_y, bg_txt_dim_w, bg_txt_dim_h, text); + } + // Drag slot + if (is_dragging) { + if (layout == 0) { + translate(last_x, last_y ); + rotate(0.15); + scale(1.1, 1.1); + + // Slot shadow + set_source_rgba(0, 0, 0, 0.15); + for (var i = 0; i<4; i++) { + draw_slot_bubble( i*0.4 + 1-slot_size/2, i*0.4 + 1-slot_size/2, slot_size + i*0.8, slot_size+i*0.8); + fill(); + } + draw_slot_bubble( 2-slot_size/2, 2-slot_size/2, slot_size, slot_size); + fill(); + + //Flying slot + set_source_rgba(active_slot_color); + draw_slot_bubble( -slot_size/2, -slot_size/2, slot_size, slot_size); + fill(); + } else { + translate(last_x, last_y ); + // rotate(0.15); + set_source_rgba(active_slot_color); + + draw_slot_bubble( -slot_size/2, -slot_size/2, slot_size, slot_size); + fill(); + // slot name + var text = format_slot_name(drag_slot); + var bg_txt_pos_x = slot_size/2+ spacing; + var bg_txt_pos_y = -slot_size/2; + var bg_txt_dim_w = ui_width - (2*margin + slot_size + spacing); + var bg_txt_dim_h = slot_size; + set_source_rgba(stored_slot_color); + draw_text_bubble(bg_txt_pos_x, bg_txt_pos_y, bg_txt_dim_w, bg_txt_dim_h, text); + + } + } - - } - } + } + } } paint.local = 1; @@ -529,6 +545,8 @@ function anything() { slots[v][6] = -1; if (active_slot == v) { active_slot = 0; + } else if (previous_active_slot == v) { + previous_active_slot = 0; } // to_pattrstorage("getslotname", v); @@ -538,6 +556,11 @@ function anything() { set_active_slot(active_slot); if (!is_dragging) { outlet(0, "delete", v); + if (selected_slot == v) { + selected_slot == 0 + outlet(2, 'set'); + outlet(3, 'set', 0); + } } trigger_writeagain(); } @@ -545,8 +568,7 @@ function anything() { } } -function bang() -{ +function bang() { to_pattrstorage("recall", active_slot); } @@ -554,14 +576,17 @@ function msg_int(v) { to_pattrstorage("recall", v); } -function msg_float(v) -{ +function msg_float(v) { var s = Math.floor(v); var i = v % 1; to_pattrstorage("recall", s, s+1, i); } -function pattrstorage(v){ +function init() { + loadbang(); +} + +function pattrstorage(v) { find_pattrstorage(v); paint_base(); } @@ -756,6 +781,9 @@ function lockedslots() { if (locked_slots.length) { for (var i = 0; i < locked_slots.length; i++) { slots[locked_slots[i]][5] = 1; + if (locked_slots[i] == selected_slot) { + select(selected_slot); + } } } } @@ -780,6 +808,7 @@ function read() { } function resync() { + set_active_slot(0); calc_rows_columns(); } @@ -794,6 +823,9 @@ function find_pattrstorage(name) { to_pattrstorage("getlockedslots"); } else { pattrstorage_name = null; + active_slot = 0; + previous_active_slot = 0; + selected_slot = 0; slots_clear(); // error("Pattrstorage", name, "doesn't exist.\n"); } @@ -882,17 +914,24 @@ trigger_writeagain.local = 1; // MOUSE EVENTS function onidle(x,y,but,cmd,shift,capslock,option,ctrl) { - if (last_x != x || last_y != y - y_offset|| shift_hold != shift || option_hold != option) { - last_x = x; + var redraw_flag = false; + if (last_x != x || last_y != y - y_offset) { + last_x = x; last_y = y - y_offset; - shift_hold = shift; - option_hold = option; - var cur = get_slot_index(x, y - y_offset); + var cur = get_slot_index(x, y - y_offset); if (cur != last_hovered) { last_hovered = cur; + redraw_flag = true; } + } + if (shift_hold != shift || option_hold != option) { + shift_hold = shift; + option_hold = option; + redraw_flag = true; + } + if (redraw_flag) { mgraphics.redraw(); - } + } } onidle.local = 1; @@ -939,28 +978,6 @@ function ondblclick(x,y,but,cmd,shift,capslock,option,ctrl) { if (last_hovered > -1 && pattrstorage_name != null && filled_slots.indexOf(last_hovered) > -1) { to_pattrstorage("recall", last_hovered); - // var output = "recall"; - // if (select_mode) { - // output = "select"; - // } - // if (shift) { - // output = "store"; - // if (option) { - // output = "delete"; - // } - // } else if (slots[last_hovered][4] == null) { - // return; - // } - // if (output == "store") { - // store(last_hovered); - // } else { - // if (output == "select") { - // select(last_hovered); - // // mgraphics.redraw(); - // } else { - // to_pattrstorage(output, last_hovered); - // } - // } } last_x = x; @@ -1075,14 +1092,32 @@ function onresize(w,h) } onresize.local = 1; -// function ondblclick(x,y,but,cmd,shift,capslock,option,ctrl) -// { -// last_x = x; -// last_y = y; -// } -// ondblclick.local = 1; - // ATTRIBUTES DECLARATION +declareattribute("pattrstorage", "getpattrstorage", "setpattrstorage", 1); +function getpattrstorage() { + if (pattrstorage_name == null) { + return + } else { + return pattrstorage_name; + } +} +function setpattrstorage(v){ + // This method is called for the first time when the patch is loading, before the loadbang (not all objects are instanciated yet) + // With v being the value stored whithin the patcher + if (v == null) { + pattrstorage_name = null; + pattrstorage_obj = null; + } else { + pattrstorage_name = arrayfromargs(arguments)[0]; + } + // If the loadbang already occured once, we need to retrigger here + if (has_loaded) { + find_pattrstorage(pattrstorage_name); + loadbang(); + } + // Otherwise, we just wait for the patch to call loadbang automatically at the end of its startup routine. +} + declareattribute("bubblesize", "getslotsize", "setslotsize", 1); function getslotsize() { return slot_size; @@ -1466,4 +1501,11 @@ function setcolor6(){ } else { error('color_6: wrong number of arguments\n'); } +} + +// UTILITY +function post_keys(obj) { + post('Keys of obj: ', obj, '\n'); + post(Object.keys(obj)); + post('\n'); } \ No newline at end of file diff --git a/tc.preset_demo.maxpat b/tc.preset_demo.maxpat index fc24d68..f23c14a 100755 --- a/tc.preset_demo.maxpat +++ b/tc.preset_demo.maxpat @@ -4,13 +4,13 @@ "appversion" : { "major" : 8, "minor" : 6, - "revision" : 2, + "revision" : 3, "architecture" : "x64", "modernui" : 1 } , "classnamespace" : "box", - "rect" : [ 34.0, 100.0, 854.0, 848.0 ], + "rect" : [ 310.0, 100.0, 854.0, 848.0 ], "bglocked" : 0, "openinpresentation" : 0, "default_fontsize" : 12.0, @@ -39,6 +39,42 @@ "subpatcher_template" : "", "assistshowspatchername" : 0, "boxes" : [ { + "box" : { + "id" : "obj-31", + "maxclass" : "message", + "numinlets" : 2, + "numoutlets" : 1, + "outlettype" : [ "" ], + "patching_rect" : [ 245.5, 565.0, 89.0, 22.0 ], + "text" : "storagewindow" + } + + } +, { + "box" : { + "id" : "obj-25", + "maxclass" : "message", + "numinlets" : 2, + "numoutlets" : 1, + "outlettype" : [ "" ], + "patching_rect" : [ 422.0, 598.0, 45.0, 22.0 ], + "text" : "store 3" + } + + } +, { + "box" : { + "id" : "obj-14", + "maxclass" : "message", + "numinlets" : 2, + "numoutlets" : 1, + "outlettype" : [ "" ], + "patching_rect" : [ 360.5, 586.0, 29.5, 22.0 ], + "text" : "init" + } + + } +, { "box" : { "id" : "obj-128", "items" : [ "Grid", ",", "List" ], @@ -69,7 +105,7 @@ "maxclass" : "comment", "numinlets" : 1, "numoutlets" : 0, - "patching_rect" : [ 959.0, 908.0, 131.0, 33.0 ], + "patching_rect" : [ 959.0, 908.0, 133.0, 33.0 ], "text" : "Set a given color (from 1 to 6)" } @@ -82,7 +118,6 @@ "numoutlets" : 1, "outlettype" : [ "" ], "patching_rect" : [ 830.0, 927.0, 123.0, 22.0 ], - "presentation_linecount" : 2, "text" : "color_wheel 3 0 1 1 1" } @@ -129,7 +164,7 @@ "maxclass" : "comment", "numinlets" : 1, "numoutlets" : 0, - "patching_rect" : [ 928.0, 780.0, 150.0, 87.0 ], + "patching_rect" : [ 928.0, 780.0, 151.0, 87.0 ], "text" : "When color mode is set to cycle, stored presets are shown in colors from color_1 to color_6, cyclically depending on their slot number." } @@ -303,7 +338,7 @@ "appversion" : { "major" : 8, "minor" : 6, - "revision" : 2, + "revision" : 3, "architecture" : "x64", "modernui" : 1 } @@ -967,7 +1002,7 @@ , { "box" : { "id" : "obj-8", - "items" : [ "0 (tmp)", ",", "1 <(unnamed)>", ",", "2 <(unnamed)>", ",", "3 <(unnamed)>", ",", "4 <(unnamed)>", ",", "5 <(unnamed)>", ",", "6 <(unnamed)>", ",", "7 onze", ",", "8 up", ",", "9 <(unnamed)>", ",", "10 oui", ",", "11 <(unnamed)>", ",", "12 <(unnamed)>", ",", "13 <(unnamed)>", ",", "14 <(unnamed)>", ",", "15 <(unnamed)>" ], + "items" : [ "6 <(unnamed)>", ",", "19 <(unnamed)>", ",", "39 <(unnamed)>" ], "maxclass" : "umenu", "numinlets" : 1, "numoutlets" : 3, @@ -987,7 +1022,7 @@ "numinlets" : 1, "numoutlets" : 0, "patching_rect" : [ 72.0, 139.0, 507.0, 87.0 ], - "text" : "Pattrstorage messages that doesn't trigger output and need to be sent to the jsui instead:\n- store (send to jsui only)\n- recallmulti (send to pattrstorage first for timing accuracy, then to jsui)\n- slotname (send \"setslotname\" or \"text\" to jsui instead, will rename active slot)\n- lock (or setlock to lock/unlock of the active slot)\n- some other. I've not tested them all. " + "text" : "Pattrstorage messages that doesn't trigger output and need to be sent to the jsui instead:\n- store (send to jsui only)\n- recallmulti (send to pattrstorage first for timing accuracy, then to jsui)\n- slotname (send \"setslotname\" or \"text\" to jsui instead, will rename selected slot)\n- lock (or setlock to lock/unlock of the active slot)\n- some other. I've not tested them all. " } } @@ -1056,18 +1091,17 @@ , { "box" : { "border" : 0, - "embedstate" : [ [ "autowriteagain", 0 ], [ "active_slot_color", 0.808, 0.898, 0.91, 1 ], [ "color_4", 0.367, 0.542, 0.712, 1 ], [ "slot_round", 0 ], [ "stored_slot_color", 0.502, 0.502, 0.502, 1 ], [ "layout", 0 ], [ "select_mode", 0 ], [ "color_5", 0.283, 0.606, 0.559, 1 ], [ "text_color", 0.129, 0.129, 0.129, 1 ], [ "color_mode", 0 ], [ "color_1", 0.743, 0.41, 0.501, 1 ], [ "bubblesize", 20 ], [ "interp_slot_color", 1, 1, 1, 0.8 ], [ "margin", 4 ], [ "color_6", 0.316, 0.616, 0.377, 1 ], [ "fontsize", 14 ], [ "scrollable", 1 ], [ "empty_slot_color", 0.349, 0.349, 0.349, 1 ], [ "color_2", 0.679, 0.405, 0.669, 1 ], [ "fontname", "Arial" ], [ "ignoreslotzero", 1 ], [ "spacing", 4 ], [ "text_bg_color", 1, 1, 1, 0.5 ], [ "min_rows", 50 ], [ "bgcolor", 0.2, 0.2, 0.2, 1 ], [ "color_3", 0.527, 0.459, 0.756, 1 ], [ "displayinterp", 1 ] ], + "embedstate" : [ [ "layout", 0 ], [ "color_6", 0.316, 0.616, 0.377, 1 ], [ "text_color", 0.129, 0.129, 0.129, 1 ], [ "ignoreslotzero", 1 ], [ "min_rows", 50 ], [ "bgcolor", 0.2, 0.2, 0.2, 1 ], [ "spacing", 4 ], [ "empty_slot_color", 0.349, 0.349, 0.349, 1 ], [ "displayinterp", 1 ], [ "color_1", 0.743, 0.41, 0.501, 1 ], [ "text_bg_color", 1, 1, 1, 0.5 ], [ "slot_round", 0 ], [ "color_2", 0.679, 0.405, 0.669, 1 ], [ "color_4", 0.367, 0.542, 0.712, 1 ], [ "autowriteagain", 0 ], [ "color_3", 0.527, 0.459, 0.756, 1 ], [ "active_slot_color", 0.808, 0.898, 0.91, 1 ], [ "color_mode", 0 ], [ "margin", 4 ], [ "interp_slot_color", 1, 1, 1, 0.8 ], [ "fontsize", 14 ], [ "select_mode", 0 ], [ "color_5", 0.283, 0.606, 0.559, 1 ], [ "bubblesize", 20 ], [ "stored_slot_color", 0.502, 0.502, 0.502, 1 ], [ "scrollable", 1 ], [ "fontname", "Arial" ], [ "pattrstorage", "test" ] ], "filename" : "tc.preset.js", "id" : "obj-10", - "jsarguments" : [ "test" ], "maxclass" : "jsui", "numinlets" : 1, "numoutlets" : 4, "outlettype" : [ "", "", "", "" ], "parameter_enable" : 0, - "patching_rect" : [ 72.0, 637.0, 364.0, 124.0 ], + "patching_rect" : [ 72.0, 636.0, 364.0, 125.0 ], "presentation" : 1, - "presentation_rect" : [ 1.0, 103.0, 269.0, 77.0 ] + "presentation_rect" : [ 1.0, 103.0, 293.0, 149.0 ] } } @@ -1125,10 +1159,10 @@ "outlettype" : [ "" ], "patching_rect" : [ 72.0, 599.0, 176.0, 22.0 ], "saved_object_attributes" : { - "client_rect" : [ 27, 158, 514, 944 ], + "client_rect" : [ 1450, 76, 2131, 1323 ], "parameter_enable" : 0, "parameter_mappable" : 0, - "storage_rect" : [ 25, 107, 816, 991 ] + "storage_rect" : [ 583, 69, 1034, 197 ] } , "text" : "pattrstorage test @savemode 0", @@ -1334,6 +1368,13 @@ "source" : [ "obj-131", 0 ] } + } +, { + "patchline" : { + "destination" : [ "obj-10", 0 ], + "source" : [ "obj-14", 0 ] + } + } , { "patchline" : { @@ -1387,6 +1428,13 @@ "source" : [ "obj-24", 0 ] } + } +, { + "patchline" : { + "destination" : [ "obj-10", 0 ], + "source" : [ "obj-25", 0 ] + } + } , { "patchline" : { @@ -1408,6 +1456,13 @@ "source" : [ "obj-3", 1 ] } + } +, { + "patchline" : { + "destination" : [ "obj-1", 0 ], + "source" : [ "obj-31", 0 ] + } + } , { "patchline" : {