Compare commits

...

27 Commits

Author SHA1 Message Date
6b07a8e90b menu_mode and recall_filled 2025-03-05 17:10:28 +01:00
aa2359c468 umenu update with set instead of setsymbol 2024-12-18 15:39:05 +01:00
69cbe9b235 folder name 2024-12-18 15:29:20 +01:00
76ad31163f fix issue when resyncing with out-of-grid new presets 2024-12-18 15:15:01 +01:00
4df1c2b7e1 prevent updating slotname when locked ; coll-compatible filled_slots dict 2024-12-04 10:51:42 +01:00
5b3b12e613 send_name attribute 2024-11-29 22:20:51 +01:00
f9a3711507 fix names as symboles in filled_slots_dict 2024-11-29 19:04:38 +01:00
af803d109e autowatch 2024-11-29 16:58:23 +01:00
3214f0c673 small perf improvements (less paint_base calls) ; create and maintain a Dict with filled slots info 2024-11-29 16:53:26 +01:00
65dd0ca8e0 Max 9 v8ui ready 2024-10-31 00:25:52 +01:00
83dc04b993 fix umenu set to item 0 when paint_base in layout 1 2024-08-23 00:45:13 +02:00
6f7ac37a05 fix false error when receiving write messages 2024-08-23 00:35:34 +02:00
5792689842 clean 2024-08-20 12:28:16 +02:00
1f6e2b5c5a fix preset disapearing if pushed away from displayed slot after a preset have been drag onto another 2024-08-20 12:24:40 +02:00
3b387c66d2 grid layout scrollable, auto-scroll when drag outside of window 2024-08-20 12:09:19 +02:00
e07e8ef9ca fix regression not interpreting recall feedback correctlty 2024-08-20 01:45:13 +02:00
8b91c7ad5d new snippet with color selector 2024-08-20 01:17:43 +02:00
f0a41a6687 maxref update 2024-08-20 00:49:17 +02:00
198718e2d2 readme and help file update 2024-08-20 00:42:23 +02:00
03fb521851 Reset color of selected slot by sending empty setcolor message 2024-08-19 19:31:01 +02:00
c82a9053bb Avoid errors when recall messages start by a string (parameter name) 2024-08-19 18:41:38 +02:00
b85e2ff66b protection against wrongly addressed write messages 2024-08-17 13:02:53 +02:00
66faf94f77 autowriteagain at preset color change 2024-08-17 12:46:23 +02:00
8149b21855 New presets use default colors 2024-08-16 11:23:05 +02:00
2b27dee78f Updated documentation and test patcher. 2024-08-11 20:18:23 +02:00
ec4e876d09 New color modes ready. 2024-08-11 18:37:40 +02:00
8c9691e18f slots: using dictionnary instead of array. Color modes "custom" and "free" in good progress. 2024-08-09 15:29:12 +02:00
9 changed files with 2397 additions and 1985 deletions

View File

