2 Commits

Author SHA1 Message Date
3a8d893e5a inline interp + multi interp modes working 2026-07-09 11:59:57 +02:00
bcfeb98af9 1st attempt to drag-to-interp 2026-07-08 22:04:26 +02:00

View File

@@ -80,6 +80,7 @@ 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 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
@@ -198,6 +199,10 @@ function slot(left, top, right, bottom) {
this.top = top;
this.right = right;
this.bottom = bottom;
this.center = {
x: (left + right) / 2,
y: (top + bottom) / 2,
}
}
this.export_metadata = function () {
@@ -459,7 +464,7 @@ function paint_base() {
for (var i = 1; i <= true_slots_count_display; i++) {
if (i != drag_slot) { //We mask the slot that is currently dragged as it is drawn at the mouse position already
var slot = slots[i];
if (slot.filled == true) {
if (slot.filled === true) {
if (color_mode == 1) {
mg.set_source_rgba(color_wheel_custom[i % color_wheel_size]);
} else if (color_mode == 2) {
@@ -503,7 +508,7 @@ function paint()
mgraphics.set_line_width(1);
// Active slot
if (is_dragging == 0 && active_slot > 0 && active_slot <= slots_count_display) {
if (is_dragging !== 1 && active_slot > 0 && active_slot <= slots_count_display) {
var opacity = active_slot_color[3];
var opacity = control_hold && last_hovered == active_slot ? active_slot_color[3] * 0.7 : active_slot_color[3];
mgraphics.set_source_rgba(active_slot_color[0], active_slot_color[1], active_slot_color[2], opacity);
@@ -521,7 +526,7 @@ function paint()
}
// Previous active slot
if (is_dragging == 0 && previous_active_slot > 0 && previous_active_slot <= slots_count_display) {
if (is_dragging === 0 && previous_active_slot > 0 && previous_active_slot <= slots_count_display) {
mgraphics.set_source_rgba(active_slot_color[0], active_slot_color[1], active_slot_color[2], active_slot_color[3] * 0.5);
if (color_mode) {
if (!control_hold) {
@@ -545,7 +550,7 @@ function paint()
}
// Interpolated slots
if (is_dragging == 0 && display_interp && is_interpolating) {
if (is_dragging !== 1 && display_interp && is_interpolating) {
for (var i = 1; i <= slots_count_display; i++) {
var slot = slots[i];
@@ -575,10 +580,10 @@ function paint()
// }
// Hovered slot
if (last_hovered > -1) {
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)) {
if (slots[last_hovered].filled === false || (slots[last_hovered].filled === true && !control_hold)) {
mgraphics.set_source_rgba(text_color[0], text_color[1], text_color[2], 0.8 * text_color[3]);
mgraphics.set_line_width(1);
draw_slot_bubble(slots[last_hovered].left, slots[last_hovered].top, slot_size, slot_size);
@@ -589,7 +594,7 @@ function paint()
var stroke_width = Math.round(1 + slot_size / 10);
stroke_width = Math.max(2, stroke_width);
if (shift_hold) {
if (control_hold && slots[last_hovered].filled == true) {
if (control_hold && slots[last_hovered].filled === true) {
// About to lock/unlock
var bracket_size = slot_size * 0.2;
mgraphics.set_source_rgba(text_color);
@@ -603,7 +608,7 @@ function paint()
mgraphics.rel_line_to(0, slot_size);
mgraphics.rel_line_to(-bracket_size, 0);
mgraphics.stroke();
} else if (option_hold && !control_hold && slots[last_hovered].filled == true) {
} else if (option_hold && !control_hold && slots[last_hovered].filled === true) {
// About to delete
mgraphics.set_source_rgba(0, 0, 0, 0.5);
draw_slot_bubble(slots[last_hovered].left + 1, slots[last_hovered].top + 1, slot_size-2, slot_size-2);
@@ -614,7 +619,7 @@ function paint()
draw_slot_bubble(slots[last_hovered].left + 1, slots[last_hovered].top + 1, slot_size-2, slot_size-2);
mgraphics.fill();
}
} else if (control_hold && slots[last_hovered].filled == true) {
} else if (control_hold && slots[last_hovered].filled === true) {
// About to rename
mgraphics.set_source_rgba(text_color);
mgraphics.set_line_width(stroke_width);
@@ -682,7 +687,7 @@ function paint()
}
// Drag slot
if (is_dragging) {
if (is_dragging === 1) {
if (layout == 0) {
mgraphics.translate(last_x, last_y );
mgraphics.rotate(0.15);
@@ -925,7 +930,7 @@ function anything() {
} else {
slots[v].name = null;
slots[v].interp = -1;
slots[v].filled = 0;
slots[v].filled = false;
if (active_slot == v) {
active_slot = 0;
selected_slot = 0;
@@ -934,7 +939,7 @@ function anything() {
previous_active_slot = 0;
}
if (is_dragging == 0 && is_moving == 0) {
if (is_dragging === 0 && is_moving === 0) {
to_pattrstorage("delete", v);
to_pattrstorage("getslotlist");
set_active_slot(active_slot);
@@ -1019,7 +1024,7 @@ function slotname() {
return;
}
if (slot > 0 && name != "(undefined)") {
if (is_updating_names == 1 && slots[slot].filled == false && name !== "<(unnamed)>") {
if (is_updating_names == 1 && slots[slot].filled === false && name !== "<(unnamed)>") {
// Removing parenthesis automatically added by pattrstorage if the preset has a name but isn't filled
name = name.slice(1, -1);
}
@@ -1160,21 +1165,26 @@ function recallmulti() {
var interp_slots = [];
var summed_weight = 0;
for (var i = 0; i < filled_slots.length; i++) {
slots[filled_slots[i]].interp = -1;
}
for (var i = 0; i < args.length; i++) {
var slot = Math.floor(args[i]);
var weight = args[i] % 1.;
if (weight == 0) weight = 1;
summed_weight += weight;
interp_slots.push([Math.floor(args[i]), weight]);
interp_slots.push([slot, weight]);
}
for (var i = 0; i < interp_slots.length; i++) {
var nb = interp_slots[i][0];
if (slots[nb].filled == true) {
if (slots[nb].filled === true) {
interp_slots[i][1] /= summed_weight;
} else {
interp_slots[i][1] = -1;
}
slots[nb].interp = interp_slots[i][1]
slots[nb].interp = interp_slots[i][1];
}
is_interpolating = 1;
@@ -1295,7 +1305,7 @@ function move() {
if (args.length < 2) return;
var src_slot = args[0]; // Preset to move
var dst_slot = args[1]; // Destination slot
if (src_slot == dst_slot || !(src_slot <= slots_highest && dst_slot <= slots_count_display) || slots[src_slot].filled == false) {
if (src_slot == dst_slot || !(src_slot <= slots_highest && dst_slot <= slots_count_display) || slots[src_slot].filled === false) {
if (is_dragging) {
}
@@ -1307,7 +1317,7 @@ function move() {
var cur_prev_active_slot = previous_active_slot;
var cur_selected_slot = selected_slot;
var offset = ((dst_slot <= src_slot) && slots[dst_slot].filled) ? 1 : 0;
var offset_others = slots[dst_slot].filled == true ? 1 : 0;
var offset_others = slots[dst_slot].filled === true ? 1 : 0;
var src_slot_lock = slots[src_slot].lock;
var recalc_rows_flag = 0;
@@ -1316,7 +1326,7 @@ function move() {
lock(src_slot, 0);
}
// If new slot is empty we just move the drag preset here. If it's not, we move al next slots to the right
if (slots[dst_slot].filled == true) {
if (slots[dst_slot].filled === true) {
if (slots_highest == slots_count_display) {
// If there's a stored preset in the last displayed slot, it will be pushed to a new row at insert, so we need to add a new row at redraw
recalc_rows_flag = 1;
@@ -1799,7 +1809,7 @@ function onclick(x,y,but,cmd,shift,capslock,option,ctrl)
output = "lock";
} else if (!shift && ctrl && slots[last_hovered].filled) {
output = "rename";
} else if (slots[last_hovered].filled == false) {
} else if (slots[last_hovered].filled === false) {
return;
}
if (output == "recall" && recall_passthrough == false) {
@@ -1854,51 +1864,132 @@ function ondrag(x,y,but,cmd,shift,capslock,option,ctrl)
{
if (pattrstorage_name != null) {
y -= y_offset;
if (is_dragging == 0 && last_hovered > 0 && slots[last_hovered].filled == true) {
// To prevent mistakes, is_dragging is set to 1 only when dragging for more than 10 pixels
var dist_from_start = Math.sqrt((x-last_x)*(x-last_x)+(y-last_y)*(y-last_y));
if (dist_from_start > 10) {
is_dragging = 1;
drag_slot = last_hovered;
paint_base(); // We repaint the base with the dragged slot removed from the grid
}
} else if (is_dragging == 1) {
last_hovered = get_slot_index(x, y);
last_hovered_is_preset_slot = scrollable && nbslot_edit && last_hovered > (true_slots_count_display - 2) ? false : true;
if (!last_hovered_is_preset_slot) {
last_hovered = 0;
}
if (!but) {
// When the button is released, the dragging ceases
if (last_hovered > 0 && last_hovered != drag_slot && last_hovered_is_preset_slot) {
move(drag_slot, last_hovered);
} else {
// Drag released but not somewhere we can throw a slot in
is_dragging = 0;
drag_slot = -1;
paint_base();
if (drag_mode === 1) {
if (is_dragging === 0 && last_hovered > 0 && slots[last_hovered].filled === true) {
// To prevent mistakes, is_dragging is set to 1 only when dragging for more than 10 pixels
var dist_from_start = Math.sqrt((x-last_x)*(x-last_x)+(y-last_y)*(y-last_y));
if (dist_from_start > 10) {
is_dragging = 1;
drag_slot = last_hovered;
paint_base(); // We repaint the base with the dragged slot removed from the grid
}
} else {
// Click still hold, we keep dragging
if (scrollable) {
// Auto-scroll if mouse out of bounds
if (y+y_offset < 0 && y-(last_y-drag_scroll) < 0) {
drag_scroll = 2;
} else if (y+y_offset > ui_height && y-(last_y-drag_scroll) > 0) {
drag_scroll = -2;
} else if (is_dragging == 1) {
last_hovered = get_slot_index(x, y);
last_hovered_is_preset_slot = scrollable && nbslot_edit && last_hovered > (true_slots_count_display - 2) ? false : true;
if (!last_hovered_is_preset_slot) {
last_hovered = 0;
}
if (!but) {
// When the button is released, the dragging ceases
if (last_hovered > 0 && last_hovered != drag_slot && last_hovered_is_preset_slot) {
move(drag_slot, last_hovered);
} else {
drag_scroll = 0;
// Drag released but not somewhere we can throw a slot in
is_dragging = 0;
drag_slot = -1;
paint_base();
}
} else {
// Click still hold, we keep dragging
if (scrollable) {
// Auto-scroll if mouse out of bounds
if (y+y_offset < 0 && y-(last_y-drag_scroll) < 0) {
drag_scroll = 2;
} else if (y+y_offset > ui_height && y-(last_y-drag_scroll) > 0) {
drag_scroll = -2;
} else {
drag_scroll = 0;
}
y_offset += drag_scroll;
y_offset = Math.min(y_offset, 0);
y_offset = Math.max(y_offset, -1 * (bg_height - ui_height));
}
y_offset += drag_scroll;
y_offset = Math.min(y_offset, 0);
y_offset = Math.max(y_offset, -1 * (bg_height - ui_height));
}
mgraphics.redraw();
mgraphics.redraw();
}
last_x = x;
last_y = y;
}
} else if (drag_mode === 2) {
// Drag to interpolate across adjacent (previous and next) presets
if (is_dragging == 0) {
var dist_from_start = Math.sqrt((x-last_x)*(x-last_x)+(y-last_y)*(y-last_y));
if (dist_from_start > 3) {
is_dragging = 2;
}
}
// 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 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;
for (var i = 0; i < filled_slots.length; i++) {
var p = filled_slots[i];
if (p <= current_slot) {
if (prev_filled_slot === -1 || p > prev_filled_slot) {
prev_filled_slot = p;
}
} else if (p > current_slot) {
if (next_filled_slot === -1 || p < next_filled_slot) {
next_filled_slot = p;
}
}
}
var interp_amount = 0;
if (prev_filled_slot === -1) {
prev_filled_slot = next_filled_slot;
interp_amount = 1;
} else if (next_filled_slot === -1) {
next_filled_slot = prev_filled_slot;
interp_amount = 1;
} else if (prev_filled_slot > 0 && next_filled_slot > 0) {
interp_amount = (last_hovered + relative_dist_from_start - prev_filled_slot) / (next_filled_slot - prev_filled_slot);
interp_amount = Math.min(interp_amount, Math.max(interp_amount, 0), 1);
}
if (prev_filled_slot !== -1 || next_filled_slot !== -1) {
to_pattrstorage("recall", prev_filled_slot, next_filled_slot, interp_amount);
}
last_x = x;
last_y = y;
if (!but) {
is_dragging = 0;
}
}
} else if (drag_mode === 3) {
// Drag to interpolate across adjacent (previous and next) presets
if (is_dragging == 0) {
var dist_from_start = Math.sqrt((x-last_x)*(x-last_x)+(y-last_y)*(y-last_y));
if (dist_from_start > 3) {
is_dragging = 3;
}
}
// 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;
}
}
if (nearby_slots.length) {
var args = ["recallmulti"].concat(nearby_slots);
to_pattrstorage.apply(null, args);
recallmulti.apply(null, nearby_slots);
}
last_x = x;
last_y = y;
if (!but) {
is_dragging = 0;
}
}
last_x = x;
last_y = y;
}
}
}
@@ -2324,6 +2415,8 @@ function setselect_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("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;