{ "patcher": { "fileversion": 1, "appversion": { "major": 9, "minor": 1, "revision": 1, "architecture": "x64", "modernui": 1 }, "classnamespace": "box", "rect": [ 34.0, 77.0, 813.0, 570.0 ], "default_fontsize": 16.0, "boxes": [ { "box": { "fontface": 1, "fontsize": 20.0, "id": "obj-17", "maxclass": "comment", "numinlets": 1, "numoutlets": 0, "patching_rect": [ 622.5806496143341, 1009.4337722063065, 322.5806474685669, 29.0 ], "text": "load mtr01.txt and play here --->", "textcolor": [ 1.0, 0.0, 0.0, 1.0 ] } }, { "box": { "bgcolor": [ 0.7803921568627451, 0.5882352941176471, 0.8156862745098039, 1.0 ], "fontsize": 16.0, "id": "obj-47", "maxclass": "newobj", "numinlets": 0, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 996.3855789899826, 456.626522898674, 109.0, 27.0 ], "text": "r masschange" } }, { "box": { "id": "obj-185", "maxclass": "newobj", "numinlets": 1, "numoutlets": 0, "patching_rect": [ 936.1446129083633, 400.0000147819519, 104.0, 27.0 ], "text": "s massthresh" } }, { "box": { "id": "obj-184", "maxclass": "newobj", "numinlets": 1, "numoutlets": 0, "patching_rect": [ 936.1446129083633, 751.8072566986084, 153.0, 27.0 ], "text": "s forcechangethresh" } }, { "box": { "id": "obj-181", "maxclass": "newobj", "numinlets": 1, "numoutlets": 0, "patching_rect": [ 1633.7350001335144, 406.02411139011383, 109.0, 27.0 ], "text": "s speedthresh" } }, { "box": { "id": "obj-34", "maxclass": "number", "numinlets": 1, "numoutlets": 2, "outlettype": [ "", "bang" ], "parameter_enable": 0, "patching_rect": [ 1784.3374153375626, 95.18072640895844, 50.0, 27.0 ] } }, { "box": { "id": "obj-3", "maxclass": "number", "numinlets": 1, "numoutlets": 2, "outlettype": [ "", "bang" ], "parameter_enable": 0, "patching_rect": [ 1184.5060657262802, 433.7349557876587, 50.0, 27.0 ] } }, { "box": { "id": "obj-31", "maxclass": "number", "numinlets": 1, "numoutlets": 2, "outlettype": [ "", "bang" ], "parameter_enable": 0, "patching_rect": [ 1106.0241372585297, 86.74699115753174, 50.0, 27.0 ] } }, { "box": { "fontsize": 36.0, "id": "obj-4", "maxclass": "comment", "numinlets": 1, "numoutlets": 0, "patching_rect": [ 936.1446129083633, 145.78313791751862, 168.57143259048462, 48.0 ], "text": "MASS" } }, { "box": { "fontsize": 36.0, "id": "obj-5", "linecount": 2, "maxclass": "comment", "numinlets": 1, "numoutlets": 0, "patching_rect": [ 936.1446129083633, 496.3855605125427, 168.57143259048462, 89.0 ], "text": "FORCE CHANGE" } }, { "box": { "fontsize": 36.0, "id": "obj-23", "maxclass": "comment", "numinlets": 1, "numoutlets": 0, "patching_rect": [ 1633.7350001335144, 145.78313791751862, 131.0, 48.0 ], "text": "SPEED" } }, { "box": { "id": "obj-12", "maxclass": "message", "numinlets": 2, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 1045.7831711769104, 116.86747419834137, 44.0, 27.0 ], "text": "open" } }, { "box": { "filename": "none", "id": "obj-7", "maxclass": "v8ui", "numinlets": 1, "numoutlets": 1, "outlettype": [ "" ], "parameter_enable": 0, "patching_rect": [ 936.1446129083633, 156.62651181221008, 636.1446018218994, 236.1445870399475 ], "textfile": { "text": "// Max v8ui scrolling line display with draggable threshold lines\r\nmgraphics.init();\r\nmgraphics.relative_coords = 0;\r\nmgraphics.autofill = 0;\r\n\r\nvar values = [];\r\nvar maxPoints = 200;\r\nvar minVal = 0.;\r\nvar maxVal = 6000.;\r\nvar bgColor = [0.1, 0.1, 0.1, 1];\r\nvar lineColor = [0.0, 0.8, 1.0, 1];\r\nvar gridColor = [0.3, 0.3, 0.3, 1];\r\n\r\n// Threshold lines\r\nvar highThreshold = 80.; // Green line (trigger)\r\nvar lowThreshold = 20.; // Red line (hysteresis)\r\nvar highColor = [0.0, 1.0, 0.0, 1]; // Green\r\nvar lowColor = [1.0, 0.0, 0.0, 1]; // Red\r\nvar thresholdLineWidth = 2;\r\nvar grabRadius = 10; // How close mouse needs to be to grab line\r\n\r\n// Mouse interaction\r\nvar dragging = null; // 'high', 'low', or null\r\nvar hovering = null; // 'high', 'low', or null\r\n\r\n// Initialize with zero line\r\nfor (var i = 0; i < maxPoints; i++) {\r\n values[i] = 0;\r\n}\r\n\r\n// Receive new value\r\nfunction msg_float(v) {\r\n values.push(v);\r\n if (values.length > maxPoints) {\r\n values.shift();\r\n }\r\n mgraphics.redraw();\r\n}\r\n\r\nfunction msg_int(v) {\r\n msg_float(v);\r\n}\r\n\r\n// Map value from data range to screen coordinates\r\nfunction mapValue(val, h) {\r\n return h - ((val - minVal) / (maxVal - minVal)) * h;\r\n}\r\n\r\n// Map screen Y coordinate back to data value\r\nfunction unmapValue(y, h) {\r\n return minVal + (maxVal - minVal) * (1 - y / h);\r\n}\r\n\r\n// Check if mouse is near a threshold line\r\nfunction checkHover(x, y, w, h) {\r\n var highY = mapValue(highThreshold, h);\r\n var lowY = mapValue(lowThreshold, h);\r\n \r\n if (Math.abs(y - highY) < grabRadius) {\r\n return 'high';\r\n } else if (Math.abs(y - lowY) < grabRadius) {\r\n return 'low';\r\n }\r\n return null;\r\n}\r\n\r\n// Output threshold values as a list\r\nfunction outputThresholds() {\r\n outlet(0, [highThreshold, lowThreshold]);\r\n}\r\n\r\nfunction onclick(x, y, but, cmd, shift, capslock, option, ctrl) {\r\n var w = box.rect[2] - box.rect[0];\r\n var h = box.rect[3] - box.rect[1];\r\n \r\n dragging = checkHover(x, y, w, h);\r\n mgraphics.redraw();\r\n}\r\n\r\nfunction ondrag(x, y, but, cmd, shift, capslock, option, ctrl) {\r\n if (dragging) {\r\n var w = box.rect[2] - box.rect[0];\r\n var h = box.rect[3] - box.rect[1];\r\n \r\n var newVal = unmapValue(y, h);\r\n newVal = Math.max(minVal, Math.min(maxVal, newVal)); // Clamp to range\r\n \r\n if (dragging === 'high') {\r\n highThreshold = Math.max(newVal, lowThreshold + 0.1); // Keep high above low\r\n } else if (dragging === 'low') {\r\n lowThreshold = Math.min(newVal, highThreshold - 0.1); // Keep low below high\r\n }\r\n \r\n outputThresholds();\r\n mgraphics.redraw();\r\n }\r\n}\r\n\r\nfunction onidleout() {\r\n hovering = null;\r\n mgraphics.redraw();\r\n}\r\n\r\nfunction onidle(x, y, but, cmd, shift, capslock, option, ctrl) {\r\n var w = box.rect[2] - box.rect[0];\r\n var h = box.rect[3] - box.rect[1];\r\n \r\n var newHover = checkHover(x, y, w, h);\r\n if (newHover !== hovering) {\r\n hovering = newHover;\r\n mgraphics.redraw();\r\n }\r\n}\r\n\r\nfunction ondblclick(x, y, but, cmd, shift, capslock, option, ctrl) {\r\n dragging = null;\r\n}\r\n\r\nfunction paint() {\r\n var w = box.rect[2] - box.rect[0];\r\n var h = box.rect[3] - box.rect[1];\r\n \r\n // Background\r\n mgraphics.set_source_rgba(bgColor[0], bgColor[1], bgColor[2], bgColor[3]);\r\n mgraphics.rectangle(0, 0, w, h);\r\n mgraphics.fill();\r\n \r\n // Grid lines\r\n mgraphics.set_source_rgba(gridColor[0], gridColor[1], gridColor[2], gridColor[3]);\r\n mgraphics.set_line_width(1);\r\n \r\n // Zero line\r\n var zeroY = mapValue(0, h);\r\n mgraphics.move_to(0, zeroY);\r\n mgraphics.line_to(w, zeroY);\r\n mgraphics.stroke();\r\n \r\n // Min/max lines\r\n var maxY = mapValue(maxVal, h);\r\n var minY = mapValue(minVal, h);\r\n mgraphics.move_to(0, maxY);\r\n mgraphics.line_to(w, maxY);\r\n mgraphics.move_to(0, minY);\r\n mgraphics.line_to(w, minY);\r\n mgraphics.stroke();\r\n \r\n // Draw line graph\r\n if (values.length > 1) {\r\n mgraphics.set_source_rgba(lineColor[0], lineColor[1], lineColor[2], lineColor[3]);\r\n mgraphics.set_line_width(2);\r\n \r\n var xStep = w / (maxPoints - 1);\r\n var startIdx = Math.max(0, values.length - maxPoints);\r\n \r\n mgraphics.move_to(0, mapValue(values[startIdx], h));\r\n \r\n for (var i = 1; i < values.length; i++) {\r\n var x = i * xStep;\r\n var y = mapValue(values[startIdx + i], h);\r\n mgraphics.line_to(x, y);\r\n }\r\n \r\n mgraphics.stroke();\r\n }\r\n \r\n // Draw threshold lines\r\n var highY = mapValue(highThreshold, h);\r\n var lowY = mapValue(lowThreshold, h);\r\n \r\n // High threshold (green)\r\n var highAlpha = (hovering === 'high' || dragging === 'high') ? 1 : 0.7;\r\n var highWidth = (hovering === 'high' || dragging === 'high') ? 3 : thresholdLineWidth;\r\n mgraphics.set_source_rgba(highColor[0], highColor[1], highColor[2], highAlpha);\r\n mgraphics.set_line_width(highWidth);\r\n mgraphics.move_to(0, highY);\r\n mgraphics.line_to(w, highY);\r\n mgraphics.stroke();\r\n \r\n // Low threshold (red)\r\n var lowAlpha = (hovering === 'low' || dragging === 'low') ? 1 : 0.7;\r\n var lowWidth = (hovering === 'low' || dragging === 'low') ? 3 : thresholdLineWidth;\r\n mgraphics.set_source_rgba(lowColor[0], lowColor[1], lowColor[2], lowAlpha);\r\n mgraphics.set_line_width(lowWidth);\r\n mgraphics.move_to(0, lowY);\r\n mgraphics.line_to(w, lowY);\r\n mgraphics.stroke();\r\n \r\n // Draw labels\r\n mgraphics.select_font_face(\"Arial\");\r\n mgraphics.set_font_size(10);\r\n \r\n mgraphics.set_source_rgba(highColor[0], highColor[1], highColor[2], 1);\r\n mgraphics.move_to(5, highY - 5);\r\n mgraphics.show_text(\"High: \" + highThreshold.toFixed(2));\r\n \r\n mgraphics.set_source_rgba(lowColor[0], lowColor[1], lowColor[2], 1);\r\n mgraphics.move_to(5, lowY + 15);\r\n mgraphics.show_text(\"Low: \" + lowThreshold.toFixed(2));\r\n}\r\n\r\n// Set thresholds from outside\r\nfunction setthresholds(high, low) {\r\n highThreshold = Math.max(high, low + 0.1);\r\n lowThreshold = Math.min(low, high - 0.1);\r\n outputThresholds();\r\n mgraphics.redraw();\r\n}\r\n\r\nfunction clear() {\r\n values = [];\r\n for (var i = 0; i < maxPoints; i++) {\r\n values[i] = 0;\r\n }\r\n mgraphics.redraw();\r\n}\r\n\r\nfunction range(min, max) {\r\n minVal = min;\r\n maxVal = max;\r\n mgraphics.redraw();\r\n}\r\n\r\n// Output initial values on load\r\nfunction loadbang() {\r\n outputThresholds();\r\n}", "filename": "none", "flags": 0, "embed": 1, "autowatch": 1 }, "varname": "v8ui_AE" } }, { "box": { "id": "obj-9", "maxclass": "newobj", "numinlets": 3, "numoutlets": 1, "outlettype": [ "float" ], "patching_rect": [ 1126.5060657262802, 466.2650774717331, 68.0, 27.0 ], "text": "slide 1 5" } }, { "box": { "id": "obj-10", "maxclass": "message", "numinlets": 2, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 1724.0964492559433, 106.0241003036499, 44.0, 27.0 ], "text": "open" } }, { "box": { "id": "obj-374", "maxclass": "newobj", "numinlets": 3, "numoutlets": 1, "outlettype": [ "float" ], "patching_rect": [ 1633.7350001335144, 106.0241003036499, 68.0, 27.0 ], "text": "slide 1 5" } }, { "box": { "filename": "none", "id": "obj-373", "maxclass": "v8ui", "numinlets": 1, "numoutlets": 1, "outlettype": [ "" ], "parameter_enable": 0, "patching_rect": [ 1633.7350001335144, 145.78313791751862, 648.1927950382233, 246.98796093463898 ], "textfile": { "text": "// Max v8ui scrolling line display with draggable threshold lines\r\nmgraphics.init();\r\nmgraphics.relative_coords = 0;\r\nmgraphics.autofill = 0;\r\n\r\nvar values = [];\r\nvar maxPoints = 200;\r\nvar minVal = 0.;\r\nvar maxVal = 1.5;\r\nvar bgColor = [0.1, 0.1, 0.1, 1];\r\nvar lineColor = [0.0, 0.8, 1.0, 1];\r\nvar gridColor = [0.3, 0.3, 0.3, 1];\r\n\r\n// Threshold lines\r\nvar highThreshold = 1.5; // Green line (trigger)\r\nvar lowThreshold = 0.5; // Red line (hysteresis)\r\nvar highColor = [0.0, 1.0, 0.0, 1]; // Green\r\nvar lowColor = [1.0, 0.0, 0.0, 1]; // Red\r\nvar thresholdLineWidth = 2;\r\nvar grabRadius = 10; // How close mouse needs to be to grab line\r\n\r\n// Mouse interaction\r\nvar dragging = null; // 'high', 'low', or null\r\nvar hovering = null; // 'high', 'low', or null\r\n\r\n// Initialize with zero line\r\nfor (var i = 0; i < maxPoints; i++) {\r\n values[i] = 0;\r\n}\r\n\r\n// Receive new value\r\nfunction msg_float(v) {\r\n values.push(v);\r\n if (values.length > maxPoints) {\r\n values.shift();\r\n }\r\n mgraphics.redraw();\r\n}\r\n\r\nfunction msg_int(v) {\r\n msg_float(v);\r\n}\r\n\r\n// Map value from data range to screen coordinates\r\nfunction mapValue(val, h) {\r\n return h - ((val - minVal) / (maxVal - minVal)) * h;\r\n}\r\n\r\n// Map screen Y coordinate back to data value\r\nfunction unmapValue(y, h) {\r\n return minVal + (maxVal - minVal) * (1 - y / h);\r\n}\r\n\r\n// Check if mouse is near a threshold line\r\nfunction checkHover(x, y, w, h) {\r\n var highY = mapValue(highThreshold, h);\r\n var lowY = mapValue(lowThreshold, h);\r\n \r\n if (Math.abs(y - highY) < grabRadius) {\r\n return 'high';\r\n } else if (Math.abs(y - lowY) < grabRadius) {\r\n return 'low';\r\n }\r\n return null;\r\n}\r\n\r\n// Output threshold values as a list\r\nfunction outputThresholds() {\r\n outlet(0, [highThreshold, lowThreshold]);\r\n}\r\n\r\nfunction onclick(x, y, but, cmd, shift, capslock, option, ctrl) {\r\n var w = box.rect[2] - box.rect[0];\r\n var h = box.rect[3] - box.rect[1];\r\n \r\n dragging = checkHover(x, y, w, h);\r\n mgraphics.redraw();\r\n}\r\n\r\nfunction ondrag(x, y, but, cmd, shift, capslock, option, ctrl) {\r\n if (dragging) {\r\n var w = box.rect[2] - box.rect[0];\r\n var h = box.rect[3] - box.rect[1];\r\n \r\n var newVal = unmapValue(y, h);\r\n newVal = Math.max(minVal, Math.min(maxVal, newVal)); // Clamp to range\r\n \r\n if (dragging === 'high') {\r\n highThreshold = Math.max(newVal, lowThreshold + 0.1); // Keep high above low\r\n } else if (dragging === 'low') {\r\n lowThreshold = Math.min(newVal, highThreshold - 0.1); // Keep low below high\r\n }\r\n \r\n outputThresholds();\r\n mgraphics.redraw();\r\n }\r\n}\r\n\r\nfunction onidleout() {\r\n hovering = null;\r\n mgraphics.redraw();\r\n}\r\n\r\nfunction onidle(x, y, but, cmd, shift, capslock, option, ctrl) {\r\n var w = box.rect[2] - box.rect[0];\r\n var h = box.rect[3] - box.rect[1];\r\n \r\n var newHover = checkHover(x, y, w, h);\r\n if (newHover !== hovering) {\r\n hovering = newHover;\r\n mgraphics.redraw();\r\n }\r\n}\r\n\r\nfunction ondblclick(x, y, but, cmd, shift, capslock, option, ctrl) {\r\n dragging = null;\r\n}\r\n\r\nfunction paint() {\r\n var w = box.rect[2] - box.rect[0];\r\n var h = box.rect[3] - box.rect[1];\r\n \r\n // Background\r\n mgraphics.set_source_rgba(bgColor[0], bgColor[1], bgColor[2], bgColor[3]);\r\n mgraphics.rectangle(0, 0, w, h);\r\n mgraphics.fill();\r\n \r\n // Grid lines\r\n mgraphics.set_source_rgba(gridColor[0], gridColor[1], gridColor[2], gridColor[3]);\r\n mgraphics.set_line_width(1);\r\n \r\n // Zero line\r\n var zeroY = mapValue(0, h);\r\n mgraphics.move_to(0, zeroY);\r\n mgraphics.line_to(w, zeroY);\r\n mgraphics.stroke();\r\n \r\n // Min/max lines\r\n var maxY = mapValue(maxVal, h);\r\n var minY = mapValue(minVal, h);\r\n mgraphics.move_to(0, maxY);\r\n mgraphics.line_to(w, maxY);\r\n mgraphics.move_to(0, minY);\r\n mgraphics.line_to(w, minY);\r\n mgraphics.stroke();\r\n \r\n // Draw line graph\r\n if (values.length > 1) {\r\n mgraphics.set_source_rgba(lineColor[0], lineColor[1], lineColor[2], lineColor[3]);\r\n mgraphics.set_line_width(2);\r\n \r\n var xStep = w / (maxPoints - 1);\r\n var startIdx = Math.max(0, values.length - maxPoints);\r\n \r\n mgraphics.move_to(0, mapValue(values[startIdx], h));\r\n \r\n for (var i = 1; i < values.length; i++) {\r\n var x = i * xStep;\r\n var y = mapValue(values[startIdx + i], h);\r\n mgraphics.line_to(x, y);\r\n }\r\n \r\n mgraphics.stroke();\r\n }\r\n \r\n // Draw threshold lines\r\n var highY = mapValue(highThreshold, h);\r\n var lowY = mapValue(lowThreshold, h);\r\n \r\n // High threshold (green)\r\n var highAlpha = (hovering === 'high' || dragging === 'high') ? 1 : 0.7;\r\n var highWidth = (hovering === 'high' || dragging === 'high') ? 3 : thresholdLineWidth;\r\n mgraphics.set_source_rgba(highColor[0], highColor[1], highColor[2], highAlpha);\r\n mgraphics.set_line_width(highWidth);\r\n mgraphics.move_to(0, highY);\r\n mgraphics.line_to(w, highY);\r\n mgraphics.stroke();\r\n \r\n // Low threshold (red)\r\n var lowAlpha = (hovering === 'low' || dragging === 'low') ? 1 : 0.7;\r\n var lowWidth = (hovering === 'low' || dragging === 'low') ? 3 : thresholdLineWidth;\r\n mgraphics.set_source_rgba(lowColor[0], lowColor[1], lowColor[2], lowAlpha);\r\n mgraphics.set_line_width(lowWidth);\r\n mgraphics.move_to(0, lowY);\r\n mgraphics.line_to(w, lowY);\r\n mgraphics.stroke();\r\n \r\n // Draw labels\r\n mgraphics.select_font_face(\"Arial\");\r\n mgraphics.set_font_size(10);\r\n \r\n mgraphics.set_source_rgba(highColor[0], highColor[1], highColor[2], 1);\r\n mgraphics.move_to(5, highY - 5);\r\n mgraphics.show_text(\"High: \" + highThreshold.toFixed(2));\r\n \r\n mgraphics.set_source_rgba(lowColor[0], lowColor[1], lowColor[2], 1);\r\n mgraphics.move_to(5, lowY + 15);\r\n mgraphics.show_text(\"Low: \" + lowThreshold.toFixed(2));\r\n}\r\n\r\n// Set thresholds from outside\r\nfunction setthresholds(high, low) {\r\n highThreshold = Math.max(high, low + 0.1);\r\n lowThreshold = Math.min(low, high - 0.1);\r\n outputThresholds();\r\n mgraphics.redraw();\r\n}\r\n\r\nfunction clear() {\r\n values = [];\r\n for (var i = 0; i < maxPoints; i++) {\r\n values[i] = 0;\r\n }\r\n mgraphics.redraw();\r\n}\r\n\r\nfunction range(min, max) {\r\n minVal = min;\r\n maxVal = max;\r\n mgraphics.redraw();\r\n}\r\n\r\n// Output initial values on load\r\nfunction loadbang() {\r\n outputThresholds();\r\n}", "filename": "none", "flags": 0, "embed": 1, "autowatch": 1 }, "varname": "v8ui_AD" } }, { "box": { "bgcolor": [ 0.396078431372549, 0.48627450980392156, 0.5725490196078431, 1.0 ], "fontsize": 16.0, "id": "obj-371", "maxclass": "newobj", "numinlets": 0, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 1633.7350001335144, 75.90361726284027, 105.0, 27.0 ], "text": "r speedscalar" } }, { "box": { "id": "obj-366", "maxclass": "message", "numinlets": 2, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 936.1446129083633, 456.626522898674, 44.0, 27.0 ], "text": "open" } }, { "box": { "filename": "none", "id": "obj-364", "maxclass": "v8ui", "numinlets": 1, "numoutlets": 1, "outlettype": [ "" ], "parameter_enable": 0, "patching_rect": [ 936.1446129083633, 496.3855605125427, 639.7590597867966, 242.16868364810944 ], "textfile": { "text": "// Max v8ui scrolling line display with draggable threshold lines\r\nmgraphics.init();\r\nmgraphics.relative_coords = 0;\r\nmgraphics.autofill = 0;\r\n\r\nvar values = [];\r\nvar maxPoints = 200;\r\nvar minVal = -700.;\r\nvar maxVal = 1500.;\r\nvar bgColor = [0.1, 0.1, 0.1, 1];\r\nvar lineColor = [0.0, 0.8, 1.0, 1];\r\nvar gridColor = [0.3, 0.3, 0.3, 1];\r\n\r\n// Threshold lines\r\nvar highThreshold = 80.; // Green line (trigger)\r\nvar lowThreshold = 20.; // Red line (hysteresis)\r\nvar highColor = [0.0, 1.0, 0.0, 1]; // Green\r\nvar lowColor = [1.0, 0.0, 0.0, 1]; // Red\r\nvar thresholdLineWidth = 2;\r\nvar grabRadius = 10; // How close mouse needs to be to grab line\r\n\r\n// Mouse interaction\r\nvar dragging = null; // 'high', 'low', or null\r\nvar hovering = null; // 'high', 'low', or null\r\n\r\n// Initialize with zero line\r\nfor (var i = 0; i < maxPoints; i++) {\r\n values[i] = 0;\r\n}\r\n\r\n// Receive new value\r\nfunction msg_float(v) {\r\n values.push(v);\r\n if (values.length > maxPoints) {\r\n values.shift();\r\n }\r\n mgraphics.redraw();\r\n}\r\n\r\nfunction msg_int(v) {\r\n msg_float(v);\r\n}\r\n\r\n// Map value from data range to screen coordinates\r\nfunction mapValue(val, h) {\r\n return h - ((val - minVal) / (maxVal - minVal)) * h;\r\n}\r\n\r\n// Map screen Y coordinate back to data value\r\nfunction unmapValue(y, h) {\r\n return minVal + (maxVal - minVal) * (1 - y / h);\r\n}\r\n\r\n// Check if mouse is near a threshold line\r\nfunction checkHover(x, y, w, h) {\r\n var highY = mapValue(highThreshold, h);\r\n var lowY = mapValue(lowThreshold, h);\r\n \r\n if (Math.abs(y - highY) < grabRadius) {\r\n return 'high';\r\n } else if (Math.abs(y - lowY) < grabRadius) {\r\n return 'low';\r\n }\r\n return null;\r\n}\r\n\r\n// Output threshold values as a list\r\nfunction outputThresholds() {\r\n outlet(0, [highThreshold, lowThreshold]);\r\n}\r\n\r\nfunction onclick(x, y, but, cmd, shift, capslock, option, ctrl) {\r\n var w = box.rect[2] - box.rect[0];\r\n var h = box.rect[3] - box.rect[1];\r\n \r\n dragging = checkHover(x, y, w, h);\r\n mgraphics.redraw();\r\n}\r\n\r\nfunction ondrag(x, y, but, cmd, shift, capslock, option, ctrl) {\r\n if (dragging) {\r\n var w = box.rect[2] - box.rect[0];\r\n var h = box.rect[3] - box.rect[1];\r\n \r\n var newVal = unmapValue(y, h);\r\n newVal = Math.max(minVal, Math.min(maxVal, newVal)); // Clamp to range\r\n \r\n if (dragging === 'high') {\r\n highThreshold = Math.max(newVal, lowThreshold + 0.1); // Keep high above low\r\n } else if (dragging === 'low') {\r\n lowThreshold = Math.min(newVal, highThreshold - 0.1); // Keep low below high\r\n }\r\n \r\n outputThresholds();\r\n mgraphics.redraw();\r\n }\r\n}\r\n\r\nfunction onidleout() {\r\n hovering = null;\r\n mgraphics.redraw();\r\n}\r\n\r\nfunction onidle(x, y, but, cmd, shift, capslock, option, ctrl) {\r\n var w = box.rect[2] - box.rect[0];\r\n var h = box.rect[3] - box.rect[1];\r\n \r\n var newHover = checkHover(x, y, w, h);\r\n if (newHover !== hovering) {\r\n hovering = newHover;\r\n mgraphics.redraw();\r\n }\r\n}\r\n\r\nfunction ondblclick(x, y, but, cmd, shift, capslock, option, ctrl) {\r\n dragging = null;\r\n}\r\n\r\nfunction paint() {\r\n var w = box.rect[2] - box.rect[0];\r\n var h = box.rect[3] - box.rect[1];\r\n \r\n // Background\r\n mgraphics.set_source_rgba(bgColor[0], bgColor[1], bgColor[2], bgColor[3]);\r\n mgraphics.rectangle(0, 0, w, h);\r\n mgraphics.fill();\r\n \r\n // Grid lines\r\n mgraphics.set_source_rgba(gridColor[0], gridColor[1], gridColor[2], gridColor[3]);\r\n mgraphics.set_line_width(1);\r\n \r\n // Zero line\r\n var zeroY = mapValue(0, h);\r\n mgraphics.move_to(0, zeroY);\r\n mgraphics.line_to(w, zeroY);\r\n mgraphics.stroke();\r\n \r\n // Min/max lines\r\n var maxY = mapValue(maxVal, h);\r\n var minY = mapValue(minVal, h);\r\n mgraphics.move_to(0, maxY);\r\n mgraphics.line_to(w, maxY);\r\n mgraphics.move_to(0, minY);\r\n mgraphics.line_to(w, minY);\r\n mgraphics.stroke();\r\n \r\n // Draw line graph\r\n if (values.length > 1) {\r\n mgraphics.set_source_rgba(lineColor[0], lineColor[1], lineColor[2], lineColor[3]);\r\n mgraphics.set_line_width(2);\r\n \r\n var xStep = w / (maxPoints - 1);\r\n var startIdx = Math.max(0, values.length - maxPoints);\r\n \r\n mgraphics.move_to(0, mapValue(values[startIdx], h));\r\n \r\n for (var i = 1; i < values.length; i++) {\r\n var x = i * xStep;\r\n var y = mapValue(values[startIdx + i], h);\r\n mgraphics.line_to(x, y);\r\n }\r\n \r\n mgraphics.stroke();\r\n }\r\n \r\n // Draw threshold lines\r\n var highY = mapValue(highThreshold, h);\r\n var lowY = mapValue(lowThreshold, h);\r\n \r\n // High threshold (green)\r\n var highAlpha = (hovering === 'high' || dragging === 'high') ? 1 : 0.7;\r\n var highWidth = (hovering === 'high' || dragging === 'high') ? 3 : thresholdLineWidth;\r\n mgraphics.set_source_rgba(highColor[0], highColor[1], highColor[2], highAlpha);\r\n mgraphics.set_line_width(highWidth);\r\n mgraphics.move_to(0, highY);\r\n mgraphics.line_to(w, highY);\r\n mgraphics.stroke();\r\n \r\n // Low threshold (red)\r\n var lowAlpha = (hovering === 'low' || dragging === 'low') ? 1 : 0.7;\r\n var lowWidth = (hovering === 'low' || dragging === 'low') ? 3 : thresholdLineWidth;\r\n mgraphics.set_source_rgba(lowColor[0], lowColor[1], lowColor[2], lowAlpha);\r\n mgraphics.set_line_width(lowWidth);\r\n mgraphics.move_to(0, lowY);\r\n mgraphics.line_to(w, lowY);\r\n mgraphics.stroke();\r\n \r\n // Draw labels\r\n mgraphics.select_font_face(\"Arial\");\r\n mgraphics.set_font_size(10);\r\n \r\n mgraphics.set_source_rgba(highColor[0], highColor[1], highColor[2], 1);\r\n mgraphics.move_to(5, highY - 5);\r\n mgraphics.show_text(\"High: \" + highThreshold.toFixed(2));\r\n \r\n mgraphics.set_source_rgba(lowColor[0], lowColor[1], lowColor[2], 1);\r\n mgraphics.move_to(5, lowY + 15);\r\n mgraphics.show_text(\"Low: \" + lowThreshold.toFixed(2));\r\n}\r\n\r\n// Set thresholds from outside\r\nfunction setthresholds(high, low) {\r\n highThreshold = Math.max(high, low + 0.1);\r\n lowThreshold = Math.min(low, high - 0.1);\r\n outputThresholds();\r\n mgraphics.redraw();\r\n}\r\n\r\nfunction clear() {\r\n values = [];\r\n for (var i = 0; i < maxPoints; i++) {\r\n values[i] = 0;\r\n }\r\n mgraphics.redraw();\r\n}\r\n\r\nfunction range(min, max) {\r\n minVal = min;\r\n maxVal = max;\r\n mgraphics.redraw();\r\n}\r\n\r\n// Output initial values on load\r\nfunction loadbang() {\r\n outputThresholds();\r\n}", "filename": "none", "flags": 0, "embed": 1, "autowatch": 1 }, "varname": "v8ui_AC" } }, { "box": { "id": "obj-321", "maxclass": "newobj", "numinlets": 3, "numoutlets": 1, "outlettype": [ "float" ], "patching_rect": [ 936.1446129083633, 116.86747419834137, 68.0, 27.0 ], "text": "slide 1 5" } }, { "box": { "bgcolor": [ 0.0, 0.7019607843137254, 0.45098039215686275, 1.0 ], "id": "obj-319", "maxclass": "newobj", "numinlets": 0, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 936.1446129083633, 75.90361726284027, 113.0, 27.0 ], "text": "r centroidmass" } }, { "box": { "id": "obj-80", "maxclass": "message", "numinlets": 2, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 1100.0000406503677, 945.7831674814224, 41.0, 27.0 ], "text": "read" } }, { "box": { "id": "obj-67", "maxclass": "message", "numinlets": 2, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 1149.3976328372955, 945.7831674814224, 42.0, 27.0 ], "text": "write" } }, { "box": { "bgcolor": [ 0.618934978328545, 0.744701397656435, 0.953750108255376, 1.0 ], "color": [ 0.0, 0.0, 0.0, 1.0 ], "id": "obj-54", "maxclass": "newobj", "numinlets": 1, "numoutlets": 0, "patching_rect": [ 1095.1807633638382, 1051.8072677850723, 88.0, 27.0 ], "saved_attribute_attributes": { "bgcolor": { "expression": "themecolor.live_lcd_control_fg_alt" } }, "saved_newobj_attribute_attributes": { "bgcolor": { "expression": "themecolor.live_lcd_control_fg_alt" } }, "text": "s recswitch" } }, { "box": { "bgcolor": [ 0.3764705882352941, 0.3843137254901961, 0.4, 1.0 ], "bgcolor2": [ 0.3764705882352941, 0.3843137254901961, 0.4, 1.0 ], "bgfillcolor_angle": 270.0, "bgfillcolor_autogradient": 0.0, "bgfillcolor_color": [ 0.0, 0.854901960784314, 0.282352941176471, 1.0 ], "bgfillcolor_color1": [ 0.3764705882352941, 0.3843137254901961, 0.4, 1.0 ], "bgfillcolor_color2": [ 0.2901960784313726, 0.30980392156862746, 0.30196078431372547, 1.0 ], "bgfillcolor_proportion": 0.39, "bgfillcolor_type": "color", "fontname": "Arial", "fontsize": 20.0, "gradient": 1, "id": "obj-50", "maxclass": "message", "numinlets": 2, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 995.1807596683502, 949.3976254463196, 45.0, 31.0 ], "saved_attribute_attributes": { "bgfillcolor": { "expression": "themecolor.live_macro_assignment" } }, "text": "play" } }, { "box": { "id": "obj-32", "maxclass": "newobj", "numinlets": 1, "numoutlets": 2, "outlettype": [ "", "int" ], "patching_rect": [ 1140.9638975858688, 1010.8434108495712, 39.0, 27.0 ], "text": "t s 2" } }, { "box": { "id": "obj-15", "maxclass": "newobj", "numinlets": 1, "numoutlets": 2, "outlettype": [ "", "int" ], "patching_rect": [ 1074.6988348960876, 1010.8434108495712, 39.0, 27.0 ], "text": "t s 1" } }, { "box": { "fontsize": 20.0, "id": "obj-60", "maxclass": "comment", "numinlets": 1, "numoutlets": 0, "patching_rect": [ 667.0000023841858, 875.1707525253296, 167.0, 29.0 ], "text": "centroid threshold" } }, { "box": { "bgcolor": [ 0.101960784313725, 0.490196078431373, 0.945098039215686, 1.0 ], "fontsize": 20.0, "format": 6, "id": "obj-58", "maxclass": "flonum", "numinlets": 1, "numoutlets": 2, "outlettype": [ "", "bang" ], "parameter_enable": 0, "patching_rect": [ 611.0000023841858, 873.1707525253296, 55.0, 31.0 ], "saved_attribute_attributes": { "bgcolor": { "expression": "themecolor.live_prelisten" } } } }, { "box": { "bgcolor": [ 1.0, 0.349019607843137, 0.372549019607843, 1.0 ], "fontsize": 36.0, "id": "obj-55", "maxclass": "newobj", "numinlets": 0, "numoutlets": 0, "patcher": { "fileversion": 1, "appversion": { "major": 9, "minor": 1, "revision": 1, "architecture": "x64", "modernui": 1 }, "classnamespace": "box", "rect": [ 59.0, 107.0, 896.0, 544.0 ], "boxes": [ { "box": { "fontsize": 72.0, "format": 6, "id": "obj-53", "maxclass": "flonum", "numinlets": 1, "numoutlets": 2, "outlettype": [ "", "bang" ], "parameter_enable": 0, "patching_rect": [ 232.92683362960815, 313.0975682735443, 169.5121991634369, 91.0 ] } }, { "box": { "fontsize": 72.0, "format": 6, "id": "obj-54", "maxclass": "flonum", "numinlets": 1, "numoutlets": 2, "outlettype": [ "", "bang" ], "parameter_enable": 0, "patching_rect": [ 52.439024448394775, 313.0975682735443, 174.87804889678955, 91.0 ] } }, { "box": { "fontsize": 72.0, "format": 6, "id": "obj-52", "maxclass": "flonum", "numinlets": 1, "numoutlets": 2, "outlettype": [ "", "bang" ], "parameter_enable": 0, "patching_rect": [ 232.92683362960815, 485.048791885376, 174.87804889678955, 91.0 ] } }, { "box": { "fontsize": 72.0, "format": 6, "id": "obj-51", "maxclass": "flonum", "numinlets": 1, "numoutlets": 2, "outlettype": [ "", "bang" ], "parameter_enable": 0, "patching_rect": [ 50.0, 485.048791885376, 174.87804889678955, 91.0 ] } }, { "box": { "fontsize": 72.0, "format": 6, "id": "obj-50", "maxclass": "flonum", "numinlets": 1, "numoutlets": 2, "outlettype": [ "", "bang" ], "parameter_enable": 0, "patching_rect": [ 232.92683362960815, 146.34146451950073, 169.5121991634369, 91.0 ] } }, { "box": { "fontsize": 72.0, "format": 6, "id": "obj-49", "maxclass": "flonum", "numinlets": 1, "numoutlets": 2, "outlettype": [ "", "bang" ], "parameter_enable": 0, "patching_rect": [ 52.439024448394775, 146.34146451950073, 174.87804889678955, 91.0 ] } }, { "box": { "bgcolor": [ 0.0, 0.7019607843137254, 0.45098039215686275, 1.0 ], "fontsize": 20.0, "id": "obj-158", "maxclass": "newobj", "numinlets": 0, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 425.6097650527954, 100.0, 140.0, 31.0 ], "text": "r centroidmass" } }, { "box": { "bgcolor": [ 0.972549019607843, 0.462745098039216, 0.501960784313725, 1.0 ], "color": [ 0.0, 0.0, 0.0, 1.0 ], "fontsize": 20.0, "id": "obj-149", "maxclass": "newobj", "numinlets": 1, "numoutlets": 0, "patching_rect": [ 232.92683362960815, 446.3414716720581, 170.0, 31.0 ], "text": "s centroidy-scaled" } }, { "box": { "bgcolor": [ 0.972549019607843, 0.462745098039216, 0.501960784313725, 1.0 ], "color": [ 0.0, 0.0, 0.0, 1.0 ], "fontsize": 20.0, "id": "obj-151", "maxclass": "newobj", "numinlets": 1, "numoutlets": 0, "patching_rect": [ 52.439024448394775, 446.3414716720581, 170.0, 31.0 ], "text": "s centroidx-scaled" } }, { "box": { "bgcolor": [ 0.972549019607843, 0.462745098039216, 0.501960784313725, 1.0 ], "fontsize": 20.0, "id": "obj-147", "maxclass": "newobj", "numinlets": 0, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 232.92683362960815, 100.0, 102.0, 31.0 ], "text": "r centroidy" } }, { "box": { "bgcolor": [ 0.972549019607843, 0.462745098039216, 0.501960784313725, 1.0 ], "fontsize": 20.0, "id": "obj-148", "maxclass": "newobj", "numinlets": 0, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 52.439024448394775, 100.0, 102.0, 31.0 ], "text": "r centroidx" } }, { "box": { "bgcolor": [ 0.0, 0.7019607843137254, 0.45098039215686275, 1.0 ], "color": [ 0.0, 0.0, 0.0, 1.0 ], "fontsize": 20.0, "id": "obj-153", "maxclass": "newobj", "numinlets": 1, "numoutlets": 0, "patching_rect": [ 425.6097650527954, 446.3414716720581, 207.0, 31.0 ], "text": "s centroidmass-scaled" } }, { "box": { "fontsize": 20.0, "id": "obj-104", "maxclass": "newobj", "numinlets": 1, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 482.92683959007263, 140.2439033985138, 144.0, 31.0 ], "text": "loadmess 3200" } }, { "box": { "floatoutput": 1, "id": "obj-102", "maxclass": "slider", "numinlets": 1, "numoutlets": 1, "outlettype": [ "" ], "parameter_enable": 0, "patching_rect": [ 482.92683959007263, 176.82927012443542, 26.595744490623474, 143.61702024936676 ], "size": 4000.0, "valuepopup": 1 } }, { "box": { "floatoutput": 1, "id": "obj-98", "maxclass": "slider", "numinlets": 1, "numoutlets": 1, "outlettype": [ "" ], "parameter_enable": 0, "patching_rect": [ 425.6097650527954, 379.0, 164.89361584186554, 22.34042537212372 ], "size": 1.0 } }, { "box": { "floatoutput": 1, "id": "obj-97", "maxclass": "slider", "numinlets": 1, "numoutlets": 1, "outlettype": [ "" ], "parameter_enable": 0, "patching_rect": [ 232.92683362960815, 286.5853703022003, 164.89361584186554, 22.34042537212372 ], "size": 1.0 } }, { "box": { "floatoutput": 1, "id": "obj-77", "maxclass": "slider", "numinlets": 1, "numoutlets": 1, "outlettype": [ "" ], "parameter_enable": 0, "patching_rect": [ 52.439024448394775, 286.5853703022003, 164.89361584186554, 22.34042537212372 ], "size": 1.0 } }, { "box": { "fontname": "Arial", "fontsize": 20.0, "id": "obj-11", "maxclass": "newobj", "numinlets": 1, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 82.0, 406.0, 115.0, 31.0 ], "text": "expr 1. - $f1" } }, { "box": { "fontname": "Arial", "fontsize": 20.0, "id": "obj-10", "maxclass": "newobj", "numinlets": 1, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 267.4390244483948, 406.0975682735443, 115.0, 31.0 ], "text": "expr 1. - $f1" } }, { "box": { "fontname": "Arial", "fontsize": 20.0, "id": "obj-216", "maxclass": "newobj", "numinlets": 6, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 425.6097650527954, 337.0, 178.0, 31.0 ], "text": "scale 0. 3200. 0. 3." } }, { "box": { "fontname": "Arial", "fontsize": 20.0, "id": "obj-215", "maxclass": "newobj", "numinlets": 6, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 52.439024448394775, 245.12195467948914, 155.0, 31.0 ], "text": "scale 0.2 5. 0. 1." } }, { "box": { "fontname": "Arial", "fontsize": 20.0, "id": "obj-214", "maxclass": "newobj", "numinlets": 6, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 232.92683362960815, 245.12195467948914, 155.0, 31.0 ], "text": "scale 0.2 5. 0. 1." } } ], "lines": [ { "patchline": { "destination": [ "obj-216", 2 ], "source": [ "obj-102", 0 ] } }, { "patchline": { "destination": [ "obj-102", 0 ], "source": [ "obj-104", 0 ] } }, { "patchline": { "destination": [ "obj-214", 0 ], "order": 0, "source": [ "obj-147", 0 ] } }, { "patchline": { "destination": [ "obj-50", 0 ], "order": 1, "source": [ "obj-147", 0 ] } }, { "patchline": { "destination": [ "obj-215", 0 ], "order": 0, "source": [ "obj-148", 0 ] } }, { "patchline": { "destination": [ "obj-49", 0 ], "order": 1, "source": [ "obj-148", 0 ] } }, { "patchline": { "destination": [ "obj-216", 0 ], "source": [ "obj-158", 0 ] } }, { "patchline": { "destination": [ "obj-149", 0 ], "order": 1, "source": [ "obj-214", 0 ] } }, { "patchline": { "destination": [ "obj-52", 0 ], "order": 0, "source": [ "obj-214", 0 ] } }, { "patchline": { "destination": [ "obj-53", 0 ], "order": 2, "source": [ "obj-214", 0 ] } }, { "patchline": { "destination": [ "obj-97", 0 ], "order": 3, "source": [ "obj-214", 0 ] } }, { "patchline": { "destination": [ "obj-151", 0 ], "order": 0, "source": [ "obj-215", 0 ] } }, { "patchline": { "destination": [ "obj-51", 0 ], "order": 3, "source": [ "obj-215", 0 ] } }, { "patchline": { "destination": [ "obj-54", 0 ], "order": 1, "source": [ "obj-215", 0 ] } }, { "patchline": { "destination": [ "obj-77", 0 ], "order": 2, "source": [ "obj-215", 0 ] } }, { "patchline": { "destination": [ "obj-153", 0 ], "order": 0, "source": [ "obj-216", 0 ] } }, { "patchline": { "destination": [ "obj-98", 0 ], "order": 1, "source": [ "obj-216", 0 ] } } ], "default_bgcolor": [ 1.0, 0.349019607843137, 0.372549019607843, 1.0 ], "saved_attribute_attributes": { "bgcolor": { "expression": "themecolor.live_record" } } }, "patching_rect": [ 100.00000238418579, 1081.927750825882, 197.0, 50.0 ], "saved_attribute_attributes": { "bgcolor": { "expression": "themecolor.live_record" } }, "saved_newobj_attribute_attributes": { "bgcolor": { "expression": "themecolor.live_record" } }, "saved_object_attributes": { "bgcolor": [ 1.0, 0.349019607843137, 0.372549019607843, 1.0 ] }, "text": "p SCALING" } }, { "box": { "id": "obj-42", "maxclass": "newobj", "numinlets": 1, "numoutlets": 0, "patching_rect": [ 100.00000238418579, 1005.5759055614471, 40.0, 27.0 ], "text": "print" } }, { "box": { "fontname": "Arial", "fontsize": 20.0, "id": "obj-19", "maxclass": "message", "numinlets": 2, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 296.3414704799652, 873.1707525253296, 41.0, 31.0 ], "text": "info" } }, { "box": { "fontname": "Arial", "fontsize": 20.0, "id": "obj-18", "maxclass": "message", "numinlets": 2, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 245.12195706367493, 873.1707525253296, 46.0, 31.0 ], "text": "help" } }, { "box": { "bgcolor": [ 0.3764705882352941, 0.3843137254901961, 0.4, 1.0 ], "bgcolor2": [ 0.3764705882352941, 0.3843137254901961, 0.4, 1.0 ], "bgfillcolor_angle": 270.0, "bgfillcolor_autogradient": 0.0, "bgfillcolor_color": [ 0.0, 0.854901960784314, 0.282352941176471, 1.0 ], "bgfillcolor_color1": [ 0.3764705882352941, 0.3843137254901961, 0.4, 1.0 ], "bgfillcolor_color2": [ 0.2901960784313726, 0.30980392156862746, 0.30196078431372547, 1.0 ], "bgfillcolor_proportion": 0.39, "bgfillcolor_type": "color", "fontname": "Arial", "fontsize": 20.0, "gradient": 1, "id": "obj-22", "maxclass": "message", "numinlets": 2, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 160.97561359405518, 873.1707525253296, 70.0, 31.0 ], "saved_attribute_attributes": { "bgfillcolor": { "expression": "themecolor.live_macro_assignment" } }, "text": "open 8" } }, { "box": { "bgcolor": [ 0.172137149796092, 0.172137100044002, 0.172137113045018, 1.0 ], "bgcolor2": [ 0.172137149796092, 0.172137100044002, 0.172137113045018, 1.0 ], "bgfillcolor_angle": 270.0, "bgfillcolor_autogradient": 0.0, "bgfillcolor_color": [ 1.0, 0.349019607843137, 0.372549019607843, 1.0 ], "bgfillcolor_color1": [ 0.172137149796092, 0.172137100044002, 0.172137113045018, 1.0 ], "bgfillcolor_color2": [ 0.172137149796092, 0.172137100044002, 0.172137113045018, 1.0 ], "bgfillcolor_proportion": 0.5, "bgfillcolor_type": "color", "fontname": "Arial", "fontsize": 20.0, "gradient": 1, "id": "obj-20", "maxclass": "message", "numinlets": 2, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 100.00000238418579, 873.1707525253296, 55.0, 31.0 ], "saved_attribute_attributes": { "bgfillcolor": { "expression": "themecolor.live_record" } }, "text": "close" } }, { "box": { "fontsize": 36.0, "id": "obj-41", "maxclass": "newobj", "numinlets": 3, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 100.0, 915.8536803722382, 530.0000023841858, 50.0 ], "text": "sub_input-output" } }, { "box": { "fontsize": 20.0, "id": "obj-144", "maxclass": "newobj", "numinlets": 0, "numoutlets": 1, "outlettype": [ "" ], "patcher": { "fileversion": 1, "appversion": { "major": 9, "minor": 1, "revision": 1, "architecture": "x64", "modernui": 1 }, "classnamespace": "box", "rect": [ 168.0, 132.0, 896.0, 544.0 ], "boxes": [ { "box": { "id": "obj-1", "maxclass": "newobj", "numinlets": 1, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 526.0, 334.0, 79.0, 22.0 ], "text": "append 3 5 6" } }, { "box": { "id": "obj-6", "linecount": 2, "maxclass": "message", "numinlets": 2, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 46.0, 379.0, 429.0, 36.0 ], "text": "0.1 0. 0.6 0.5 0.3 0.1 0.2 0. 0.1 0. 0.1 0. 0.4 0. 0.2 0.2 0.4 0.9 0.1 0.4 0.3 0.4 0.9 0.9 0.2 0.8 0.1 0. 0. 0.1 1.3 0.4 1. 0.6 0.1 0. 0.588675 0.465812 0.010969 0" } }, { "box": { "fontsize": 12.0, "id": "obj-2", "maxclass": "comment", "numinlets": 1, "numoutlets": 0, "patching_rect": [ 668.0, 446.0, 57.0, 20.0 ], "text": "<- format" } }, { "box": { "fontsize": 12.0, "id": "obj-165", "maxclass": "message", "numinlets": 2, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 46.0, 447.5, 613.0, 22.0 ], "text": "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 y x 1 0 0 0 0" } }, { "box": { "bgcolor": [ 0.5019607843137255, 0.29411764705882354, 0.29411764705882354, 1.0 ], "fontsize": 12.0, "id": "obj-156", "maxclass": "newobj", "numinlets": 0, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 213.8245507478714, 237.0, 61.0, 22.0 ], "text": "r states" } }, { "box": { "bgcolor": [ 0.0, 0.7019607843137254, 0.45098039215686275, 1.0 ], "fontsize": 12.0, "id": "obj-158", "maxclass": "newobj", "numinlets": 0, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 171.53847312927246, 204.61539459228516, 126.0, 22.0 ], "text": "r centroidmass-scaled" } }, { "box": { "bgcolor": [ 0.972549019607843, 0.462745098039216, 0.501960784313725, 1.0 ], "fontsize": 12.0, "id": "obj-159", "maxclass": "newobj", "numinlets": 0, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 132.0, 161.0, 103.0, 22.0 ], "text": "r centroidy-scaled" } }, { "box": { "bgcolor": [ 0.972549019607843, 0.462745098039216, 0.501960784313725, 1.0 ], "fontsize": 12.0, "id": "obj-160", "maxclass": "newobj", "numinlets": 0, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 90.95613768696785, 132.30769538879395, 103.0, 22.0 ], "text": "r centroidx-scaled" } }, { "box": { "bgcolor": [ 0.262745098039216, 0.568627450980392, 0.901960784313726, 1.0 ], "fontsize": 12.0, "id": "obj-155", "maxclass": "newobj", "numinlets": 0, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 50.0, 100.0, 86.0, 22.0 ], "text": "r sensorlist" } }, { "box": { "fontsize": 12.0, "id": "obj-129", "maxclass": "newobj", "numinlets": 5, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 50.0, 270.7692470550537, 182.8245507478714, 22.0 ], "text": "join 5" } }, { "box": { "fontsize": 12.0, "id": "obj-55", "maxclass": "comment", "numinlets": 1, "numoutlets": 0, "patching_rect": [ 202.0, 133.30769538879395, 107.0, 20.0 ], "text": "swap for visualizer" } }, { "box": { "fontname": "Arial", "fontsize": 12.0, "id": "obj-4", "maxclass": "newobj", "numinlets": 1, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 438.0, 100.0, 244.0, 22.0 ], "text": "loadmess jsfile 05_visualizer_states_36x_.js" } }, { "box": { "fontname": "Arial", "fontsize": 12.0, "id": "obj-38", "maxclass": "message", "numinlets": 2, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 611.0, 198.0, 99.0, 22.0 ], "text": "scalecentroid 0.1" } }, { "box": { "fontname": "Arial", "fontsize": 12.0, "id": "obj-7", "maxclass": "message", "numinlets": 2, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 568.0, 166.15385246276855, 91.0, 22.0 ], "text": "scalecircles 1.5" } }, { "box": { "fontname": "Arial", "fontsize": 12.0, "id": "obj-5", "maxclass": "message", "numinlets": 2, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 511.5, 133.30769538879395, 97.0, 22.0 ], "text": "sensormax 1200" } }, { "box": { "comment": "", "id": "obj-143", "index": 1, "maxclass": "outlet", "numinlets": 1, "numoutlets": 0, "patching_rect": [ 649.4552157822268, 357.769257, 30.0, 30.0 ] } } ], "lines": [ { "patchline": { "destination": [ "obj-143", 0 ], "source": [ "obj-1", 0 ] } }, { "patchline": { "destination": [ "obj-1", 0 ], "source": [ "obj-129", 0 ] } }, { "patchline": { "destination": [ "obj-129", 0 ], "source": [ "obj-155", 0 ] } }, { "patchline": { "destination": [ "obj-129", 4 ], "source": [ "obj-156", 0 ] } }, { "patchline": { "destination": [ "obj-129", 3 ], "source": [ "obj-158", 0 ] } }, { "patchline": { "destination": [ "obj-129", 2 ], "source": [ "obj-159", 0 ] } }, { "patchline": { "destination": [ "obj-129", 1 ], "source": [ "obj-160", 0 ] } }, { "patchline": { "destination": [ "obj-143", 0 ], "source": [ "obj-38", 0 ] } }, { "patchline": { "destination": [ "obj-143", 0 ], "source": [ "obj-4", 0 ] } }, { "patchline": { "destination": [ "obj-143", 0 ], "source": [ "obj-5", 0 ] } }, { "patchline": { "destination": [ "obj-143", 0 ], "source": [ "obj-7", 0 ] } } ] }, "patching_rect": [ 187.49999284744263, 18.749999284744263, 242.0, 31.0 ], "text": "p sensorlist_attributes" } }, { "box": { "bgcolor": [ 0.262745098039216, 0.568627450980392, 0.901960784313726, 1.0 ], "fontsize": 20.0, "id": "obj-83", "maxclass": "newobj", "numinlets": 0, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 1036.1446166038513, 891.5662980079651, 105.0, 31.0 ], "text": "r sensorlist" } }, { "box": { "bgcolor": [ 0.309803921568627, 0.572549019607843, 0.611764705882353, 1.0 ], "fontsize": 20.0, "id": "obj-130", "maxclass": "newobj", "numinlets": 1, "numoutlets": 0, "patching_rect": [ 974.6988312005997, 1049.3976291418076, 90.0, 31.0 ], "text": "s reclist", "textcolor": [ 0.167919, 0.167914, 0.167917, 1.0 ] } }, { "box": { "fontsize": 20.0, "id": "obj-30", "maxclass": "comment", "numinlets": 1, "numoutlets": 0, "patching_rect": [ 458.3333158493042, 19.749999284744263, 486.0, 29.0 ], "text": "List: 36x sensors, centroid vector x, y, mass, 4x states" } }, { "box": { "fontname": "Arial", "fontsize": 20.0, "id": "obj-122", "maxclass": "comment", "numinlets": 1, "numoutlets": 0, "patching_rect": [ 1016.8675074577332, 855.4217183589935, 95.0, 29.0 ], "text": "RECORD" } }, { "box": { "fontname": "Arial", "fontsize": 20.0, "id": "obj-28", "maxclass": "newobj", "numinlets": 4, "numoutlets": 4, "outlettype": [ "", "", "", "" ], "patching_rect": [ 959.0361800193787, 1008.4337722063065, 63.0, 31.0 ], "saved_object_attributes": { "embed": 0 }, "text": "mtr 3" } }, { "box": { "fontname": "Arial", "fontsize": 20.0, "id": "obj-27", "maxclass": "message", "numinlets": 2, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 1007.2289528846741, 981.927747130394, 52.0, 31.0 ], "text": "clear" } }, { "box": { "bgcolor": [ 0.3764705882352941, 0.3843137254901961, 0.4, 1.0 ], "bgcolor2": [ 0.3764705882352941, 0.3843137254901961, 0.4, 1.0 ], "bgfillcolor_angle": 270.0, "bgfillcolor_autogradient": 0.0, "bgfillcolor_color": [ 1.0, 0.349019607843137, 0.372549019607843, 1.0 ], "bgfillcolor_color1": [ 0.3764705882352941, 0.3843137254901961, 0.4, 1.0 ], "bgfillcolor_color2": [ 0.2901960784313726, 0.30980392156862746, 0.30196078431372547, 1.0 ], "bgfillcolor_proportion": 0.39, "bgfillcolor_type": "color", "fontname": "Arial", "fontsize": 20.0, "gradient": 1, "id": "obj-14", "maxclass": "message", "numinlets": 2, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 973.4940118789673, 919.27714240551, 46.0, 31.0 ], "saved_attribute_attributes": { "bgfillcolor": { "expression": "themecolor.live_record" } }, "text": "stop" } }, { "box": { "bgcolor": [ 0.3764705882352941, 0.3843137254901961, 0.4, 1.0 ], "bgcolor2": [ 0.3764705882352941, 0.3843137254901961, 0.4, 1.0 ], "bgfillcolor_angle": 270.0, "bgfillcolor_autogradient": 0.0, "bgfillcolor_color": [ 0.101960784313725, 0.490196078431373, 0.945098039215686, 1.0 ], "bgfillcolor_color1": [ 0.3764705882352941, 0.3843137254901961, 0.4, 1.0 ], "bgfillcolor_color2": [ 0.2901960784313726, 0.30980392156862746, 0.30196078431372547, 1.0 ], "bgfillcolor_proportion": 0.39, "bgfillcolor_type": "color", "fontname": "Arial", "fontsize": 20.0, "gradient": 1, "id": "obj-8", "maxclass": "message", "numinlets": 2, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 959.0361800193787, 884.3373820781708, 65.0, 31.0 ], "saved_attribute_attributes": { "bgfillcolor": { "expression": "themecolor.live_spectrum_alternative_color" } }, "text": "record" } }, { "box": { "fontname": "Arial", "fontsize": 20.0, "id": "obj-6", "maxclass": "message", "numinlets": 2, "numoutlets": 1, "outlettype": [ "" ], "patching_rect": [ 99.99999618530273, 18.749999284744263, 53.0, 31.0 ], "text": "open" } }, { "box": { "filename": "07_visualizer_states_36x.js", "id": "obj-36", "maxclass": "v8ui", "numinlets": 1, "numoutlets": 1, "outlettype": [ "" ], "parameter_enable": 0, "patching_rect": [ 100.00000238418579, 74.39024567604065, 776.829286813736, 756.0975790023804 ], "textfile": { "text": "// visualiser.js\r\n// Dynamic 6x6 sensor visualiser with external centroid and mass input\r\n// Now supports 4 highlight indices (green points)\r\n\r\n// --- Core setup ---\r\nautowatch = 1;\r\nmgraphics.init();\r\nmgraphics.autofill = 0;\r\nmgraphics.relative_coords = 0;\r\n\r\n// --- Data storage ---\r\nvar gridSize = 6;\r\nvar values = new Array(36).fill(0);\r\nvar sensorMax = new Array(36).fill(700); // default max per sensor\r\nvar tracers = [];\r\nvar highlightIndices = []; // stores indices (1–36) that will be green\r\n\r\n// --- Parameters ---\r\nvar fadeFactor = 0.9;\r\nvar radiusMin = 5;\r\nvar radiusMax = 30;\r\nvar scaleCircles = 1.0;\r\nvar scaleCentroid = 1.0;\r\nvar tracerCount = 20;\r\n\r\n// --- Centroid ---\r\nvar cx = 0.5;\r\nvar cy = 0.5;\r\nvar weight = 0.5;\r\n\r\n// --- Initialize ---\r\nfunction initValues() {\r\n values = new Array(gridSize * gridSize).fill(0);\r\n}\r\ninitValues();\r\n\r\n// --- Receive list: 36 sensor values + centroidX + centroidY + mass + 4 highlights ---\r\nfunction list() {\r\n var a = arrayfromargs(arguments);\r\n if (a.length != 43) return; // expect 43 values total (36 + 3 + 4)\r\n\r\n // --- First 36: sensor values ---\r\n for (var i = 0; i < 36; i++) {\r\n var v = Math.max(0, a[i]);\r\n var vmax = Math.max(1, sensorMax[i]);\r\n values[i] = v / vmax;\r\n }\r\n\r\n // --- Next 3: centroid x, y, mass ---\r\n cx = Math.max(0, Math.min(1, a[36]));\r\n cy = Math.max(0, Math.min(1, a[37]));\r\n weight = Math.max(0, a[38]);\r\n\r\n // --- Last 4: highlight indices (1–36) ---\r\n highlightIndices = [];\r\n for (var i = 39; i < 43; i++) {\r\n var idx = Math.floor(a[i]) - 1; // convert 1-based to 0-based\r\n if (idx >= 0 && idx < 36 && highlightIndices.indexOf(idx) === -1)\r\n highlightIndices.push(idx);\r\n }\r\n\r\n // Add to tracers\r\n tracers.push({x: cx, y: cy, alpha: 1.0});\r\n if (tracers.length > tracerCount) tracers.shift();\r\n\r\n mgraphics.redraw();\r\n}\r\n\r\n// --- Set sensormax uniformly ---\r\nfunction sensormax(v) {\r\n v = Math.max(1, v);\r\n for (var i = 0; i < 36; i++) sensorMax[i] = v;\r\n}\r\n\r\n// --- Scaling controls ---\r\nfunction scalecircles(v) {\r\n scaleCircles = Math.max(0.1, v);\r\n}\r\nfunction scalecentroid(v) {\r\n scaleCentroid = Math.max(0.1, v);\r\n}\r\n\r\n// --- Grid size (optional) ---\r\nfunction grid(n) {\r\n gridSize = Math.max(1, Math.floor(n));\r\n initValues();\r\n mgraphics.redraw();\r\n}\r\n\r\n// --- Drawing ---\r\nfunction paint() {\r\n with (mgraphics) {\r\n var w = box.rect[2] - box.rect[0];\r\n var h = box.rect[3] - box.rect[1];\r\n var margin = 0.1;\r\n var gridW = w * (1 - 2 * margin);\r\n var gridH = h * (1 - 2 * margin);\r\n var gridCells = gridSize - 1;\r\n var cellW = gridW / gridCells;\r\n var cellH = gridH / gridCells;\r\n\r\n // Background\r\n set_source_rgba(0.05, 0.05, 0.05, 1);\r\n rectangle(0, 0, w, h);\r\n fill();\r\n\r\n // Grid lines\r\n set_source_rgba(0.4, 0.4, 0.4, 0.2);\r\n for (var i = 0; i <= gridCells; i++) {\r\n move_to(margin * w + i * cellW, margin * h);\r\n line_to(margin * w + i * cellW, margin * h + gridH);\r\n stroke();\r\n move_to(margin * w, margin * h + i * cellH);\r\n line_to(margin * w + gridW, margin * h + i * cellH);\r\n stroke();\r\n }\r\n\r\n // Circles (sensor nodes)\r\n for (var i = 0; i < gridSize; i++) {\r\n for (var j = 0; j < gridSize; j++) {\r\n var idx = i * gridSize + j;\r\n var val = values[idx];\r\n var radius = (radiusMin + val * (radiusMax - radiusMin)) * scaleCircles;\r\n var x = margin * w + j * cellW;\r\n var y = margin * h + (gridSize - 1 - i) * cellH;\r\n\r\n // Determine color\r\n if (highlightIndices.indexOf(idx) !== -1) {\r\n set_source_rgba(0.2, 0.9, 0.3, 0.9); // green\r\n } else {\r\n set_source_rgba(0.2, 0.6, 0.9, 0.8); // blue\r\n }\r\n\r\n ellipse(x - radius / 2, y - radius / 2, radius, radius);\r\n fill();\r\n }\r\n }\r\n\r\n // Tracers\r\n for (var t = 0; t < tracers.length; t++) {\r\n var tr = tracers[t];\r\n set_source_rgba(1, 0.2, 0.2, tr.alpha * 0.6);\r\n var tx = margin * w + tr.y * gridW;\r\n var ty = margin * h + (1 - tr.x) * gridH;\r\n ellipse(tx - 4, ty - 4, 8, 8);\r\n fill();\r\n tr.alpha *= fadeFactor;\r\n }\r\n\r\n // Centroid\r\n var cxPix = margin * w + cy * gridW;\r\n var cyPix = margin * h + (1 - cx) * gridH;\r\n var crad = (radiusMin + 15 * weight) * scaleCentroid;\r\n set_source_rgba(1, 0.2, 0.2, 1);\r\n ellipse(cxPix - crad / 2, cyPix - crad / 2, crad, crad);\r\n fill();\r\n }\r\n}", "filename": "07_visualizer_states_36x.js", "flags": 0, "embed": 1, "autowatch": 1 }, "varname": "v8ui_AA" } }, { "box": { "angle": 270.0, "bgcolor": [ 1.0, 1.0, 1.0, 0.07 ], "id": "obj-121", "maxclass": "panel", "mode": 0, "numinlets": 1, "numoutlets": 0, "patching_rect": [ 936.1446129083633, 842.1687058210373, 177.7777805328369, 246.0317498445511 ], "proportion": 0.5 } } ], "lines": [ { "patchline": { "destination": [ "obj-373", 0 ], "source": [ "obj-10", 0 ] } }, { "patchline": { "destination": [ "obj-7", 0 ], "source": [ "obj-12", 0 ] } }, { "patchline": { "destination": [ "obj-15", 0 ], "source": [ "obj-14", 0 ] } }, { "patchline": { "destination": [ "obj-36", 0 ], "source": [ "obj-144", 0 ] } }, { "patchline": { "destination": [ "obj-28", 0 ], "source": [ "obj-15", 0 ] } }, { "patchline": { "destination": [ "obj-54", 0 ], "source": [ "obj-15", 1 ] } }, { "patchline": { "destination": [ "obj-41", 0 ], "source": [ "obj-18", 0 ] } }, { "patchline": { "destination": [ "obj-41", 0 ], "source": [ "obj-19", 0 ] } }, { "patchline": { "destination": [ "obj-41", 0 ], "source": [ "obj-20", 0 ] } }, { "patchline": { "destination": [ "obj-41", 0 ], "source": [ "obj-22", 0 ] } }, { "patchline": { "destination": [ "obj-28", 0 ], "source": [ "obj-27", 0 ] } }, { "patchline": { "destination": [ "obj-130", 0 ], "source": [ "obj-28", 1 ] } }, { "patchline": { "destination": [ "obj-9", 2 ], "source": [ "obj-3", 0 ] } }, { "patchline": { "destination": [ "obj-321", 2 ], "source": [ "obj-31", 0 ] } }, { "patchline": { "destination": [ "obj-321", 0 ], "source": [ "obj-319", 0 ] } }, { "patchline": { "destination": [ "obj-28", 0 ], "source": [ "obj-32", 0 ] } }, { "patchline": { "destination": [ "obj-54", 0 ], "source": [ "obj-32", 1 ] } }, { "patchline": { "destination": [ "obj-7", 0 ], "source": [ "obj-321", 0 ] } }, { "patchline": { "destination": [ "obj-374", 2 ], "source": [ "obj-34", 0 ] } }, { "patchline": { "destination": [ "obj-184", 0 ], "source": [ "obj-364", 0 ] } }, { "patchline": { "destination": [ "obj-364", 0 ], "source": [ "obj-366", 0 ] } }, { "patchline": { "destination": [ "obj-374", 0 ], "source": [ "obj-371", 0 ] } }, { "patchline": { "destination": [ "obj-181", 0 ], "source": [ "obj-373", 0 ] } }, { "patchline": { "destination": [ "obj-373", 0 ], "source": [ "obj-374", 0 ] } }, { "patchline": { "destination": [ "obj-42", 0 ], "disabled": 1, "source": [ "obj-41", 0 ] } }, { "patchline": { "destination": [ "obj-9", 0 ], "source": [ "obj-47", 0 ] } }, { "patchline": { "destination": [ "obj-32", 0 ], "source": [ "obj-50", 0 ] } }, { "patchline": { "destination": [ "obj-41", 2 ], "source": [ "obj-58", 0 ] } }, { "patchline": { "destination": [ "obj-36", 0 ], "source": [ "obj-6", 0 ] } }, { "patchline": { "destination": [ "obj-28", 0 ], "source": [ "obj-67", 0 ] } }, { "patchline": { "destination": [ "obj-185", 0 ], "source": [ "obj-7", 0 ] } }, { "patchline": { "destination": [ "obj-28", 0 ], "source": [ "obj-8", 0 ] } }, { "patchline": { "destination": [ "obj-28", 0 ], "source": [ "obj-80", 0 ] } }, { "patchline": { "destination": [ "obj-28", 1 ], "source": [ "obj-83", 0 ] } }, { "patchline": { "destination": [ "obj-364", 0 ], "source": [ "obj-9", 0 ] } } ], "autosave": 0, "accentcolor": [ 0.458595350062755, 0.458595237564901, 0.458595266962388, 0.0 ], "selectioncolor": [ 0.92156862745098, 0.749019607843137, 0.329411764705882, 1.0 ], "patchlinecolor": [ 0.447518749806177, 0.44751863973454, 0.447518668498017, 0.0 ], "oscreceiveudpport": 0 } }