5 Commits

Author SHA1 Message Date
b3aed4c39a add store_passthrough 2026-07-10 09:35:23 +02:00
ddc5dcc162 make drag_mode 2 compatible with list layout; weighted interp for
drag_mode 3; small fixes
2026-07-09 21:20:54 +02:00
ae02cdbf7c removed useless attribute getters 2026-07-09 13:49:24 +02:00
bc3a4b31e7 bug fix 2026-07-09 13:23:24 +02:00
589c97b56b add drag_interp_radius attribute, defaults to 1. 2026-07-09 12:20:29 +02:00

View File

@@ -80,13 +80,15 @@ var min_rows = 10; // Minimum number of rows to display if scrollable i
var color_mode = 0; // Change the way the filled slots (stored presets) color is handeld. 0: stored_slot_color. 1: looping through color_1 to color_6. 2: Freely assign colors 1 to 6. 3: Set any color to any preset
var select_mode = 0; // 0: single click to select and recall the slot. 1: single click to select the slot, double click to recall it.
var click_mode = 0; // Sets the behavior of single clicks. 0: normal (recall), 1: select, 2: store, 3: delete
var drag_mode = 1; // Sets the behavior of drag operations. 0: disabled, 1: move preset (default), 2: in-line interpolation
var drag_mode = 1; // Sets the behavior of drag operations. 0: disabled, 1: move preset (default), 2: in-line interpolation, 3: zone interpolation
var drag_interp_radius = 1; // In use with drag_mode 3
var send_name = "none"; // The global name to send presets dict name to (received by the [receive] object)
var unique_names = false; // When enabled, force names to be unique when renaming slots by appending "bis" to them. Gets applied only to subsequently renamed presets.
var autoname = false; // Automatically name new presets when created as "Preset" followed by the slot id
var use_uid = 0; // Generating UID for each presets when enabled. Requires a [pattr preset_metadata]
var timestamp = false; // Generates a `created` and `modified` timestamp for each preset. Requires use_uid enabled
var recall_passthrough = true; // By default (true), clicking a slot sends a recall message directly to [pattrstorage], and the jsui left outlet outputs a recall message once the recall is done. When disabled, clicking a slot will send a recall message straight from the jsui left outlet, so it's up to the user to forward the message to pattrstorage. It can be usefull for triggering interpolations with custom logic.
var store_passthrough = true; // Same as recall_passthrough but for store messages triggered with shift+click. The store message message has to be routed back into [tc.preset] to be effective.
var ui_rename = false; // Use the attached textedit, if any, to edit slot names directly in the JSUI frame when clicking a slot while holding the control key. When disabled, the textedit remains untouched but gets focused when clicking a slot while holding the control key.
var poll_edited = 0; // If >0, check if current preset is edited every X seconds defined by the variable value.
var nbslot_edit = true; // If nbslot_edit and scrollable are enabled, the last two visible slots are replaced by buttons to add or remove lines of slot.
@@ -318,13 +320,14 @@ function calc_rows_columns(src) {
slots[cur].set_geom(left, top, right, bottom);
} else {
// Empty slot, possibly not initialized (if above slots_highest)
slots[cur] = new slot(left, top, right, bottom);
slots[cur] = new slot();
slots[cur].set_geom(left, top, right, bottom);
}
}
}
if (slots_count_display < slots_highest) {
if (slots.length < slots_highest ) {
for (var i = slots_count_display + 1; i <= slots_highest; i++) {
slots[i] = new slot();
}
@@ -580,7 +583,7 @@ function paint()
// }
// Hovered slot
if ((last_hovered > -1) && ((drag_mode < 2) || (drag_mode === 2 && !is_dragging))) {
if ((last_hovered > -1) && ((drag_mode < 2) || (drag_mode >= 2 && !is_dragging))) {
// Slot border
if (slots[last_hovered].filled === false || (slots[last_hovered].filled === true && !control_hold)) {
@@ -1254,8 +1257,10 @@ function store(v) {
if (!(ignore_slot_zero && v === 0)) {
set_active_slot(v);
}
outlet(0, "store", v);
if (store_passthrough) {
outlet(0, "store", v);
}
if (v) {
// We writagain only if stored preset is > 0
trigger_writeagain();
@@ -1496,7 +1501,6 @@ find_pattrstorage.local = 1;
function to_pattrstorage() {
if (pattrstorage_obj != null) {
// post('sending to pattrstorage: ', arrayfromargs(arguments), '\n');
pattrstorage_obj.message(arrayfromargs(arguments));
}
}
@@ -1599,7 +1603,6 @@ function update_filled_slots_dict() {
tmp_dict['color_custom'] = slot.color_custom; // Preset color (when color_mode = 3)
}
if (use_uid) tmp_dict['uid'] = slot.uid; // Preset uid (unique and persistent across preset renaming, overwriting and moving) Useful for keeping track of preset across changes
// post('updating by_uid', slot.uid, '\n');
if (timestamp) {
tmp_dict['created'] = slot.created;
tmp_dict['modified'] = slot.modified;
@@ -1816,7 +1819,11 @@ function onclick(x,y,but,cmd,shift,capslock,option,ctrl)
// if recall_passthrough == true, send the recall message to pattrstorage directly
outlet(0, 'recall', last_hovered);
} else if (output == "store") {
store(last_hovered);
if (store_passthrough) {
store(last_hovered);
} else {
outlet(0, 'store', last_hovered);
}
} else if (output == "select") {
select(last_hovered);
// mgraphics.redraw();
@@ -1921,7 +1928,9 @@ function ondrag(x,y,but,cmd,shift,capslock,option,ctrl)
}
// last_hovered retains the slot where the drag began
if (is_dragging === 2 && last_hovered > -1) {
var relative_dist_from_start = (x - slots[last_hovered].center.x) / (slot_size + spacing);
var relative_dist_from_start =
layout === 0 ? (x - slots[last_hovered].center.x) / (slot_size + spacing) :
(y - slots[last_hovered].center.y) / (slot_size + spacing);
var current_slot = Math.max(Math.round(last_hovered - 0.5 + relative_dist_from_start), 1);
var prev_filled_slot = -1;
var next_filled_slot = -1;
@@ -1967,16 +1976,19 @@ function ondrag(x,y,but,cmd,shift,capslock,option,ctrl)
}
// last_hovered retains the slot where the drag began
if (is_dragging === 3 && last_hovered > -1) {
var radius = 2;
var nearby_slots = [];
var max_dist = 0;
for (var i = 0; i < filled_slots.length; i++) {
var s_pos = slots[filled_slots[i]].center;
var dist_from_mouse = Math.sqrt((x - s_pos.x) * (x - s_pos.x) + (y - s_pos.y) * (y - s_pos.y)) / (slot_size + spacing);
if (dist_from_mouse < radius) {
var interp_factor = 1 - (dist_from_mouse / radius);
nearby_slots.push(filled_slots[i] + interp_factor);
if (max_dist < dist_from_mouse) max_dist = dist_from_mouse;
// Interpolating only through displayed slots;
if (filled_slots[i] <= slots_count_display) {
var s_pos = slots[filled_slots[i]].center;
var dist_from_mouse = Math.sqrt((x - s_pos.x) * (x - s_pos.x) + (y - s_pos.y) * (y - s_pos.y)) / (slot_size + spacing);
if (dist_from_mouse < drag_interp_radius) {
var interp_factor = Math.pow((dist_from_mouse / drag_interp_radius) - 1, 4)
// var interp_factor = 1 - (dist_from_mouse / drag_interp_radius);
nearby_slots.push(filled_slots[i] + interp_factor);
if (max_dist < dist_from_mouse) max_dist = dist_from_mouse;
}
}
}
if (nearby_slots.length) {
@@ -2080,12 +2092,7 @@ function setslotsize(v){
}
setslotsize.local = 1;
declareattribute("slot_round", "getslotround", "setslotround", 1, {type: "long", default: 0, label: "Slot Round", category: "Appearance"});
function getslotround() {
return slot_round;
}
getslotround.local = 1;
declareattribute("slot_round", null, "setslotround", 1, {type: "long", default: 0, label: "Slot Round", category: "Appearance"});
function setslotround(v){
if (arguments.length) {
slot_round = Math.max(0, Math.min(slot_size, v));
@@ -2097,12 +2104,7 @@ function setslotround(v){
}
setslotround.local = 1;
declareattribute("margin", "getmargin", "setmargin", 1, {type: "long", default: 4, label: "Margin", category: "Appearance"});
function getmargin() {
return margin;
}
getmargin.local = 1;
declareattribute("margin", null, "setmargin", 1, {type: "long", default: 4, label: "Margin", category: "Appearance"});
function setmargin(v){
if (arguments.length) {
margin = Math.max(0, v);
@@ -2113,12 +2115,7 @@ function setmargin(v){
}
setmargin.local = 1;
declareattribute("spacing", "getspacing", "setspacing", 1, {type: "long", default: 4, label: "Spacing", category: "Appearance"});
function getspacing() {
return spacing;
}
getspacing.local = 1;
declareattribute("spacing", null, "setspacing", 1, {type: "long", default: 4, label: "Spacing", category: "Appearance"});
function setspacing(v){
if (arguments.length) {
spacing = Math.max(1, v);
@@ -2148,12 +2145,7 @@ function setbgcolor(){
}
setbgcolor.local = 1;
declareattribute("empty_slot_color", "getemptycolor", "setemptycolor", 1, {style: "rgba", label: "Empty Slot Color", category: "Appearance"});
function getemptycolor() {
return empty_slot_color;
}
getemptycolor.local = 1;
declareattribute("empty_slot_color", null, "setemptycolor", 1, {style: "rgba", label: "Empty Slot Color", category: "Appearance"});
function setemptycolor(){
if (arguments.length == 4) {
empty_slot_color = [arguments[0], arguments[1], arguments[2], arguments[3]];
@@ -2166,12 +2158,7 @@ function setemptycolor(){
}
setemptycolor.local = 1;
declareattribute("active_slot_color", "getactiveslotcolor", "setactiveslotcolor", 1, {style: "rgba", label: "Active Slot Color", category: "Appearance"});
function getactiveslotcolor() {
return active_slot_color;
}
getactiveslotcolor.local = 1;
declareattribute("active_slot_color", null, "setactiveslotcolor", 1, {style: "rgba", label: "Active Slot Color", category: "Appearance"});
function setactiveslotcolor(){
if (arguments.length == 4) {
active_slot_color = [arguments[0], arguments[1], arguments[2], arguments[3]];
@@ -2184,12 +2171,7 @@ function setactiveslotcolor(){
}
setactiveslotcolor.local = 1;
declareattribute("stored_slot_color", "getstoredslotcolor", "setstoredslotcolor", 1, {style: "rgba", label: "Stored Slot Color", category: "Appearance"});
function getstoredslotcolor() {
return stored_slot_color;
}
getstoredslotcolor.local = 1;
declareattribute("stored_slot_color", null, "setstoredslotcolor", 1, {style: "rgba", label: "Stored Slot Color", category: "Appearance"});
function setstoredslotcolor(){
if (arguments.length == 4) {
stored_slot_color = [arguments[0], arguments[1], arguments[2], arguments[3]];
@@ -2202,12 +2184,7 @@ function setstoredslotcolor(){
}
setstoredslotcolor.local = 1;
declareattribute("interp_slot_color", "getinterpslotcolor", "setinterpslotcolor", 1, {style: "rgba", label: "Interpolating slot color", category: "Appearance"});
function getinterpslotcolor() {
return interp_slot_color;
}
getinterpslotcolor.local = 1;
declareattribute("interp_slot_color", null, "setinterpslotcolor", 1, {style: "rgba", label: "Interpolating slot color", category: "Appearance"});
function setinterpslotcolor(){
if (arguments.length == 4) {
interp_slot_color = [arguments[0], arguments[1], arguments[2], arguments[3]];
@@ -2220,11 +2197,7 @@ function setinterpslotcolor(){
}
setinterpslotcolor.local = 1;
declareattribute("text_color", "gettextcolor", "settextcolor", 1, {style: "rgba", label: "Text Color", category: "Appearance"});
function gettextcolor() {
return text_color;
}
gettextcolor.local = 1;
declareattribute("text_color", null, "settextcolor", 1, {style: "rgba", label: "Text Color", category: "Appearance"});
function settextcolor(){
if (arguments.length == 4) {
text_color = [arguments[0], arguments[1], arguments[2], arguments[3]];
@@ -2293,12 +2266,7 @@ function setfontname(v){
}
setfontname.local = 1;
declareattribute("menu_mode", "getmenu_mode", "setmenu_mode", 1, {style: "enumindex", enumvals: ["Preset number + name", "Preset number", "Preset name"], label: "Menu Mode"});
function getmenu_mode() {
return menu_mode;
}
getmenu_mode.local = 1;
declareattribute("menu_mode", null, "setmenu_mode", 1, {style: "enumindex", enumvals: ["Preset number + name", "Preset number", "Preset name"], label: "Menu Mode"});
function setmenu_mode(v){
if (arguments.length == 1) {
menu_mode = Math.min(Math.max(0, parseInt(v)), 2);
@@ -2337,12 +2305,7 @@ function setignoreslotzero(v){
}
setignoreslotzero.local = 1;
declareattribute("display_interp", "getdisplayinterp", "setdisplayinterp", 1, {style: "onoff", label: "Display Interpolations", category: "Appearance"});
function getdisplayinterp() {
return display_interp;
}
getdisplayinterp.local = 1;
declareattribute("display_interp", null, "setdisplayinterp", 1, { style: "onoff", label: "Display Interpolations", category: "Appearance" });
function setdisplayinterp(v){
if (v == 0) {
display_interp = 0;
@@ -2352,12 +2315,7 @@ function setdisplayinterp(v){
}
setdisplayinterp.local = 1;
declareattribute("layout", "getlayout", "setlayout", 1, {style: "enumindex", enumvals: ["Grid", "List"], label: "Layout", category: "Appearance"});
function getlayout() {
return layout;
}
getlayout.local = 1;
declareattribute("layout", null, "setlayout", 1, {style: "enumindex", enumvals: ["Grid", "List"], label: "Layout", category: "Appearance"});
function setlayout(v){
if (v == 0) {
layout = 0;
@@ -2369,12 +2327,7 @@ function setlayout(v){
}
setlayout.local = 1;
declareattribute("scrollable", "getscrollable", "setscrollable", 1, {style: "onoff", label: "Scrollable"});
function getscrollable() {
return scrollable;
}
getscrollable.local = 1;
declareattribute("scrollable", null, "setscrollable", 1, {style: "onoff", label: "Scrollable"});
function setscrollable(v){
if (v == 0) {
scrollable = 0;
@@ -2386,11 +2339,7 @@ function setscrollable(v){
}
setscrollable.local = 1;
declareattribute("min_rows", "getmin_rows", "setmin_rows", 1, {type: "long", min: 1, label: "Minimum Rows"});
function getmin_rows() {
return min_rows;
}
getmin_rows.local = 1;
declareattribute("min_rows", null, "setmin_rows", 1, {type: "long", min: 1, label: "Minimum Rows"});
function setmin_rows(v){
if (v > 0) {
min_rows = v;
@@ -2403,26 +2352,18 @@ setmin_rows.local = 1;
declareattribute("click_mode", null, null, 1, { style: "enumindex", enumvals: ["Recall", "Select", "Store", "Delete"], default: 0, label: "Click Mode", paint: 1});
declareattribute("select_mode", "getselect_mode", "setselect_mode", 1, {style: "onoff", label: "Select Mode", invisible: 1});
function getselect_mode() {
return select_mode;
}
getselect_mode.local = 1;
declareattribute("select_mode", null, "setselect_mode", 1, {style: "onoff", label: "Select Mode", invisible: 1});
function setselect_mode(v) {
select_mode = v ? 1 : 0;
if (select_mode) this.box.message("click_mode", v);
}
setselect_mode.local = 1;
declareattribute("drag_mode", null, null, 1, { style: "enumindex", enumvals: ["Disabled", "Move", "In-Line Interp", "Interp"], default: 1, label: "Drag Mode", paint: 1});
declareattribute("drag_mode", null, null, 1, { style: "enumindex", enumvals: ["Disabled", "Move", "In-Line Interp", "Interp"], default: 1, label: "Drag Mode", paint: 1 });
declareattribute("color_mode", "getcolor_mode", "setcolor_mode", 1, {type: "long", min: 0, max: 3, style: "enumindex", enumvals: ["Classic", "Cycle", "Select", "Custom"], label: "Color Mode", category: "Appearance"});
function getcolor_mode() {
return color_mode;
}
getcolor_mode.local = 1;
declareattribute("drag_interp_radius", null, null, 1, { type: "float", min: 1, default: 1, label: "Drag Interpolation Radius" });
declareattribute("color_mode", null, "setcolor_mode", 1, {type: "long", min: 0, max: 3, style: "enumindex", enumvals: ["Classic", "Cycle", "Select", "Custom"], label: "Color Mode", category: "Appearance"});
function setcolor_mode(v){
v = Math.floor(v);
v = Math.max(0, Math.min(3, v));
@@ -2447,12 +2388,7 @@ function setcolor_mode(v){
}
setcolor_mode.local = 1;
declareattribute("color_1", "getcolor1", "setcolor1", 1, {style: "rgba", label: "Color 1", category: "Appearance"});
function getcolor1() {
return color_1;
}
getcolor1.local = 1;
declareattribute("color_1", null, "setcolor1", 1, {style: "rgba", label: "Color 1", category: "Appearance"});
function setcolor1(){
if (arguments.length == 4) {
color_wheel(1, arguments[0], arguments[1], arguments[2], arguments[3]);
@@ -2464,12 +2400,7 @@ function setcolor1(){
}
setcolor1.local = 1;
declareattribute("color_2", "getcolor2", "setcolor2", 1, {style: "rgba", label: "Color 2", category: "Appearance"});
function getcolor2() {
return color_2;
}
getcolor2.local = 1;
declareattribute("color_2", null, "setcolor2", 1, {style: "rgba", label: "Color 2", category: "Appearance"});
function setcolor2(){
if (arguments.length == 4) {
color_wheel(2, arguments[0], arguments[1], arguments[2], arguments[3]);
@@ -2481,12 +2412,7 @@ function setcolor2(){
}
setcolor2.local = 1;
declareattribute("color_3", "getcolor3", "setcolor3", 1, {style: "rgba", label: "Color 3", category: "Appearance"});
function getcolor3() {
return color_3;
}
getcolor3.local = 1;
declareattribute("color_3", null, "setcolor3", 1, {style: "rgba", label: "Color 3", category: "Appearance"});
function setcolor3(){
if (arguments.length == 4) {
color_wheel(3, arguments[0], arguments[1], arguments[2], arguments[3]);
@@ -2498,12 +2424,7 @@ function setcolor3(){
}
setcolor3.local = 1;
declareattribute("color_4", "getcolor4", "setcolor4", 1, {style: "rgba", label: "Color 4", category: "Appearance"});
function getcolor4() {
return color_4;
}
getcolor4.local = 1;
declareattribute("color_4", null, "setcolor4", 1, {style: "rgba", label: "Color 4", category: "Appearance"});
function setcolor4(){
if (arguments.length == 4) {
color_wheel(4, arguments[0], arguments[1], arguments[2], arguments[3]);
@@ -2515,12 +2436,7 @@ function setcolor4(){
}
setcolor4.local = 1;
declareattribute("color_5", "getcolor5", "setcolor5", 1, {style: "rgba", label: "Color 5", category: "Appearance"});
function getcolor5() {
return color_5;
}
getcolor5.local = 1;
declareattribute("color_5", null, "setcolor5", 1, {style: "rgba", label: "Color 5", category: "Appearance"});
function setcolor5(){
if (arguments.length == 4) {
color_wheel(5, arguments[0], arguments[1], arguments[2], arguments[3]);
@@ -2532,12 +2448,7 @@ function setcolor5(){
}
setcolor5.local = 1;
declareattribute("color_6", "getcolor6", "setcolor6", 1, {style: "rgba", label: "Color 6", category: "Appearance"});
function getcolor6() {
return color_6;
}
getcolor6.local = 1;
declareattribute("color_6", null, "setcolor6", 1, {style: "rgba", label: "Color 6", category: "Appearance"});
function setcolor6(){
if (arguments.length == 4) {
color_wheel(6, arguments[0], arguments[1], arguments[2], arguments[3]);
@@ -2549,12 +2460,7 @@ function setcolor6(){
}
setcolor6.local = 1;
declareattribute("send_name", "getsendname", "setsendname", 1, {type: "symbol", label: "Send Dictionary To"});
function getsendname() {
return send_name;
}
getsendname.local = 1;
declareattribute("send_name", null, "setsendname", 1, {type: "symbol", label: "Send Dictionary To"});
function setsendname(){
if (arguments.length > 0) {
send_name = arguments[0];
@@ -2564,12 +2470,7 @@ function setsendname(){
}
setsendname.local = 1;
declareattribute("unique_names", "getunique_names", "setunique_names", 1, {style: "onoff", label: "Force Unique Names"});
function getunique_names() {
return unique_names;
}
getunique_names.local = 1;
declareattribute("unique_names", null, "setunique_names", 1, {style: "onoff", label: "Force Unique Names"});
function setunique_names(v){
unique_names = v > 0;
}
@@ -2577,12 +2478,7 @@ setunique_names.local = 1;
declareattribute("autoname", null, null, 1, { style: "onoff", label: "Autoname new presets" });
declareattribute("use_uid", "getuse_uid", "setuse_uid", 1, {style: "onoff", label: "Use UID"});
function getuse_uid() {
return use_uid;
}
getuse_uid.local = 1;
declareattribute("use_uid", null, "setuse_uid", 1, {style: "onoff", label: "Use UID"});
function setuse_uid(v){
var new_val = v == 1 ? 1 : 0;
if (new_val != use_uid && new_val == 1) {
@@ -2611,23 +2507,19 @@ function settimestamp(v){
}
settimestamp.local = 1;
declareattribute("recall_passthrough", "getrecall_passthrough", "setrecall_passthrough", 1, {style: "onoff", label: "Recall Passthrough"});
function getrecall_passthrough() {
return recall_passthrough;
}
getrecall_passthrough.local = 1;
declareattribute("recall_passthrough", null, "setrecall_passthrough", 1, {style: "onoff", label: "Recall Passthrough"});
function setrecall_passthrough(v){
recall_passthrough = v > 0;
}
setrecall_passthrough.local = 1;
declareattribute("ui_rename", "getui_rename", "setui_rename", 1, {style: "onoff", label: "Rename In UI"});
function getui_rename() {
return ui_rename;
declareattribute("store_passthrough", null, "setstore_passthrough", 1, {style: "onoff", label: "Store Passthrough"});
function setstore_passthrough(v){
store_passthrough = v > 0;
}
getui_rename.local = 1;
setstore_passthrough.local = 1;
declareattribute("ui_rename", null, "setui_rename", 1, {style: "onoff", label: "Rename In UI"});
function setui_rename(v){
ui_rename = v > 0;
if (ui_rename) {
@@ -2636,12 +2528,7 @@ function setui_rename(v){
}
setui_rename.local = 1;
declareattribute("poll_edited", "getpoll_edited", "setpoll_edited", 1, {type: "float", min: 0, label: "Poll Edited State"});
function getpoll_edited() {
return poll_edited;
}
getpoll_edited.local = 1;
declareattribute("poll_edited", null, "setpoll_edited", 1, {type: "float", min: 0, label: "Poll Edited State"});
function setpoll_edited(v){
poll_edited = v == 0 ? 0 : Math.max(0.1, Math.abs(v));
if (poll_edited > 0) {
@@ -2672,12 +2559,7 @@ function do_poll_edited() {
}
do_poll_edited.local = 1;
declareattribute("edited_color", "getedited_color", "setedited_color", 1, {style: "rgba", label: "Edited Dot Color", category: "Appearance"});
function getedited_color() {
return edited_color;
}
getedited_color.local = 1;
declareattribute("edited_color", null, "setedited_color", 1, {style: "rgba", label: "Edited Dot Color", category: "Appearance"});
function setedited_color(){
if (arguments.length == 4) {
edited_color = [arguments[0], arguments[1], arguments[2], arguments[3]];
@@ -2697,12 +2579,7 @@ function edited(v) {
}
}
declareattribute("nbslot_edit", "getnbslot_edit", "setnbslot_edit", 1, {style: "onoff", label: "Add/remove rows of presets"});
function getnbslot_edit() {
return nbslot_edit;
}
getnbslot_edit.local = 1;
declareattribute("nbslot_edit", null, "setnbslot_edit", 1, {style: "onoff", label: "Add/remove rows of presets"});
function setnbslot_edit(v){
nbslot_edit = v > 0;
y_offset = 0;