@@ -17,7 +17,7 @@ A [jsui] replacement for the [preset] object in Cycling'74 Max.
- More look customization - More look customization
- Dynamically adapts to resize both in Edit and Presentation mode - 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) - 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) - Color mode: various ways to colorize preset slots
## How to install ## How to install
- [Download](https://github.com/Teufeuleu/tc.preset/archive/refs/heads/main.zip) this repository (and please consider donating on the [gumroad page](https://glucose47.gumroad.com/l/tc_preset) if you like this package) - [Download](https://github.com/Teufeuleu/tc.preset/archive/refs/heads/main.zip) this repository (and please consider donating on the [gumroad page](https://glucose47.gumroad.com/l/tc_preset) if you like this package)

View File

@@ -53,12 +53,24 @@
<description>Function depends on inlet</description> <description>Function depends on inlet</description>
</method> --> </method> -->
<method name="color_wheel"> <method name="color_wheel">
<digest>Set the slot colors</digest> <digest>Define color wheel colors</digest>
<description>The message "color_wheel", followed by an integer and four float, defines one of the 6 available slot colors when color_mode is enabled. <description>The message "color_wheel", followed by an integer and four float, defines one of the 6 available slot colors when color_mode is enabled.
The integer argument, between 1 and 6, defines which color in being modifier, and next the four floats define the color in the RGBA format. The integer argument, between 1 and 6, defines which color in being modified, and next the four floats define the color in the RGBA format.
The message "color_wheel" without argument resets the six colors to their default values. The message "color_wheel" without argument resets the six colors to their default values.
</description> </description>
</method> </method>
<method name="setcolor">
<digest>Set the preset colors</digest>
<description>The message "setcolor" allows to set the color of a preset as shown when in color_mode 2 (select) or 3 (custom).
With 1 or 2 integer arguments, it allows to set a preset color as seen in color mode 2. With 4 float arguments or 1 integer followed by 4 floats, it allows to set a preset color for the color mode 3.
With 1 integer argument, the currently selected preset color wheel's color is set to the argument's value.
With two integer arguments, the preset number defined by first argument is set to color wheel's color defined by the second argument.
With 4 float arguments, the currently selected preset is set to a custom color defined by the four arguments (in RGBA format).
With 1 integer followed by 4 float arguments, the preset number defined by first argument is set to a custom color defined by the four arguments (in RGBA format).
The integer argument, between 1 and 6, defines which color in being modifier, and next the four floats define the color in the RGBA format.
With no argument, it resets colors for the select preset to default values.
</description>
</method>
<method name="pattrstorage"> <method name="pattrstorage">
<digest>Link to named pattrstorage object</digest> <digest>Link to named pattrstorage object</digest>
<description>The word 'pattrstorage' followed by the name of an existing pattrstorage links the jsui to that pattrstorage. <description>The word 'pattrstorage' followed by the name of an existing pattrstorage links the jsui to that pattrstorage.
@@ -66,6 +78,11 @@
If the word `pattrstorage`is sent alone, the jsui is unlinked from any pattrstorage. If the word `pattrstorage`is sent alone, the jsui is unlinked from any pattrstorage.
</description> </description>
</method> </method>
<method name="recall_filled">
<digest>Recalls nth filled preset</digest>
<description>Recalls the nth filled preset. Example: 'recall_filled 3' will recall the third available filled preset from the preset list, regardless of its slot number.
</description>
</method>
<method name="resync"> <method name="resync">
<digest>Resync the jsui to the pattrstorage</digest> <digest>Resync the jsui to the pattrstorage</digest>
<description>The word 'resync' will repopulate the jsui with the current preset list from the pattrstorage. It is usefull in case you add/remove/edit presets without using the jsui. <description>The word 'resync' will repopulate the jsui with the current preset list from the pattrstorage. It is usefull in case you add/remove/edit presets without using the jsui.
@@ -113,7 +130,13 @@
</attribute> </attribute>
<attribute name='color_mode' get='1' set='1' type='int' size='1' > <attribute name='color_mode' get='1' set='1' type='int' size='1' >
<digest>Color mode</digest> <digest>Color mode</digest>
<description>When set to 0, all preset slots have the same color (same as the preset object). When set to 1, stored preset slots are colored. See color_1 to color_6 as well as the color_wheel message.</description> <description>When set to 0, all preset slots have the same color (same as the preset object) defined by the stored_slot_color attribute.
When set to 1, stored preset slots are colored according to one of the six colors of the color wheel, in a repeating pattern.
In mode 2, stored preset colors can be freely set to one of the six colors of the color wheel.
In mode 3, stored preset color can be set to any color in RGBA format.
To define colors of the color wheel for modes 1 and 2, see color_1 to color_6 as well as the color_wheel message.
To define preset color as in mode 2 or 3, see the setcolor message. Modes 2 and 3 require a pattr object named 'preset_color' to be at the same patcher level as the tc.preset object.
</description>
</attribute> </attribute>
<attribute name='color_1' get='1' set='1' type='list' size='4' > <attribute name='color_1' get='1' set='1' type='list' size='4' >
<digest>Slot color 1</digest> <digest>Slot color 1</digest>
@@ -156,6 +179,10 @@
<digest>Object margin</digest> <digest>Object margin</digest>
<description>Defines the size, in pixels, of the margin between the jsui border and the preset slots.</description> <description>Defines the size, in pixels, of the margin between the jsui border and the preset slots.</description>
</attribute> </attribute>
<attribute name='menu_mode' get='1' set='1' type='int' size='1' >
<digest>Menu mode</digest>
<description>Populates the umenu connected to 2nd outlet with preset number and name (0), preset number only (1), or name only (2). See recall_filled when using mode 2</description>
</attribute>
<attribute name='min_rows' get='1' set='1' type='int' size='1' > <attribute name='min_rows' get='1' set='1' type='int' size='1' >
<digest>Minimum number of rows to display</digest> <digest>Minimum number of rows to display</digest>
<description>Defines the minimum number of rows to display if scrollable is enabled and layout is set to 1. <description>Defines the minimum number of rows to display if scrollable is enabled and layout is set to 1.
@@ -164,7 +191,7 @@
</attribute> </attribute>
<attribute name='scrollable' get='1' set='1' type='int' size='1' > <attribute name='scrollable' get='1' set='1' type='int' size='1' >
<digest>Scroll through your presets</digest> <digest>Scroll through your presets</digest>
<description>When set to 1, you can through the jsui to see all your presets, or at least up to the slot number defined by the min_rows attributes. Currently only works with the list layout. <description>When set to 1, you can through the jsui to see all your presets, or at least up to the row defined by the min_rows attributes.
</description> </description>
</attribute> </attribute>
<attribute name='select_mode' get='1' set='1' type='int' size='1' > <attribute name='select_mode' get='1' set='1' type='int' size='1' >

View File

@@ -4,7 +4,7 @@
"appversion" : { "appversion" : {
"major" : 8, "major" : 8,
"minor" : 6, "minor" : 6,
"revision" : 3, "revision" : 4,
"architecture" : "x64", "architecture" : "x64",
"modernui" : 1 "modernui" : 1
} }
@@ -26,7 +26,7 @@
"toptoolbarpinned" : 2, "toptoolbarpinned" : 2,
"righttoolbarpinned" : 2, "righttoolbarpinned" : 2,
"bottomtoolbarpinned" : 2, "bottomtoolbarpinned" : 2,
"toolbars_unpinned_last_save" : 0, "toolbars_unpinned_last_save" : 15,
"tallnewobj" : 0, "tallnewobj" : 0,
"boxanimatetime" : 200, "boxanimatetime" : 200,
"enablehscroll" : 0, "enablehscroll" : 0,
@@ -80,7 +80,7 @@
} }
, { , {
"box" : { "box" : {
"embedstate" : [ [ "color_1", 0.743, 0.41, 0.501, 1 ], [ "autowriteagain", 0 ], [ "layout", 1 ], [ "color_6", 0.316, 0.616, 0.377, 1 ], [ "color_2", 0.679, 0.405, 0.669, 1 ], [ "empty_slot_color", 0.349, 0.349, 0.349, 1 ], [ "color_mode", 0 ], [ "stored_slot_color", 0.502, 0.502, 0.502, 1 ], [ "active_slot_color", 0.808, 0.898, 0.91, 1 ], [ "bgcolor", 0.2, 0.2, 0.2, 1 ], [ "slot_round", 0 ], [ "margin", 4 ], [ "color_3", 0.527, 0.459, 0.756, 1 ], [ "fontsize", 14 ], [ "text_color", 0.129, 0.129, 0.129, 1 ], [ "interp_slot_color", 1, 1, 1, 0.8 ], [ "scrollable", 1 ], [ "fontname", "Arial" ], [ "color_4", 0.367, 0.542, 0.712, 1 ], [ "ignoreslotzero", 1 ], [ "min_rows", 50 ], [ "text_bg_color", 1, 1, 1, 0.5 ], [ "color_5", 0.283, 0.606, 0.559, 1 ], [ "display_interp", 1 ], [ "bubblesize", 14 ], [ "spacing", 4 ], [ "select_mode", 0 ] ], "embedstate" : [ [ "spacing", 4 ], [ "color_3", 0.527, 0.459, 0.756, 1 ], [ "text_bg_color", 1, 1, 1, 0.5 ], [ "color_1", 0.743, 0.41, 0.501, 1 ], [ "color_2", 0.679, 0.405, 0.669, 1 ], [ "color_4", 0.367, 0.542, 0.712, 1 ], [ "select_mode", 0 ], [ "scrollable", 0 ], [ "bubblesize", 14 ], [ "margin", 4 ], [ "fontsize", 14 ], [ "color_mode", 0 ], [ "color_5", 0.283, 0.606, 0.559, 1 ], [ "ignoreslotzero", 1 ], [ "min_rows", 10 ], [ "stored_slot_color", 0.502, 0.502, 0.502, 1 ], [ "fontname", "Arial" ], [ "empty_slot_color", 0.349, 0.349, 0.349, 1 ], [ "text_color", 0.129, 0.129, 0.129, 1 ], [ "color_6", 0.316, 0.616, 0.377, 1 ], [ "display_interp", 1 ], [ "bgcolor", 0.2, 0.2, 0.2, 1 ], [ "slot_round", 0 ], [ "interp_slot_color", 1, 1, 1, 0.8 ], [ "active_slot_color", 0.808, 0.898, 0.91, 1 ], [ "autowriteagain", 0 ], [ "layout", 1 ] ],
"filename" : "tc.preset", "filename" : "tc.preset",
"id" : "obj-8", "id" : "obj-8",
"maxclass" : "jsui", "maxclass" : "jsui",
@@ -134,7 +134,7 @@
} }
, { , {
"box" : { "box" : {
"embedstate" : [ [ "color_1", 0.743, 0.41, 0.501, 1 ], [ "autowriteagain", 0 ], [ "layout", 0 ], [ "color_6", 0.316, 0.616, 0.377, 1 ], [ "color_2", 0.679, 0.405, 0.669, 1 ], [ "empty_slot_color", 0.349, 0.349, 0.349, 1 ], [ "color_mode", 0 ], [ "stored_slot_color", 0.502, 0.502, 0.502, 1 ], [ "active_slot_color", 0.808, 0.898, 0.91, 1 ], [ "bgcolor", 0.2, 0.2, 0.2, 1 ], [ "slot_round", 0 ], [ "margin", 4 ], [ "color_3", 0.527, 0.459, 0.756, 1 ], [ "fontsize", 14 ], [ "text_color", 0.129, 0.129, 0.129, 1 ], [ "interp_slot_color", 1, 1, 1, 0.8 ], [ "scrollable", 1 ], [ "fontname", "Arial" ], [ "color_4", 0.367, 0.542, 0.712, 1 ], [ "ignoreslotzero", 1 ], [ "min_rows", 50 ], [ "text_bg_color", 1, 1, 1, 0.5 ], [ "color_5", 0.283, 0.606, 0.559, 1 ], [ "display_interp", 1 ], [ "bubblesize", 14 ], [ "spacing", 4 ], [ "select_mode", 0 ] ], "embedstate" : [ [ "spacing", 4 ], [ "color_3", 0.527, 0.459, 0.756, 1 ], [ "text_bg_color", 1, 1, 1, 0.5 ], [ "color_1", 0.743, 0.41, 0.501, 1 ], [ "color_2", 0.679, 0.405, 0.669, 1 ], [ "color_4", 0.367, 0.542, 0.712, 1 ], [ "select_mode", 0 ], [ "scrollable", 0 ], [ "bubblesize", 14 ], [ "margin", 4 ], [ "fontsize", 14 ], [ "color_mode", 0 ], [ "color_5", 0.283, 0.606, 0.559, 1 ], [ "ignoreslotzero", 1 ], [ "min_rows", 10 ], [ "stored_slot_color", 0.502, 0.502, 0.502, 1 ], [ "fontname", "Arial" ], [ "empty_slot_color", 0.349, 0.349, 0.349, 1 ], [ "text_color", 0.129, 0.129, 0.129, 1 ], [ "color_6", 0.316, 0.616, 0.377, 1 ], [ "display_interp", 1 ], [ "bgcolor", 0.2, 0.2, 0.2, 1 ], [ "slot_round", 0 ], [ "interp_slot_color", 1, 1, 1, 0.8 ], [ "active_slot_color", 0.808, 0.898, 0.91, 1 ], [ "autowriteagain", 0 ], [ "layout", 0 ] ],
"filename" : "tc.preset", "filename" : "tc.preset",
"id" : "obj-3", "id" : "obj-3",
"maxclass" : "jsui", "maxclass" : "jsui",

File diff suppressed because it is too large Load Diff

View File

@@ -1,2 +1,2 @@
max objectfile tc.preset tc.preset; max objectfile tc.preset tc.preset;
max definesubstitution tc.preset jsui @filename tc.preset max definesubstitution tc.preset jsui @filename tc.preset;

View File

@@ -70,11 +70,12 @@ var layout = 0; // 0: grid mode (same as [preset]). 1: list mode
var display_interp = 1; // Enable/disable the UI feedback when interpolating between presets var display_interp = 1; // Enable/disable the UI feedback when interpolating between presets
var ignore_slot_zero = 1; // Makes previous_active_slot and interpolation display to ignore slot 0. Can be usefull when using slot 0 as a temporary step for interpolation. var ignore_slot_zero = 1; // Makes previous_active_slot and interpolation display to ignore slot 0. Can be usefull when using slot 0 as a temporary step for interpolation.
var auto_writeagain = 0; // When enabled, will send a "writeagain" to pattrstorage any time a preset is stored/deleted/moved/renamed/(un)locked var auto_writeagain = 0; // When enabled, will send a "writeagain" to pattrstorage any time a preset is stored/deleted/moved/renamed/(un)locked
var menu_number_only = 0; // Populates the umenu connected to 2nd outlet with stored preset number only, instead of number and name var menu_mode = 0; // Populates the umenu connected to 2nd outlet with preset number and name (0), preset number only (1), or name only (2)
var scrollable = 1; // Defines weither the object can be scrolled or not var scrollable = 0; // Defines weither the object can be scrolled or not
var min_rows = 50; // Minimum number of rows to display if scrollable is enabled var min_rows = 10; // Minimum number of rows to display if scrollable is enabled
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 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 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 send_name = "none"; // The global name to send presets dict name to (received by the [receive] object)
// (WORK) // (WORK)
var pattrstorage_name, pattrstorage_obj = null; var pattrstorage_name, pattrstorage_obj = null;
@@ -84,6 +85,7 @@ var slots = []; // Stores on screen box, name, lock and interpol
var slots_highest = 0; // Highest filled preset slot number var slots_highest = 0; // Highest filled preset slot number
var slots_count_display = 0; // Number of slots to be displayed var slots_count_display = 0; // Number of slots to be displayed
var filled_slots = []; // List of stored slots var filled_slots = []; // List of stored slots
var filled_slots_dict = new Dict();
var active_slot = 0; //Last recalled slot var active_slot = 0; //Last recalled slot
var previous_active_slot = 0; //Previously recalled slot var previous_active_slot = 0; //Previously recalled slot
@@ -101,10 +103,19 @@ var is_painting_base = 0;
var half_slot_size, half_margin, half_spacing; var half_slot_size, half_margin, half_spacing;
var last_x, last_y, last_hovered = -1; var last_x, last_y, last_hovered = -1;
var y_offset = 0; // handle scrolling var y_offset = 0; // handle scrolling
var drag_scroll = 0; // handle scrolling when dragging outside of boundaries
var shift_hold, option_hold = 0; var shift_hold, option_hold = 0;
var is_interpolating = 0; var is_interpolating = 0;
var is_dragging = 0; // Drag flag var is_dragging = 0; // Drag flag
var drag_slot = -1; // Stores the slot that's being dragged var drag_slot = -1; // Stores the slot that's being dragged
var is_writing = 0;
// Keeping track of various variables for dealing with color modes
var requested_slot = -1; // Which slot we're waiting a value for (used in get_all_preset_colors)
var color_mode_candidate = 0; // Which color mode we're aiming
var is_listening_to_subscriptionlist = 0; //Filters out received subscriptionlist messages when not updating slot color values
var is_listening_to_clientlist = 0; //Filters out received clientlist messages when not updating slot color values
var color_pattr;
var has_loaded = false; var has_loaded = false;
@@ -113,6 +124,42 @@ if (jsarguments.length>1) { // Depreciated, use "pattrstorage" attribute instead
} }
// FUNCTIONS // FUNCTIONS
function slot(left, top, right, bottom, name, lock, interp, color_index, color_custom) {
this.left = left;
this.top = top;
this.right = right;
this.bottom = bottom;
this.name = name;
this.lock = lock;
this.interp = interp;
this.color_index = color_index;
this.color_custom = color_custom;
this.init = function() {
this.left = 0;
this.top = 0;
this.right = 0;
this.bottom = 0;
this.name = null;
this.lock = 0;
this.interp = -1;
this.init_color();
}
this.init_color = function() {
this.color_index = 0;
this.color_custom = stored_slot_color;
}
this.clear = function() {
this.name = null;
this.lock = 0;
this.interp = -1;
this.color_index = 0;
this.color_custom = stored_slot_color;
}
}
function loadbang() { function loadbang() {
// post("loadbang\n"); // post("loadbang\n");
has_loaded = true; has_loaded = true;
@@ -125,20 +172,22 @@ function calc_rows_columns() {
half_spacing = spacing / 2; half_spacing = spacing / 2;
half_slot_size = slot_size / 2; half_slot_size = slot_size / 2;
slots[0] = [0, 0, 0, 0, "(tmp)", 0, -1]; // Slot 0 is valid, but not represented in the GUI (and never saved by pattrstorage) slots[0] = new slot(0, 0, 0, 0, "(tmp)", 0, -1, 0, stored_slot_color); // Slot 0 is valid, but not represented in the GUI (and never saved by pattrstorage)
if (layout == 0) { if (layout == 0) {
columns = Math.floor((ui_width - margin + spacing) / (slot_size + spacing)); columns = Math.floor((ui_width - margin + spacing) / (slot_size + spacing));
rows = Math.floor((ui_height - margin + spacing) / (slot_size + spacing)); rows = Math.floor((ui_height - margin + spacing) / (slot_size + spacing));
slots_count_display = columns * rows; if (scrollable) {
rows = Math.max(rows, Math.max(min_rows, Math.ceil(slots_highest/columns)));
}
} else { } else {
columns = 1; columns = 1;
rows = Math.floor((ui_height - margin + spacing) / (slot_size + spacing)); rows = Math.floor((ui_height - margin + spacing) / (slot_size + spacing));
if (scrollable) { if (scrollable) {
rows = Math.max(rows, Math.max(min_rows, slots_highest)); rows = Math.max(rows, Math.max(min_rows, slots_highest));
} }
slots_count_display = columns * rows;
} }
slots_count_display = columns * rows;
for (var i = 0; i < rows; i++) { for (var i = 0; i < rows; i++) {
var top = margin + i * (spacing+slot_size); var top = margin + i * (spacing+slot_size);
@@ -147,30 +196,13 @@ function calc_rows_columns() {
var left = margin + j * (spacing+slot_size); var left = margin + j * (spacing+slot_size);
var right = left + slot_size; var right = left + slot_size;
var cur = 1 + i * columns + j; var cur = 1 + i * columns + j;
var prev_name = null;
var prev_lock = 0; var prev_state = new slot();
var prev_interp = -1; prev_state.init();
if (typeof slots[cur] !== 'undefined') { if (typeof slots[cur] !== 'undefined') {
prev_name = slots[cur][4]; prev_state = slots[cur];
prev_lock = slots[cur][5];
prev_interp = slots[cur][6];
} }
slots[cur] = [left, top, right, bottom, prev_name, prev_lock, prev_interp]; slots[cur] = new slot(left, top, right, bottom, prev_state.name, prev_state.lock, prev_state.interp, prev_state.color_index, prev_state.color_custom);
//0: left position
//1: top position
//2: right position
//3: bottom position
//4: name, null if nothing stored on that slot
//5: lock state
//6: is being interpolated (0 or 1)
}
}
if (slots_count_display < slots_highest) {
for (var i = slots_count_display + 1; i <= slots_highest; i++) {
slots[i] = [0, 0, 0, 0, null, 0, -1];
} }
} }
paint_base(); paint_base();
@@ -185,21 +217,21 @@ function draw_slot(id, scale, cont) {
if(is_painting_base) { if(is_painting_base) {
draw_slot_bubble(slots[id][0] * scale, slots[id][1] *scale, slot_size * scale, slot_size * scale, cont); draw_slot_bubble(slots[id].left * scale, slots[id].top *scale, slot_size * scale, slot_size * scale, cont);
} else { } else {
draw_slot_bubble(slots[id][0] + offset, slots[id][1] + offset, slot_size * scale, slot_size * scale, cont); draw_slot_bubble(slots[id].left + offset, slots[id].top + offset, slot_size * scale, slot_size * scale, cont);
} }
cont.fill(); cont.fill();
if (layout == 1) { if (layout == 1) {
// slot text background // slot text background
var bg_txt_pos_x = margin + slot_size + spacing; var bg_txt_pos_x = margin + slot_size + spacing;
var bg_txt_pos_y = slots[id][1]; var bg_txt_pos_y = slots[id].top;
var bg_txt_dim_w = ui_width - (2*margin + slot_size + spacing); var bg_txt_dim_w = ui_width - (2*margin + slot_size + spacing);
var bg_txt_dim_h = slot_size; var bg_txt_dim_h = slot_size;
if (slots[id][4] != null) { if (slots[id].name != null) {
cont.set_source_rgba(stored_slot_color); cont.set_source_rgba(stored_slot_color);
} else { } else {
cont.set_source_rgba(empty_slot_color); cont.set_source_rgba(empty_slot_color);
@@ -252,12 +284,12 @@ draw_text_bubble.local = 1;
function format_slot_name(id) { function format_slot_name(id) {
var text = id; var text = id;
// If slot is locked, add brackets around its number // If slot is locked, add brackets around its number
if (slots[id][5] == 1) { if (slots[id].lock == 1) {
text = '[' + text + ']'; text = '[' + text + ']';
} }
// If slot has a name, append it to the preset name // If slot has a name, append it to the preset name
if (slots[id][4] != null) { if (slots[id].name != null) {
text += ': ' + slots[id][4]; text += ': ' + slots[id].name;
} }
text = text.toString(); text = text.toString();
return text; return text;
@@ -284,9 +316,13 @@ function paint_base() {
// All slots // All slots
for (var i = 1; i <= slots_count_display; i++) { for (var i = 1; i <= 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 if (i != drag_slot) { //We mask the slot that is currently dragged as it is drawn at the mouse position already
if (slots[i][4] != null) { if (slots[i].name != null) {
if (color_mode) { if (color_mode == 1) {
set_source_rgba(color_wheel_custom[i % color_wheel_size]); set_source_rgba(color_wheel_custom[i % color_wheel_size]);
} else if (color_mode == 2) {
set_source_rgba(color_wheel_custom[Math.abs(slots[i].color_index) % color_wheel_size]);
} else if (color_mode == 3) {
set_source_rgba(slots[i].color_custom);
} else { } else {
set_source_rgba(stored_slot_color); set_source_rgba(stored_slot_color);
} }
@@ -329,37 +365,40 @@ function paint()
if (is_dragging == 0 && active_slot > 0 && active_slot <= slots_count_display) { if (is_dragging == 0 && active_slot > 0 && active_slot <= slots_count_display) {
set_source_rgba(active_slot_color); set_source_rgba(active_slot_color);
if (color_mode) { if (color_mode) {
draw_slot_bubble(slots[active_slot][0]+1.5, slots[active_slot][1]+1.5, slot_size-3, slot_size-3); draw_slot_bubble(slots[active_slot].left+1.5, slots[active_slot].top+1.5, slot_size-3, slot_size-3);
set_line_width(3); set_line_width(3);
stroke(); stroke();
} else { } else {
draw_slot_bubble(slots[active_slot][0], slots[active_slot][1], slot_size, slot_size); draw_slot_bubble(slots[active_slot].left, slots[active_slot].top, slot_size, slot_size);
fill(); fill();
} }
} }
// Previous active slot // 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) {
// 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); 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 (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); draw_slot_bubble(slots[previous_active_slot].left+1.5, slots[previous_active_slot].top+1.5, slot_size-3, slot_size-3);
set_line_width(3); set_line_width(3);
stroke(); stroke();
} else { } else {
draw_slot_bubble(slots[previous_active_slot][0], slots[previous_active_slot][1], slot_size, slot_size); draw_slot_bubble(slots[previous_active_slot].left, slots[previous_active_slot].top, slot_size, slot_size);
fill(); fill();
} }
} }
//Hide dragged slot
if (is_dragging) {
set_source_rgba(empty_slot_color);
draw_slot_bubble(slots[drag_slot].left, slots[drag_slot].top, slot_size, slot_size);
fill();
}
// Selected slot // Selected slot
if (selected_slot > 0 && selected_slot <= slots_count_display) { if (selected_slot > 0 && selected_slot <= slots_count_display) {
set_source_rgba(active_slot_color); set_source_rgba(active_slot_color);
set_line_width(1); 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); draw_slot_bubble(slots[selected_slot].left - 0.5, slots[selected_slot].top - 0.5, slot_size + 1, slot_size + 1);
stroke(); stroke();
} }
@@ -367,12 +406,12 @@ function paint()
if (is_dragging == 0 && display_interp && is_interpolating) { if (is_dragging == 0 && display_interp && is_interpolating) {
for (var i = 1; i <= slots_count_display; i++) { for (var i = 1; i <= slots_count_display; i++) {
var interp = slots[i][6]; var interp = slots[i].interp;
if (interp >= 0) { if (interp >= 0) {
set_source_rgba(interp_slot_color); set_source_rgba(interp_slot_color);
draw_slot_bubble(slots[i][0], slots[i][1], slot_size, slot_size); draw_slot_bubble(slots[i].left, slots[i].top, slot_size, slot_size);
stroke(); stroke();
draw_slot_bubble(slots[i][0], slots[i][1] + slot_size * (1-interp), slot_size, slot_size * interp); draw_slot_bubble(slots[i].left, slots[i].top + slot_size * (1-interp), slot_size, slot_size * interp);
fill(); fill();
} }
} }
@@ -384,18 +423,19 @@ function paint()
if (option_hold) { if (option_hold) {
// About to delete // About to delete
set_source_rgba(empty_slot_color[0], empty_slot_color[1], empty_slot_color[2], 0.8); 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); draw_slot_bubble(slots[last_hovered].left + 1, slots[last_hovered].top + 1, slot_size-2, slot_size-2);
fill(); fill();
} else { } else {
// About to store // About to store
set_source_rgba(active_slot_color[0], active_slot_color[1], active_slot_color[2], 0.7); 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); draw_slot_bubble(slots[last_hovered].left + 1, slots[last_hovered].top + 1, slot_size-2, slot_size-2);
fill(); fill();
} }
} }
// Slot border // Slot border
set_source_rgba(1, 1, 1, 0.8); set_source_rgba(1, 1, 1, 0.8);
draw_slot_bubble(slots[last_hovered][0], slots[last_hovered][1], slot_size, slot_size); draw_slot_bubble(slots[last_hovered].left, slots[last_hovered].top, slot_size, slot_size);
stroke(); stroke();
if (layout == 0) { if (layout == 0) {
@@ -407,13 +447,13 @@ function paint()
var bg_txt_dim_w = text_dim[0] > slot_size ? text_dim[0] + 4 : slot_size + 4; 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_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_x = text_dim[0] > slot_size || is_dragging ? slots[last_hovered].left + slot_size + 2: slots[last_hovered].left - 2;
var bg_txt_pos_y = text_dim[1] > slot_size || is_dragging ? slots[last_hovered][1] - 2 : slots[last_hovered][1] - 2; var bg_txt_pos_y = text_dim[1] > slot_size || is_dragging ? slots[last_hovered].top - 2 : slots[last_hovered].top - 2;
// If there is not enough place, text is displayed on the left // If there is not enough place, text is displayed on the left
if (bg_txt_pos_x + bg_txt_dim_w > ui_width) { 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; bg_txt_pos_x = slots[last_hovered].left - half_spacing - bg_txt_dim_w;
} }
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_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);
@@ -475,13 +515,14 @@ function paint()
} }
} }
} }
paint.local = 1; paint.local = 0;
function color_wheel() { function color_wheel() {
// Rather than using an array of colors, each color has its own variable, so they can be declared as attributes and saved with the patch // Rather than using an array of colors, each color has its own variable, so they can be declared as attributes and saved with the patch
// But that makes the code sooo ugly... // But that makes the code sooo ugly...
var args = arrayfromargs(arguments); var args = arrayfromargs(arguments);
if (args.length == 0) { if (args.length == 0) {
// Reset to default
color_wheel_custom = []; color_wheel_custom = [];
color_wheel_custom = color_wheel_default.slice(); color_wheel_custom = color_wheel_default.slice();
color_1 = color_wheel_default[0]; color_1 = color_wheel_default[0];
@@ -491,6 +532,7 @@ function color_wheel() {
color_5 = color_wheel_default[4]; color_5 = color_wheel_default[4];
color_6 = color_wheel_default[5]; color_6 = color_wheel_default[5];
} else if (args.length == 5) { } else if (args.length == 5) {
// Set color
var n = args[0]; var n = args[0];
var col = [args[1], args[2], args[3], args[4]] var col = [args[1], args[2], args[3], args[4]]
if (n > 0 && n < 7) { if (n > 0 && n < 7) {
@@ -522,6 +564,100 @@ function color_wheel() {
paint_base(); paint_base();
} }
function setcolor() {
if (preset_color_pattr_exist()) {
var args = arrayfromargs(arguments);
var nb_args = args.length;
var slot_nb = selected_slot;
if (nb_args < 1 && nb_args > 5) {
error("color: wrong number of arguments.");
} else {
if (nb_args == 0) {
// Reset colors of selected slot to default values
slots[selected_slot].init_color();
} else if (nb_args == 1) {
// Set the color index of the currently selected slot (for when color_mode is 2)
slots[selected_slot].color_index = Math.floor(args);
} else if (nb_args == 2) {
// Set the color index to the 2nd argument for the slot number defined by the 1st argument
slot_nb = Math.floor(args[0]);
slots[slot_nb].color_index = Math.floor(args[1]);
} else if (nb_args == 4) {
// Set the custom color of the currently selected slot (for when color_mode is 3)
slots[selected_slot].color_custom = [args[0], args[1], args[2], args[3]];
} else if (nb_args == 5) {
// Set the custom color for the slot number defined by the 1st argument to the color defined by following arguments in rgba format.
slot_nb = Math.floor(args[0]);
slots[slot_nb].color_custom = [args[1], args[2], args[3], args[4]];
}
update_preset_color_pattr(slot_nb);
update_filled_slots_dict();
paint_base();
trigger_writeagain();
}
}
}
function preset_color_pattr_exist() {
var obj = this.patcher.getnamed("preset_color");
if (!obj) {
error("preset_color pattr not found.\n");
color_pattr = 0;
return false;
} else if (obj.maxclass != "pattr"){
error("preset_color named object is not a pattr object.\n");
color_pattr = 0;
return false;
} else if (obj.getattr('invisible') == 1) {
error("preset_color has been found but has invisible attribute set to 1\n");
color_pattr = 0;
return false;
} else {
color_pattr = obj;
return true;
}
}
preset_color_pattr_exist.local = 1;
function update_preset_color_pattr(s) {
var cstm = slots[s].color_custom;
to_pattrstorage("setstoredvalue", "preset_color", s, slots[s].color_index, cstm[0], cstm[1], cstm[2], cstm[3]);
}
update_preset_color_pattr.local = 1
function get_all_preset_colors() {
if (filled_slots.length) {
for (var i = 0; i < filled_slots.length; i++) {
get_preset_color(filled_slots[i]);
}
requested_slot = -1;
}
}
get_all_preset_colors.local = 1;
function get_preset_color(s) {
requested_slot = s;
to_pattrstorage("getstoredvalue", "preset_color", s);
}
get_preset_color.local = 1;
function preset_color() {
var args = arrayfromargs(arguments);
// post(pattrstorage_name, "preset_color", args, '----- args.length: ', args.length, '----- requested_slot: ', requested_slot,'\n');
if (args.length == 5) {
var col = Math.max(0, Math.floor(args[0])) % color_wheel_size;
slots[requested_slot].color_index = col;
slots[requested_slot].color_custom = [args[1], args[2], args[3], args[4]];
} else if (args.length == 4) {
slots[requested_slot].color_index = 0;
slots[requested_slot].color_custom = args;
} else if (args.length == 1) {
var col = Math.max(0, Math.floor(args)) % color_wheel_size;
slots[requested_slot].color_index = col;
slots[requested_slot].color_custom = stored_slot_color;
}
}
function anything() { function anything() {
// Here just to avoid error messages in case pattrstorage sends unhandled message, like when using getstoredvalue, getsubscriptionlist, getalias, etc. // Here just to avoid error messages in case pattrstorage sends unhandled message, like when using getstoredvalue, getsubscriptionlist, getalias, etc.
@@ -530,18 +666,18 @@ function anything() {
var v = arrayfromargs(arguments)[0]; var v = arrayfromargs(arguments)[0];
v = Math.floor(v); v = Math.floor(v);
if (v >= 0) { if (v >= 0) {
if (slots[v][5] > 0) { if (slots[v].lock > 0) {
error('cannot delete locked slot ' + v + '\n'); error('cannot delete locked slot ' + v + '\n');
} else { } else {
slots[v][4] = null; slots[v].name = null;
slots[v][6] = -1; slots[v].interp = -1;
if (active_slot == v) { if (active_slot == v) {
active_slot = 0; active_slot = 0;
} else if (previous_active_slot == v) { } else if (previous_active_slot == v) {
previous_active_slot = 0; previous_active_slot = 0;
} }
// to_pattrstorage("getslotname", v); if (is_dragging == 0) {
to_pattrstorage("delete", v); to_pattrstorage("delete", v);
to_pattrstorage("getslotlist"); to_pattrstorage("getslotlist");
paint_base(); paint_base();
@@ -556,6 +692,8 @@ function anything() {
} }
trigger_writeagain(); trigger_writeagain();
} }
}
} }
} else { } else {
// Passthrough to pattrstorage // Passthrough to pattrstorage
@@ -598,34 +736,43 @@ function slotlist() {
slots_highest = filled_slots[filled_slots.length - 1]; slots_highest = filled_slots[filled_slots.length - 1];
if (slots_count_display < slots_highest) { if (slots_count_display < slots_highest) {
for (var i = slots_count_display + 1; i <= slots_highest; i++) { for (var i = slots_count_display + 1; i <= slots_highest; i++) {
slots[i] = [0, 0, 0, 0, null, 0, -1]; slots[i] = new slot();
slots[i].init();
} }
} }
for (var i = 0; i < filled_slots.length; i++) { for (var i = 0; i < filled_slots.length; i++) {
to_pattrstorage("getslotname", filled_slots[i]); to_pattrstorage("getslotname", filled_slots[i]);
} }
get_all_preset_colors();
update_filled_slots_dict();
} }
} }
function slotname() { function slotname() {
var args = arrayfromargs(arguments); var args = arrayfromargs(arguments);
if (args[0] > 0 && args[1] != "(undefined)") { if (args[0] > 0 && args[1] != "(undefined)") {
slots[args[0]][4] = args[1]; slots[args[0]].name = args[1];
} }
} }
function setslotname() { function setslotname() {
// Because [pattrstorage] doesn't output anything when renaming presets with "slotname", we use a custom "setslotname" instead, that will rename the active preset // Because [pattrstorage] doesn't output anything when renaming presets with "slotname", we use a custom "setslotname" instead, that will rename the active preset
if (active_slot > 0) { if (selected_slot > 0) {
if (slots[selected_slot].lock == 0) {
var sname = arrayfromargs(arguments).join(' '); var sname = arrayfromargs(arguments).join(' ');
slotname(selected_slot, sname); slotname(selected_slot, sname);
to_pattrstorage("slotname", selected_slot, sname); to_pattrstorage("slotname", selected_slot, sname);
update_umenu(); update_umenu();
update_filled_slots_dict();
select(selected_slot); select(selected_slot);
trigger_writeagain(); trigger_writeagain();
if (layout == 1) { if (layout == 1) {
paint_base(); paint_base();
} }
} else {
error('Cannot set name of locked slot\n');
}
} }
} }
@@ -640,15 +787,15 @@ function recall() {
is_interpolating = 0; is_interpolating = 0;
set_active_slot(args[0]); set_active_slot(args[0]);
outlet(0, 'recall', args[0]); outlet(0, 'recall', args[0]);
} else { } else if (args.length == 3) {
var src_slot = args[0]; var src_slot = args[0];
var trg_slot = args[1]; var trg_slot = args[1];
for (var i = 0; i < filled_slots.length; i++) { for (var i = 0; i < filled_slots.length; i++) {
slots[filled_slots[i]][6] = -1; slots[filled_slots[i]].interp = -1;
} }
if (slots[src_slot][4] != null && slots[trg_slot][4] != null) { if (slots[src_slot].name != null && slots[trg_slot].name != null) {
if (ignore_slot_zero == 1 && src_slot == 0) { if (ignore_slot_zero == 1 && src_slot == 0) {
// Set src_slot as if we were interpolating from the last recalled preset different than 0 // Set src_slot as if we were interpolating from the last recalled preset different than 0
@@ -662,8 +809,8 @@ function recall() {
} }
var interp = Math.min( 1, Math.max(0, args[2])); var interp = Math.min( 1, Math.max(0, args[2]));
if (interp == 0.0) { if (interp == 0.0) {
slots[src_slot][6] = -1; slots[src_slot].interp = -1;
slots[trg_slot][6] = -1; slots[trg_slot].interp = -1;
is_interpolating = 0; is_interpolating = 0;
if (previous_target != active_slot) { if (previous_target != active_slot) {
previous_active_slot = active_slot; previous_active_slot = active_slot;
@@ -675,28 +822,35 @@ function recall() {
set_active_slot(src_slot); set_active_slot(src_slot);
} else if (interp == 1.0) { } else if (interp == 1.0) {
slots[src_slot][6] = -1; slots[src_slot].interp = -1;
slots[trg_slot][6] = -1; slots[trg_slot].interp = -1;
is_interpolating = 0; is_interpolating = 0;
previous_target = trg_slot; previous_target = trg_slot;
set_active_slot(trg_slot); set_active_slot(trg_slot);
} else { } else {
slots[src_slot][6] = 1 - interp; slots[src_slot].interp = 1 - interp;
slots[trg_slot][6] = interp; slots[trg_slot].interp = interp;
is_interpolating = 1; is_interpolating = 1;
active_slot = 0; active_slot = 0;
// set_active_slot(0);
} }
outlet(0, "recall", src_slot, trg_slot, interp); outlet(0, "recall", src_slot, trg_slot, interp);
} }
} }
mgraphics.redraw(); mgraphics.redraw();
} }
function recall_filled() {
// Recalling preset by its number in the filled_slots list. Useful when used menu_mode 2
var args = arrayfromargs(arguments);
var index = args[0];
if (index < filled_slots.length) {
to_pattrstorage('recall', filled_slots[args[0]]);
}
}
function recallmulti() { function recallmulti() {
var args = arrayfromargs(arguments); var args = arrayfromargs(arguments);
var interp_slots = []; var interp_slots = [];
@@ -711,12 +865,12 @@ function recallmulti() {
for (var i = 0; i < interp_slots.length; i++) { for (var i = 0; i < interp_slots.length; i++) {
var nb = interp_slots[i][0]; var nb = interp_slots[i][0];
if (slots[nb][4] != null) { if (slots[nb].name != null) {
interp_slots[i][1] /= summed_weight; interp_slots[i][1] /= summed_weight;
} else { } else {
interp_slots[i][1] = -1; interp_slots[i][1] = -1;
} }
slots[nb][6] = interp_slots[i][1] slots[nb].interp = interp_slots[i][1]
} }
is_interpolating = 1; is_interpolating = 1;
@@ -729,11 +883,16 @@ function recallmulti() {
function store(v) { function store(v) {
v = Math.floor(v); v = Math.floor(v);
if (v >= 0) { if (v >= 0) {
if (slots[v][5] > 0) { if (slots[v] && slots[v].lock > 0) {
error('cannot overwrite locked slot ' + v + '\n'); error('cannot overwrite locked slot ' + v + '\n');
} else { } else {
var recalc_rows_flag = scrollable && v > slots_highest; var recalc_rows_flag = scrollable && v > slots_highest;
if (color_pattr) {
//Initialize preset color pattr to default for new preset (otherwise, previously set color is used)
color_pattr.message(0);
}
to_pattrstorage("store", v); to_pattrstorage("store", v);
to_pattrstorage("getslotlist"); to_pattrstorage("getslotlist");
@@ -749,6 +908,7 @@ function store(v) {
outlet(0, "store", v); outlet(0, "store", v);
if (v) { if (v) {
// We writagain only if stored preset is > 0
trigger_writeagain(); trigger_writeagain();
} }
} }
@@ -765,6 +925,7 @@ function lock() {
to_pattrstorage("lock", args[0], args[1]); to_pattrstorage("lock", args[0], args[1]);
to_pattrstorage("getlockedslots"); to_pattrstorage("getlockedslots");
outlet(0, "lock", args[0], args[1]); outlet(0, "lock", args[0], args[1]);
update_filled_slots_dict();
trigger_writeagain(); trigger_writeagain();
if (layout == 1) { if (layout == 1) {
paint_base(); paint_base();
@@ -775,11 +936,11 @@ function lock() {
function lockedslots() { function lockedslots() {
var locked_slots = arrayfromargs(arguments); var locked_slots = arrayfromargs(arguments);
for (var i = 1; i < slots.length; i++) { for (var i = 1; i < slots.length; i++) {
slots[i][5] = 0; slots[i].lock = 0;
} }
if (locked_slots.length) { if (locked_slots.length) {
for (var i = 0; i < locked_slots.length; i++) { for (var i = 0; i < locked_slots.length; i++) {
slots[locked_slots[i]][5] = 1; slots[locked_slots[i]].lock = 1;
if (locked_slots[i] == selected_slot) { if (locked_slots[i] == selected_slot) {
select(selected_slot); select(selected_slot);
} }
@@ -789,6 +950,8 @@ function lockedslots() {
function write() { function write() {
var args = arrayfromargs(arguments); var args = arrayfromargs(arguments);
if (is_writing) {
is_writing = 0;
var filename = args[0]; var filename = args[0];
var state = args[1]; var state = args[1];
if (state) { if (state) {
@@ -796,6 +959,12 @@ function write() {
} else { } else {
error(pattrstorage_name + ': error while writing ' + filename + '\n'); error(pattrstorage_name + ': error while writing ' + filename + '\n');
} }
} else {
if (args.length < 2) {
error("Send your write messages directly to the pattrstorage instead.\n");
}
}
} }
function read() { function read() {
@@ -806,6 +975,42 @@ function read() {
} }
} }
// Given that v8ui has a new read method that cannot be overriden, we need to use [substitute read readfile] between [pattrstorage] and [tc.prest]
function readfile(f, s) {
read(f, s);
}
function subscriptionlist() {
var client = arrayfromargs(arguments)[0];
if (is_listening_to_subscriptionlist) {
if (client == "preset_color") {
// [pattr preset_color] subscribed
// post("preset_color pattr object found and subscribed to bound pattrstorage. Switching to color mode", color_mode_candidate, '\n');
is_listening_to_subscriptionlist = 0;
color_mode = color_mode_candidate;
paint_base();
} else if (client == "done") {
error("A [pattr preset_color] object has been found but it isn't subscribed to your pattrstorage. Please add it to your subscribelist and try changing color mode again.\n")
is_listening_to_subscriptionlist = 0;
}
}
}
function clientlist() {
var client = arrayfromargs(arguments)[0];
if (is_listening_to_clientlist) {
if (client == "preset_color") {
// post("preset_color pattr object found and client to bound pattrstorage. Switching to color mode", color_mode_candidate, '\n');
is_listening_to_clientlist = 0;
color_mode = color_mode_candidate;
paint_base();
} else if (client == "done") {
error("A [pattr preset_color] object has been found but seems to be invisible to the pattrstorage.\n")
is_listening_to_clientlist = 0;
}
}
}
function resync() { function resync() {
set_active_slot(0); set_active_slot(0);
slots_clear(); slots_clear();
@@ -839,7 +1044,6 @@ find_pattrstorage.local = 1;
function to_pattrstorage() { function to_pattrstorage() {
if (pattrstorage_obj !== null) { if (pattrstorage_obj !== null) {
// post('To pattrstorage:', arrayfromargs(arguments), '\n');
pattrstorage_obj.message(arrayfromargs(arguments)); pattrstorage_obj.message(arrayfromargs(arguments));
} }
} }
@@ -849,20 +1053,19 @@ function select(v) {
selected_slot = v; selected_slot = v;
set_umenu(selected_slot); set_umenu(selected_slot);
if (selected_slot != 0) { if (selected_slot != 0) {
outlet(2, "set", slots[selected_slot][4]); outlet(2, "set", slots[selected_slot].name);
} else { } else {
outlet(2, "set"); outlet(2, "set");
} }
outlet(3, "set", slots[selected_slot][5]); outlet(3, "set", slots[selected_slot].lock);
} }
} }
function slots_clear() { function slots_clear() {
slots[0] = [0, 0, 0, 0, "(tmp)", 0, -1]; slots[0].init();
slots[0].name = "(tmp)";
for (var i = 1; i < slots.length; i++) { for (var i = 1; i < slots.length; i++) {
slots[i][4] = null; slots[i].clear();
slots[i][5] = 0;
slots[i][6] = -1;
} }
} }
slots_clear.local = 1; slots_clear.local = 1;
@@ -870,7 +1073,7 @@ slots_clear.local = 1;
function get_slot_index(x, y) { function get_slot_index(x, y) {
// Returns which slot is hovered by the mouse // Returns which slot is hovered by the mouse
for (var i = 1; i <= slots_count_display; i++) { for (var i = 1; i <= slots_count_display; i++) {
if (y > (slots[i][1] - half_spacing) && y < (slots[i][3] + half_spacing) && x > (slots[i][0] - half_spacing) && x < (slots[i][2] + half_spacing)) { if (y > (slots[i].top - half_spacing) && y < (slots[i].bottom + half_spacing) && x > (slots[i].left - half_spacing) && x < (slots[i].right + half_spacing)) {
return i; return i;
} }
@@ -897,29 +1100,60 @@ function update_umenu() {
for (var i=0; i < filled_slots.length; i++) { for (var i=0; i < filled_slots.length; i++) {
var nb = filled_slots[i]; var nb = filled_slots[i];
var txt = null; var txt = slots[filled_slots[i]].name;
if (!menu_number_only) { switch(menu_mode){
txt = slots[filled_slots[i]][4]; case 0:
}
outlet(1, "append", nb, txt); outlet(1, "append", nb, txt);
break;
case 1:
outlet(1, "append", nb);
break;
case 2:
outlet(1, "append", txt);
break;
}
}
if (layout == 1) {
set_umenu(selected_slot);
} }
} }
} }
update_umenu.local = 1; update_umenu.local = 1;
function update_filled_slots_dict() {
// Creates a coll-compatible dict containing slot id, name, lock, color index and color_custom for all existing presets
// And sends the dict name to a receive.
// Best would be to allow for single slot updates, but for that we need to be able to know which at index of filled_slot is a slot id.
filled_slots_dict.clear();
for (var i = 0; i < filled_slots.length; i++) {
var slot_index = filled_slots[i];
var tmp_color_custom = slots[slot_index].color_custom;
filled_slots_dict.set(slot_index, slots[slot_index].name, slots[slot_index].lock, slots[slot_index].color_index, tmp_color_custom[0], tmp_color_custom[1], tmp_color_custom[2], tmp_color_custom[3]);
}
// Non coll-compatible, but with proper keys:
// filled_slots_dict.set('filled_slots');
// for (var i = 0; i < filled_slots.length; i++) {
// if (i > 0) filled_slots_dict.append('filled_slots', '');
// var tmp_color_custom = slots[filled_slots[i]].color_custom;
// filled_slots_dict.setparse('filled_slots[' + i + ']', 'slot:', filled_slots[i], 'name:', '"' + slots[filled_slots[i]].name + '"', 'lock:', slots[filled_slots[i]].lock, 'color_index:', slots[filled_slots[i]].color_index, 'color_custom:', tmp_color_custom[0], tmp_color_custom[1], tmp_color_custom[2], tmp_color_custom[3]);
// }
var tmp_send_name = send_name == "none" ? pattrstorage_name + '_presets_dict' : send_name;
messnamed(tmp_send_name, 'dictionary', filled_slots_dict.name);
}
update_filled_slots_dict.local = 1;
function set_umenu(v) { function set_umenu(v) {
outlet(1, "clearchecks"); outlet(1, "clearchecks");
var item = filled_slots.indexOf(v); var item = filled_slots.indexOf(v);
outlet(1, "checkitem", item); outlet(1, "checkitem", item);
if (menu_number_only) { outlet(1, "set", item);
outlet(1, "setsymbol", v);
} else {
outlet(1, "setsymbol", v + ' ' + slots[v][4]);
}
} }
function trigger_writeagain() { function trigger_writeagain() {
if (auto_writeagain && !is_dragging) { if (auto_writeagain && !is_dragging) {
is_writing = 1;
to_pattrstorage("writeagain"); to_pattrstorage("writeagain");
} }
@@ -969,7 +1203,7 @@ function onclick(x,y,but,cmd,shift,capslock,option,ctrl)
if (option) { if (option) {
output = "delete"; output = "delete";
} }
} else if (slots[last_hovered][4] == null) { } else if (slots[last_hovered].name == null) {
return; return;
} }
if (output == "store") { if (output == "store") {
@@ -1004,33 +1238,35 @@ function ondrag(x,y,but,cmd,shift,capslock,option,ctrl)
{ {
if (pattrstorage_name != null) { if (pattrstorage_name != null) {
y -= y_offset; y -= y_offset;
if (is_dragging == 0 && last_hovered > 0 && slots[last_hovered][4] !== null) { if (is_dragging == 0 && last_hovered > 0 && slots[last_hovered].name !== null) {
// To prevent mistakes, is_dragging is set to 1 only when dragging for more than 10 pixels // 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)); var dist_from_start = Math.sqrt((x-last_x)*(x-last_x)+(y-last_y)*(y-last_y));
if (dist_from_start > 10) { if (dist_from_start > 10) {
is_dragging = 1; is_dragging = 1;
drag_slot = last_hovered; drag_slot = last_hovered;
paint_base();
} }
} else if (is_dragging == 1) { } else if (is_dragging == 1) {
last_hovered = get_slot_index(x, y); last_hovered = get_slot_index(x, y);
last_x = x;
last_y = y;
if (!but) { if (!but) {
// Wehen to button is released, the dragging ceases // When the button is released, the dragging ceases
if (last_hovered > 0 && last_hovered != drag_slot) { if (last_hovered > 0 && last_hovered != drag_slot) {
var cur_active_slot = active_slot; var cur_active_slot = active_slot;
var cur_prev_active_slot = previous_active_slot; var cur_prev_active_slot = previous_active_slot;
var offset = ((last_hovered <= drag_slot) && slots[last_hovered][4] != null) ? 1 : 0; var offset = ((last_hovered <= drag_slot) && slots[last_hovered].name != null) ? 1 : 0;
var offset_others = slots[last_hovered][4] != null ? 1 : 0; var offset_others = slots[last_hovered].name != null ? 1 : 0;
var drag_slot_lock = slots[drag_slot][5]; var drag_slot_lock = slots[drag_slot].lock;
var recalc_rows_flag = 0
// If the slot we wan to drag is locked, we need to temporarily unlock it. // If the slot we wan to drag is locked, we need to temporarily unlock it.
if (drag_slot_lock) { if (drag_slot_lock) {
lock(drag_slot, 0); lock(drag_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 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[last_hovered][4] !== null) { if (slots[last_hovered].name !== null) {
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;
}
to_pattrstorage("insert", last_hovered); to_pattrstorage("insert", last_hovered);
} }
@@ -1064,10 +1300,15 @@ function ondrag(x,y,but,cmd,shift,capslock,option,ctrl)
outlet(0, "drag", drag_slot, last_hovered, offset); outlet(0, "drag", drag_slot, last_hovered, offset);
is_dragging = 0; is_dragging = 0;
drag_slot = -1; drag_slot = -1;
paint_base();
select(last_hovered); select(last_hovered);
if (recalc_rows_flag) {
calc_rows_columns();
} else {
paint_base();
}
trigger_writeagain(); trigger_writeagain();
} else { } else {
@@ -1078,8 +1319,24 @@ function ondrag(x,y,but,cmd,shift,capslock,option,ctrl)
} }
} else { } else {
// Click still hold, we keep dragging // 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));
}
mgraphics.redraw(); mgraphics.redraw();
} }
last_x = x;
last_y = y;
} }
} }
} }
@@ -1115,6 +1372,7 @@ if (ui_width == 64 && ui_height == 64) {
// Allows for dynamic resizing even in presentation mode (addressing the limitation of onresize()) // Allows for dynamic resizing even in presentation mode (addressing the limitation of onresize())
var pres_rect = new MaxobjListener(this.box,"presentation_rect",get_prect); var pres_rect = new MaxobjListener(this.box,"presentation_rect",get_prect);
function get_prect(prect) { function get_prect(prect) {
// post(this.patcher.wind.assoc.getattr("globalpatchername") == max.frontpatcher.wind.assoc.getattr("globalpatchername") ? 1 : 0, "\n")
onresize(prect.value[2], prect.value[3]) onresize(prect.value[2], prect.value[3])
} }
get_prect.local = 1; get_prect.local = 1;
@@ -1355,6 +1613,17 @@ function setfontname(v){
} }
} }
declareattribute("menu_mode", "getmenu_mode", "setmenu_mode", 1);
function getmenu_mode() {
return menu_mode;
}
function setmenu_mode(v){
if (arguments.length == 1) {
menu_mode = Math.min(Math.max(0, parseInt(v)), 2);
update_umenu();
}
}
declareattribute("autowriteagain", "getautowriteagain", "setautowriteagain", 1); declareattribute("autowriteagain", "getautowriteagain", "setautowriteagain", 1);
function getautowriteagain() { function getautowriteagain() {
return auto_writeagain; return auto_writeagain;
@@ -1450,12 +1719,34 @@ function getcolor_mode() {
return color_mode; return color_mode;
} }
function setcolor_mode(v){ function setcolor_mode(v){
if (v == 1) { v = Math.floor(v);
color_mode = 1; v = Math.max(0, Math.min(3, v));
} else { // For color modes 2 and 3 (select and custom),
color_mode = 0; // we need to ensure there's a [pattr preset_color] somewhere to store the preset color
} if (v >= 2 ) {
if (!preset_color_pattr_exist()) {
v = 0;
color_mode = v;
paint_base(); paint_base();
} else {
if (pattrstorage_obj != null && pattrstorage_obj.getattr('subscribemode') == 1) {
// If the pattrstorage is in subscribe mode, we need to query its subscription list,
// ...and wait for the result to continue (see function subscribelist)
post(pattrstorage_name, "subscribe mode detected. Checking for subscribed 'preset_color' client.\n");
is_listening_to_subscriptionlist = 1;
color_mode_candidate = v;
to_pattrstorage("getsubscriptionlist");
} else {
// If not in subscribe mode
is_listening_to_clientlist = 1;
color_mode_candidate = v;
to_pattrstorage("getclientlist");
}
}
} else {
color_mode = v;
paint_base();
}
} }
declareattribute("color_1", "getcolor1", "setcolor1", 1); declareattribute("color_1", "getcolor1", "setcolor1", 1);
@@ -1543,6 +1834,18 @@ function setcolor6(){
} }
} }
declareattribute("send_name", "getsendname", "setsendname", 1);
function getsendname() {
return send_name;
}
function setsendname(){
if (arguments.length > 0) {
send_name = arguments[0];
} else {
send_name = "none";
}
}
// UTILITY // UTILITY
function post_keys(obj) { function post_keys(obj) {
post('Keys of obj: ', obj, '\n'); post('Keys of obj: ', obj, '\n');

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -400,7 +400,7 @@
"numinlets" : 1, "numinlets" : 1,
"filename" : "tc.preset.js", "filename" : "tc.preset.js",
"numoutlets" : 4, "numoutlets" : 4,
"embedstate" : [ [ "bgcolor", 0.2, 0.2, 0.2, 1 ], [ "active_slot_color", 0.808, 0.898, 0.91, 1 ], [ "fontname", "Arial" ], [ "pattrstorage", "mypat" ], [ "color_2", 0.679, 0.405, 0.669, 1 ], [ "text_bg_color", 1, 1, 1, 0.5 ], [ "interp_slot_color", 1, 1, 1, 0.8 ], [ "color_3", 0.527, 0.459, 0.756, 1 ], [ "layout", 0 ], [ "spacing", 4 ], [ "autowriteagain", 0 ], [ "scrollable", 1 ], [ "empty_slot_color", 0.349, 0.349, 0.349, 1 ], [ "color_4", 0.367, 0.542, 0.712, 1 ], [ "ignoreslotzero", 1 ], [ "slot_round", 0 ], [ "stored_slot_color", 0.502, 0.502, 0.502, 1 ], [ "bubblesize", 14 ], [ "min_rows", 50 ], [ "display_interp", 1 ], [ "color_5", 0.283, 0.606, 0.559, 1 ], [ "text_color", 0.129, 0.129, 0.129, 1 ], [ "margin", 4 ], [ "select_mode", 0 ], [ "fontsize", 14 ], [ "color_1", 0.743, 0.41, 0.501, 1 ], [ "color_mode", 0 ], [ "color_6", 0.316, 0.616, 0.377, 1 ] ] "embedstate" : [ [ "bgcolor", 0.2, 0.2, 0.2, 1 ], [ "active_slot_color", 0.808, 0.898, 0.91, 1 ], [ "fontname", "Arial" ], [ "pattrstorage", "mypat" ], [ "color_2", 0.679, 0.405, 0.669, 1 ], [ "text_bg_color", 1, 1, 1, 0.5 ], [ "interp_slot_color", 1, 1, 1, 0.8 ], [ "color_3", 0.527, 0.459, 0.756, 1 ], [ "layout", 0 ], [ "spacing", 4 ], [ "autowriteagain", 0 ], [ "scrollable", 0 ], [ "empty_slot_color", 0.349, 0.349, 0.349, 1 ], [ "color_4", 0.367, 0.542, 0.712, 1 ], [ "ignoreslotzero", 1 ], [ "slot_round", 0 ], [ "stored_slot_color", 0.502, 0.502, 0.502, 1 ], [ "bubblesize", 14 ], [ "min_rows", 10 ], [ "display_interp", 1 ], [ "color_5", 0.283, 0.606, 0.559, 1 ], [ "text_color", 0.129, 0.129, 0.129, 1 ], [ "margin", 4 ], [ "select_mode", 0 ], [ "fontsize", 14 ], [ "color_1", 0.743, 0.41, 0.501, 1 ], [ "color_mode", 0 ], [ "color_6", 0.316, 0.616, 0.377, 1 ] ]
} }
} }