LAF Collection for everyone
-
Draggable AHDSR Component
I've been a bit of a mooch lately so wanted to contribute something myself. I've been revisiting an old script posted here a while ago (can't find the original link) on creating a draggable AHDSR with a panel. I really like this script but always found it was a bit difficult to bring to new projects. I didn't do much other than organize it a bit and make it so you can attach the paint routine and mousecallback to several AHDSRs, and I hardcoded some of the values. Still a work in progress but here's the script:
*Edit original script, courtesy of @ulrik :
https://forum.hise.audio/topic/4541/paint-routines-adsr/65HiseSnippet 4331.3oc6b0DaabbEdos23P4TmDjl3dbhPa.YLkL2kj5mn3JIqerEhksfoyOFBBIK2cH4ZsbWlcWpehiQywdqmysbpG6kVTfdSnWJPQNjhjC8TQQu0dnHW5019lY1el8OpkTxNxokGj3Nyady68l26MeyOb2x1RE63XYKTXh6eXerPgWPr4gltcWoqhtovFqJT3hhJc0brEtwg8UbbvZBEJb9aRprPwKHP+7sKdCECESUbXQBBumktJ9158zcCKcqkdGcCi0Uzv2WuGG00WZCUKyUrLrF.Bx4EqJzWQcWkN36nPH6bhB2RwoqPg2Tb910letYppTSaNUrpZ81Mlcl5JR0q0PAOes1JRp3YaHqBB4yslltqkcSWEWriPgKbCKsCa10ZeSVG7d5N5sLvjGjDZB8Lq30sLzHpHoTgU5panskuExQ.X5Vg1qyyrW+PwM00zCJOzt8RzJPgsf2.V3bQEuyGQ7j3EupbhWJhTANQ5BLQ5kEapZq22MrFh7bIwMLcw1sUfwIdQgQqv4lsj3JV.EltS2SYW751vCAsnzLUqVAUqQ0xKLwDS.CVNtn8TrQ6Z1x4CWybOz0Q9MtC1cYCiUr502xDd1ozj.QDZlDZaXK6qXhMtos0f9NCsw8MMR1Xr4ddMEAMl5v50zMszFXn.VVnoKS7ai1vcMsZEzoauCnLlfKlC3tgQPufMr5im3QEmn30tFZpT+Pq51KuN58V9dar7Mt8ZMQuAh455LzlEJD2V2D+95ZtceOEiAXpJHOc0EPHdhfPJil5eB1mFfnZIHZcHbZMSEvSQCgXDIs.4+w6tikHR24vSUHQIjJvmUWkoxTBqdv5qOizLUWs1Bwo8VV6gsCHkQ6JqrN8SDhUTc02CynTxWLqdv7M7XLJIwb7VJFmiPstYBlSnVpZHqOtw62AbaPT+FcyNCkXcSCvbiZOvD5SKSDD84BNVDF3Tp7DEezDEIBfgkphAxbPu.mw9J1NXHdqjeH0zFXyNtcQWCMG3BSaUaKaTIchzu.RG81gsGd7pWsLiHudnHqK5Pp2yWuHx+CkQOjwnGBLZN3eAL.wwkvOTFMc+ANcCjvs0QuIZNzUQObmx7b+wbeOLfi0VJa7oFH7wDieTizBG+3wMMrZAJ2VjbHve0McQ2yZfKX4GoAGubKaY6MxPZ6pXHkWOBYLSmtoF9.nJNy4Fjh.i2TRfnVL9fBWhMugP+QGZWPsJ5sQkb6pCi6Wmm9s02orOIAzFZ886W8EhTWKarxtAEAFThQsHoK3aEQbCXtM1cfsIj8yWu1GXKQfHYQoolnCCdU1kqxag06z0sTYzTHoPJ1iiBZBK9la0tsC1EnHRJsv5M7SGBjDM0XHM8UzzfPOfhFgE1xx00p2VAUIWMrNGCKRWVZePPkA2TOFTFBm33vAgeUqEmD25g9gLdkPmkfT1jK65BXSlrBZxaAXEH+eUrpxgjuzbfiK3KR958vFXEG7jbrfD0bWaMrMgMvjoxv7oUP0qfZDgHHD.HHLrY6vAQN55yMmoJL96h2RwePq+zpPmaWxOJi8Whqssx9joNoyxgTGXuG1qx9SCRts6cv62bPKJm7rWUfA+oBr9SEyjOEp5zM76FhmI0p+ln81t5NPZAul4U+daKsC5mB+q9NnE4xPn0hLN0M53T7tpLTUIInTBWJGxazacB3TcdNsfuk3iGnnYSlg69VkN.bWj45sqQF0FIYM76yrSYttqB5fJf.6a7.ONV9wsoEGjO022bYPyndnLK8U4L0x6DH5jHIhTmGNGkI0HBprWUmF1QOAmxJ3OSQzgLLwSwKFf4kQN72fNXVvzkSCFmWX8TFbGeKTicNdwuwNCMdgpB4NdJhXMjVsSz3bZZXMEWkoAFfUcIYSfuEYXQAxXPfbPRWeCqAlZNkjhxkNS2B2Q271JGhsK4ZO.6WcmoaCXNAf1k7y2WZxVcXPqlrbHUPFeVgbzo6h6EmRxzTbnX4gfv5JV1nJTYNurWNJ+4..Gk+vn3977uR3bQom7zsqkCF0hfUNj87PmihACkFnsF7f0RGqkNY55vAxtDftnEin1w.WWF8VIplGmdD7YnPOgVGvbO.jGjb1S4MYcVTeXH0RCgZJW2DLrSaqX1AWpE3AGj2a+f1QR4D5WmTDocGOaNjiMcyfMIxSkfsrw80LLz66fKsMQ3HbNjY7eGhnkSCb6iSy8vPoEfGc+tXSDcLiHNzwNXwHt1VFg9LwGbecO3YwcG7.yLnca8CVHhuaZQ.t3CbiGfER95fPTZRFzYx2AbJRQ0MerV1J8H67BX8o3d1NlztSx1PpLXvhjQoDEIy1AfdRvic3vJFQHhaZfPgZfyOyF.8wjHsaLI3tyUPOmISJRrAiqyoNWEM4aATeUlzd0TMqDWikMz6Xh0tOXMKQ4REJfM5Dhv+2GbIpB9ESpBnurwZ2f5tMY7E0LBqfYSqAPZkUfX1V.1xSxRY1TktTFpmYlqlARf4.qxGZkaWJNPaPQXqCg4YV9Ys06f3mcK80xDVeZKmIBAouZFtvQroCc4FUiTbz0nvk0LskoDl7HLoPJKWKPo8WwVXIgsCuGYY.rnk23MPuN6YvStSlYTTMfIxbHqPRpZ0pSWMY3CjleCsCROvrGwe8CfFy5ogQ0CBn5vj8gqlE55IQrrvIa1SuLR5sa+A9ojTZ4TJXCVfdkMcWY5rFdk5oJkSNeAwDy31a6a2JGmlDBA8SnUl19ERkHlg1yMOZUONdAXCHOQn7.dIil.QZZfAwyNPmHOlY3PXoJuMJBkLwLSxKmZ+cbJXTkxmPXvNOrSZn1qGOroTxx61F2mrYRk3xkGQBectPsThsR1OSIk29Hd3rpgt5tPV5O8SQCMdNQKxQrw6X1hlWyIwFCh7fybS.8CYxA19QPBB4mpflnJcVerafQzFEO7l17XSijGG6.MxeGJIfOzCwXbGK6dJF5eBVqTJQ3IhyBGH2y2NEzCYsSmbe0YecW0tIP4MzQFUXNYT02JyvV1XrSW81tqZsuYnegMYFrUHi8oGz7nrCkRePZ6Y1g.WLtcKtMAHCvPE5a9AWiLuX4EFmtSsKAfuVoLZ8iyLuwojFWMeZb0SIMVJecGMUaX28fws6pdrF3iQXGqgGeXZo3lKktadFBfb9rVxivfS18zwnpCQojycr6oUb5r4yvL6ojW6re2GmVKeZbsSIMt1ouqesQx0ud9z25iPhhr6ow20u9HoTMxmR03jGO2XzUpGOFKhmd5vqv1hmfUwORqd2xb4asZy6AXLb73SIU+6.QED0f3cBkYrr73q1e+t5..D1Z9Ia9Df3zgBgyEfKzgsyTDi1zorfdtirMq0yG+7i4r+.nK+VwNR4zVdOIoXj1r8C2gtZFektbDxi13icCBRYWBB1pfneI1pte8HGRZT1j6yTsX.VvQ.QLizfyl65g2vkLIlseMQ2OkrnUwEF2aMvkg3WtRsJ0qznxLUlsxbUlOE1lwpCB1sykcbz63s8QL+UGNBndG6x7N1kc6B1M90SfMyfm9RxGrruHVJTX2d2cpf71HwL2uPNAlG7+tCG7uWbNswAoiJwwKeBYTvmFIGIF3rOQ1nO+jCPrnEZMEHDkV9PYW92usGwIwgQifxQugDd6pXI+jNkRa0jb2HBeCUDCQD1R21ReUJjuzb1g7tXQt8ljmoilcL0jrDy3xFrLvNHcSlM8lrkmNB1zLS48HNO5bluKtIMddN1N2S0i.aWx7+Q1M4GOwDSvMWwcrbw20rT4IftApCEup1sSsNONafsSsZxUxzdXMrj4fdsv1AyG4QnPgKD8tLJl8cYj+pVpxt9BbDZYtgot6c6iMy5BXJ3cmGDDJ7RdREPpK8VOdYua8XSCcMrsftF4tY5c0CYWZChFJIPkdu6d5W7U1FKIjCN8pQ4zsAebinrZoZ0t3Q4gUW1mUj6ORTdbzq7K+M4RbdEedPu6II0qiJ7aWLWL5k8Yj2cWIl44a9ZoiFI13cuWhwl+laywwJuB4FpDSw9xu7aVTXTF5oVnT3D5Wcy+znwoPmH4PN8u+Ovme1GM1NQbrp+F+8+H9ubkQ2IRNhhIH7y+5wzIJFi9ra+GFKmH4XwX+ywyIJtZc3udrchhIQ8u9+XbchhxoO62+u9yKJ7tarJrtExcw1K8DjxpO11UmjMrvp38zUwralcQwUwN65Z0Wnv4BtjyBElfIA+.+6sMYlVp.bEQxbmqv.vis8ugxBGveS6Oj+g8IG3UPAGYuTW5IbETxRCVx+5Z.8qnzLyN6rxRMDBO5XxOAf5xyWe9YlUd9FBb2pBVMyNmz7UqNWUtZXULmzbyVu9byA8Emt8BYoaSH5gKP5DnNBOXo9Jj8jlqGyxnkpdmP8BTbXtYq8C.rIT3EEIHMBKHGVLVOUu97MpMCYtq.Q7Ri1TVb1me7Rg1mk9nk5YoA744Do+dJ5ob.eN.GWbex0sj+GpQOcMMC7VVN5j41C4zuXI1ggCydKh5wTNxfFSJPtD1maCsPxg+bOkZnFbTqnpJSjtruHQoWfo+jvJU8Vjm4+co7fi3sHvmXVju3y+7e2hb5s1MDxv9HHezXo8WJun.xXD9yZ+DdD94DI8uvorxkF7jLzviLdBqgWTjJDm1duIANkgmKLDxDjhhdj9rqSaRXdY429wOgGUKJ5IBi23ZwQDBZFisfyarrRT58FfeMwvMdXKrM41BozAK3qNmW7mj4H2ecwSY0JU3vY4w9wmszpLQG8iRuwQTL6kdJCOZtpUkaTEPAk.dTcYo4qMu7nBOR9TFdTlVsmUwGIeVEeTlV5wGfj7yP.jxk5eo7tD2yZHjNgZWZK99LGDoSnCbx8E3YBLRmvQ1jaiwYPPR4RGKNh6wxY.TRmP8J0M74L.LorUqj+5+eIwfeC77uLBHuxF7pfza7uA.H+J+MAo3PdWsSs2PA4UDeYwsH2ZtzkwykhLJH7DQF8duN7CDWqcarpan.dAw0+fmLuDG369Ky59KI1DFoouYCnc9qQeF89J6gQ2DC9.DimzPdob7U48kxQ+b+R43tptP2eeaESm9VNQXbSbO86CNqN7E9tN30swe78Hil7kuhE45CmRUe6hqCJYpsooh6.apawx8rFX5FwM37C6c8gzX9t93Bm4dWe7LPvdjWGIuHSFunH8vMoh1yKReobD0wcSKSq9csL0U4ko6g8tqJ7ElpzyMID+wDElCm+HeXDye9ebvq82VexY4Qg8wctbLLRbmulOTEtyJye9Vty8ZMUqMYXYFGqszvs1h4ziHXgJzP7yd49isnkydB3KvfHeV098h93lOyZ.urOVzyplvgB+37e+F9A6pA0YSEHiKYMD2YPulvr9pXn2MMwFjK0QgyQl4l8bUxyro8M0nOPNEbuJkHOWvqRI+J4Uwq3CwgflIDhyqRetM.a9rBBGoTg3DozXsPN0VDozUwtCLixZVQQnhXJVGLEbz87K4WnLegaoXFgYvyQ3zl5Gvu1B1OT8lXPy0tqiJXXH1Y9PusFX3v9QvKw2vvhk4K9VJ1ZvXn5Sd.YO2+GP1SL.YxOgAjQuxEI.jQu9DQ.jAk8Qo.H6Hx8hgCPFcCR3AjQuqJw.jQt2IQAjQuCIee.P1Exm6vvCndZAN6opvdx.p8TUTOwf1dJ6Ebx.v8TUX+eYvb4dNI.X.5L8NBdEQ.fhLhNTh9tYr7oAx3mF8QOEUaqOz+2pAXgddZIfdaReE6VTbSxyHoX24R3SO.H0GppFkUIZn731vZiaCqOtMrw31vYF2FN631v4N9FRv4t7.WqdrXC.u+VqQuNpEJ38NohDlH7espGt3J
Content.makeFrontInterface(600, 350); const var knbs_Env = Content.getAllComponents("knb_Env"); const var panelGroups = Content.getAllComponents("pnl_Env"); const var envGroups = Synth.getAllModulators("Ahdsr"); const var knobGroups = []; namespace Envelope { // ---------------------- // LAF VARIABLES & Colours // ---------------------- const var LineWidthValue = 2.0; const var BallSizeValue = 3.0; const var FillEnabled = 1; const var LineEnabled = 1; const var BallsEnabled = 1; const var BallStaticColour = 0xFF6160D3; const var BallHoverColour = 0xFCCFFFFFF; const var activeColour1 = 0x956160D3; const var activeHoverColour1 = 0xFCCFFFFFF; const var inactiveColour1 = 0x106160D3; // ---------------------- // Knob Grouping // ---------------------- inline function sortEnvKnobs() { local numGroups = parseInt(knbs_Env.length / 8); for (i = 0; i < numGroups; i++) { local group = []; for (j = 0; j < 8; j++) { group.push(knbs_Env[i * 8 + j]); } knobGroups.push(group); } } sortEnvKnobs(); // ---------------------- // Global Panel Paint Routine // ---------------------- inline function pnl_EnvPr() { // Determine group index local groupIndex = -1; for (i = 0; i < panelGroups.length; i++) { if (this == panelGroups[i]) { groupIndex = i; break; } } if (groupIndex == -1) return; local w = this.getWidth(); local h = this.getHeight() - 1; local v = this.getValue(); local offset = BallSizeValue; local lineWidth = LineWidthValue; local padding = 5; local bottomPadding = 20; local slot = (w - 2 * padding) / 5; local x; local db; local obj = []; local names = ["Attack", "Hold", "Decay", "Sustain", "Release"]; local knbsOrder = [0, 2, 3, 4, 5]; local knobs = knobGroups[groupIndex]; local p = Content.createPath(); p.clear(); // Draw envelope curve p.startNewSubPath(padding, h - padding - bottomPadding - 0.5); x = slot * v[0] + padding; v[1] > v[4] ? db = (h - 2 * padding - bottomPadding) * (1 - v[1]) + padding : db = (h - 2 * padding - bottomPadding) * (1 - v[4]) + padding; p.quadraticTo(x / 2 + padding / 2, (h - 2 * padding - bottomPadding) * (1 - v[1] * (1 - v[6])) + padding, x, db); obj.push([x, db]); local dbA = db; x += slot * v[2]; p.lineTo(x, db); obj.push([x, db]); x += slot * v[3] * 2; db = (h - 2 * padding - bottomPadding) * (1 - v[4]) + padding; local ddb = db - dbA; p.quadraticTo(x - slot * v[3], (db - ddb * (1 - v[7])), x, db); obj.push([x, db]); x = slot * 4 + padding; p.lineTo(x, db); obj.push([x, db]); x += slot * v[5]; p.quadraticTo(x - slot * v[5], h - padding - bottomPadding, x, h - padding - bottomPadding - 0.5); obj.push([x, h - padding - bottomPadding]); this.data.objects = obj; local area = p.getBounds(1); g.beginLayer(true); g.fillAll(this.get("bgColour")); g.setColour(this.get("itemColour")); if (FillEnabled) g.fillPath(p, area); g.setColour(this.get("itemColour2")); if (LineEnabled) g.drawPath(p, area, lineWidth); // Draw those balls if (BallsEnabled) { for (i = 0; i < 5; i++) { i == this.data.hover ? g.setColour(BallHoverColour) : g.setColour(BallStaticColour); local bx = obj[i][0] - offset; local by = obj[i][1] - offset; bx = Math.range(bx, padding, w - offset * 2 - padding); by = Math.range(by, padding, h - offset * 2 - padding - bottomPadding); g.drawEllipse([bx, by, offset * 2, offset * 2], 2); } } // Draw label when hovering over control if (this.data.hover != -1) { local suffix; g.setColour(this.get("textColour")); g.setFont("GlobalFont", 12); local paramName = names[this.data.hover]; local data = Math.round(knobs[knbsOrder[this.data.hover]].getValue()); this.data.hover == 3 ? suffix = " dB" : suffix = " ms"; local label = paramName + ": " + data + suffix; g.drawAlignedText(label, [0, h - 20, w, 20], "centredBottom"); } } // ---------------------- // Global Panel Mouse Callback Routine // ---------------------- inline function pnl_EnvMc() { // Determine group index based on the current panel (this) local groupIndex = -1; for (i = 0; i < panelGroups.length; i++) { if (this == panelGroups[i]) { groupIndex = i; break; } } local w = this.getWidth(); local h = this.getHeight(); local v = this.getValue(); local sens = 200; local padding = 5; local bottomPadding = 20; if (groupIndex == -1) return; if (event.hover && !event.drag) { local closest = 1000.0; local objIdx; this.data.mouseX = event.x; this.data.mouseY = event.y; local tdo = this.data.objects; for (i = 0; i < 5; i++) { local diffX = Math.abs(parseInt(tdo[i][0]) - parseInt(event.x)); if (diffX < closest) { closest = diffX; objIdx = i; } else if (diffX == closest) { if (Math.abs(tdo[i][1] - parseInt(event.y)) < Math.abs(tdo[objIdx][1] - parseInt(event.y))) objIdx = i; else if (objIdx == 0) objIdx = 1; } } this.data.hover = objIdx; this.repaint(); } else if (!event.hover) { this.data.hover = -1; this.repaint(); } if (event.clicked || event.drag) { if (event.clicked) { local KnbValues = []; // Get the knobs for the current group local knobs = knobGroups[groupIndex]; for (i = 0; i < knobs.length; i++) { KnbValues.push(knobs[i].getValueNormalized()); } this.data.values = KnbValues; } switch (this.data.hover) { case 0: if (event.shiftDown || event.rightClick) { knobGroups[groupIndex][6].setValueNormalized(this.data.values[6] + event.dragX/sens); knobGroups[groupIndex][6].changed(); } else { knobGroups[groupIndex][0].setValueNormalized(this.data.values[0] + event.dragX/sens); knobGroups[groupIndex][1].setValueNormalized(this.data.values[1] - event.dragY/sens); knobGroups[groupIndex][0].changed(); knobGroups[groupIndex][1].changed(); } break; case 1: knobGroups[groupIndex][2].setValueNormalized(this.data.values[2] + event.dragX/sens); knobGroups[groupIndex][2].changed(); break; case 2: if (event.shiftDown) { knobGroups[groupIndex][7].setValueNormalized(this.data.values[7] + event.dragX/sens); knobGroups[groupIndex][7].changed(); } else { knobGroups[groupIndex][3].setValueNormalized(this.data.values[3] + event.dragX/sens); knobGroups[groupIndex][3].changed(); } break; case 3: knobGroups[groupIndex][4].setValueNormalized(this.data.values[4] - event.dragY/sens); knobGroups[groupIndex][4].changed(); break; case 4: knobGroups[groupIndex][5].setValueNormalized(this.data.values[5] + event.dragX/sens); knobGroups[groupIndex][5].changed(); break; } } } // ---------------------- // Global Knob Control Callback // ---------------------- inline function onAHDSRKnbsControl(component, value) { local groupIndex = -1; // Determine which group contains the triggering knob. for (i = 0; i < knobGroups.length; i++) { for (j = 0; j < knobGroups[i].length; j++) { if (knobGroups[i][j] == component) { groupIndex = i; break; } } if (groupIndex != -1) break; } if (groupIndex == -1) return; local knobs = knobGroups[groupIndex]; local envelope = envGroups[groupIndex]; local panel = panelGroups[groupIndex]; local attributes = [2,3,4,5,6,7,8,9]; local panelValues = []; // Assign the controls for (k = 0; k < 8; k++) { envelope.setAttribute(attributes[k], knobs[k].getValue()); panelValues.push(knobs[k].getValueNormalized()); } panel.setValue(panelValues); panel.changed(); } // ---------------------- // Assign the Global Panel Callbacks to Each Panel // ---------------------- for (i = 0; i < panelGroups.length; i++) { panelGroups[i].setPaintRoutine(function(g) { pnl_EnvPr(); }); panelGroups[i].setMouseCallback(function(event) { pnl_EnvMc(); }); } // ---------------------- // Assign the Knob Control Callback to All Knobs in Each Group // ---------------------- for (i = 0; i < knobGroups.length; i++) { for (j = 0; j < knobGroups[i].length; j++) { knobGroups[i][j].setControlCallback(onAHDSRKnbsControl); } } }
-
@HISEnberg Gold!
-
@d-healey @HISEnberg @ulrik Thank you for sharing guys.
These beauties have been added to the collection.
hise_laf_library/Examples.md at main · christoph-hart/hise_laf_library
A public library of HISE UI Customizations (LookAndFeel) with contributions from various developers - hise_laf_library/Examples.md at main · christoph-hart/hise_laf_library
GitHub (github.com)
-
Ok, today is a productive day. Neumorphic Design, scalable :)
Added to the collection.
HiseSnippet 1851.3ocsX01aaaqEVNsZqVqa3Nf8w8AhTbAjacbkjc7Kyn24jl3tfjlFTm0aKBB1nkns4hLogjbR78tAreZ2eR2+AaGRJYQ+RRVCVYAZLOGdHeNO7vC4QmDw8Iww7HiBVmNaBwnviM6MikL5kivTlwA6YT3yLOlLcrwtylfiiIAFEJ7fWIzUn3CMjs++2uKNDy7I4hLLdGm5SNhNlljK8jNGRCC6hCHmRGqM5ZcNvmydIOjOEvwCLcLlf8u.OjbLVLrMLM9Ab7HiBO0rdv.b8fFa63Rp1LngmaisaUqQcGmAAMcazuQ+p3.b8FN.p2Oflvi5kfSHwFEd3t7fY8FwuhoVf2Qio8CIhNtF8fUVItKOLP3hBoFubDML3jLBJ1.lkSxoqGnnquw70z.5b44z1+Pp.kagNAVXiEg2CV.dt5vyQCdqAREzfzCUP5qM64GQmjjqQfmuv7.VBIZ.F1mzghZrFaD9XyWxgQvRpLFeAoaDzYtE1UcbJip43TpskkErYEmfXPTwgr9GsSWzKPYl5GQ.O5HtON7HN+hcXAcIjPavrhV4FTIhLjFCyc2oL+DJmYuYPD9p2xSvQy5ERCHQaVFMHS4vxHd+eoj0+05RbDBCKGzsBFVp1RI9tfHagrQ7KIQne8WkCvOj5eAInD56kcSHWmnhwPemTP+gptoShGLINW6HP5yeN5HbeRnk0vJwjTqr8cA2PJnK3s1atSDEGB3z10C8LjaIoVgerSHcHiDbJrf1YqbYzY3ybNuLBel24nsP1x+9TjSEmlpVqRJkkQdhwsoOvmQjfMK0tHv4BLINGxilLh5i5MBGvuBlmcCgiJEkdvjjQqrSbBNYjf8AcUvAA6GFRmDSrwh8QIso7s3JWQSFsS3jQX6LI8EybY.faO2w1KhOQsxP3wX4bCSbpqAbPtS4VMsIcJ2kT1PW4RzgWcUqwZUtspUuDvP9tk0mTM6NyYAMdosRmKCeuAl7UQjY2Emb0HZBQvIt0DaK2AqjAAWum2xoTNjbcU8Wx87pcKhWxeylBcO0dqpkjCU5kB27MSgyXn8CFRPE+n1tUg4uJBGPgXotPVa6yDKOnEVHUTpXaE.k2xR8N+bY.y.vpr3sbpvsx1KSFYRV1uqdKh+3VBu66RnnwCXLfFOAyfLB5IDVkLEm1gHjwJM.g4Vwozs.0pKAza.O0us.CELSa.Z2Ix2RlOfOX.f02C654GEZ1pMpXQM0eXA0spOWMNx+p.ck087DJmq8T3zyEL3BF8A4331DFkB.GdioijoqbuU0QXFD1pR0OFeM32xeQYhDzhADCWVj7FoS.CC1haOGZ+aZfLWHv9fcdv++zEPb5HIrf41uk9z8LgMUAizE9TI.tDGNkbLOZLNj9eHAsyIcj3xbpu0DWQlVPf8YKvROGAGUVqDEbe1BJuQEvYrsV.WkE9dCQTfjUAJbGfLAWB.xPRxt7orfXa41o3hfT8xD1uHKFQStql7Oz15NB3WMwX90fpLgvgfr4tLpwx6DxGFTbNE9NA6FXc3mbFTm.2RdILviyiGJ0FgPVVZb4g+cPk2y2ojmPwq8ZeQxbx9Pctt4Z3ZUvpjks.Wb4Gyf1Ed+q3EMv9XZFcf6pJ1Rkid4G2rOaHkQpDvmBOV8TdujHJan87iIP5uzqnbpTyYgqHxy444jd81BO3AoZh+B.t2zACnWK5bCWhsHukcKFp3Jj0Zb5k72sTujas9qXYhkXIys1t5GqaYY8aheo9m5kzxbkLde8DhCE3d7DNiH.pTKLCVxeHbfUdhc9qqmegPwrWPi3ri4Ij2vrEOhtn0uYgVV0fAqUm.NQ7vPRzZUKpiK51LzlMcbeBriHCHlOPnVkEK.x7lK.Ru9LeE6nMPN6.FM4MSHrappMiTJUTrTJpfglHKU5qRKURUygAEpH5yMkbrgDvY0nV5a+WcL9wC1CmfylFXFgUYBIJgJbfB6QtDp3UUAVQy8HwWjvm.EuNeWDpvVsneYV8YhGTHWyGYJ+sqw05kPOSuyUhDYyE7+h5LhPGNRq35YcxySHphulWSW3x3VddFZIPTZZzxC9u5MM5yi.+tGbSl9Zoj9V3weSi0kan4KO9NIPMe4zN49xueVG357bceni5DkX66etja14mWwMC5rh2zpVKW2pM8LxJnKUrqSyZddUMDIFDvZuH5kDCcVp3m8jm7j+P8sIVoLZn.ddvzPbxhU0K91GoJfH8EJkVTtLKllLS+ai72Vo9+Ug3WadBMwez5w3FqAiPD8mBLl9AR9Ry8GLf3mjCvGZ188eZ9ZHFukOMAtB50X3lHHhx73oi6A6z9DX0gGwGJxzTXCQjrpuinufA5A28K67GPKUoqnegTktYJMFi8i3+juJSh3Sv7HoD.SL4mqpn4qE8QKkBQzFSCn+ju+hS0JF5ceMr580vZ2WC299ZX86qgMtuF17tMT7A61YZBer5XigwqOYeYJ+BE1mggHPYzpwehrhJNX
-
@orange sexy!
-
@HISEnberg what happened to Decay curve?
-
@DanH Ahh I just forgot to rename it, that's why there are 2 Attack Curves
@orange Sexy indeed!!!!A little less sexy, but in case anyone finds it useful, here is a knob laf and mute and solo buttons:
HiseSnippet 2225.3ocwY0saaibElxIZQkZ61cA5CvTi8BpDEYRJYIqHX3XaYm0XscLhRC1EFFtiHGIMwTjBjT1RcadP165aPut2kmld89FzdNyveFJK4n0XWTJ.KMm4blyuy2Y33KB7sYgg9AZEJ+t4SXZE9CE6M2KZzginbOsS5pUnTwa776eJcf1AymPCCYNZEJ7jWiSWnzS0DO+7dGPcod1rLRZZu2mayNkOlGkQ8hW8cbW2ioNr2wGqvciWchsu2g9t9SAS4IEMzlPsugNjcNEYaihZeKMbjVgmUr8f5s2ooAstyN1La6FC1tUyFTyF02lxZWe.0zl0ZaKavH+hib3Q9A8hnQrPsBO8.em48F4emmTAumGx66xvAlZ8.MKIeruqC5hHUsCGwcctHIFEpAqxEYQrmHiX+4hmwc3ozyhbekXBRlDpAvBaj27dRNyyT07LTLukXRETLomJMoutXO6.9jnrYP642W7DuHVv.JjmTMEIuZa7u9SEOzG3vKp1X5MriCfAoRnaZXTk.+oRmxvyVaw8rcm5vz2rKy1kEPi39dg09P3lBFfrYXD4VZ.4Fu9WiUKgjcIIK+PVz9ttG5OdhuGLNTeyDtDRmIb+HuqOaJDfdPgS3BENurXf6yKKx0BJ1kN35uCp6Uj0NfAopS8sotm56ey9dNGyXt54zIJ1ASih78VKAKmnlZArg7PHTe7TOaLRpuoS.8t25GQCl2yk6vB1rJYPxjCqR76+gJk+wxD3AULEzGPpFEzUmTpy.pzKMtJixbAESEJ2InXoPYjfRcfRJIDB3aY7gihf4ZXjwqKsOyMcFKiXY1ZKRW1.tGSHIA8Et2PBZcD8H+IvZPlvmwbCqjSG6iLrK4xYUIyqRtqphhULPazulQdNX6OiXTaakYP+aNLihAu.KA.GmQiFUaL2SOmFpHYk7BRCEWm5MzkA6RChRD7hSDL1RYQELcjmSNVrpYsHKXjMa8dNQOUvWnLAZHXx7Vp6T149Aiot7+NyQI1F.gvvQTG+6DjFVKjEIQO0Ml0vP9ToS7jC.L2ibc4SBY5WBAuW.AgmSrphgK4uaTE95YHIwWWUISWhcAHB.YX.0gCEzYp70wTNFTf9kB53CZ67H1XoEYB5YVhtptJlH+ChwLCCKwmTIdtpDQASYhAW8PdVplVoG8V9XxHHg6hI8kD+rrNV7jpEr7c8zBfPVyPQUuFfeBmS7ukE3Rm+YCbFyZ1Tp6kGyvHzBy+HhPhp21aml9SFh+xrV6zenFyNwygaSg9UDWXWcZQcHVt1EPtvl+PwsbwLUJ6YdN2a910U1eIVhuGlyF2QK18X6GJ2XfaDxohN4E6GPwlmHVHrg9yIFXNOftTL1bh7.5ImHkJWBkfmDrjkTwPy1tb6aXNj8fzHlBa21vf7x3A3SGQjtef.0xO.TAC9hb2HXaBtzpUoKnBHSURVmdJjdzkwzpBusZbnRLB9qkn.sj7Cnuc2cWRyZ.jB8NIZNIhMKB7AReenQ1XRzHdfCQmOf34GQh8hLXaj6zF.iHaQp2I2bpP5PDbDTxkIh.iOa3Uct21QLxgLj5mxBRAKGCMX0MspHCb667goPa3P.pjPCIdLFbPNA6o1iCObBrO78HtZBTcf+TOG8T31JfMhCBmNX.eVmEE8cXrYw7Ytk8kjDSVE9Xe.rwi4fhqqrTUSCQUIaZC.BALG3jHkJ+Qbu2.H6qywTQ5gnvd9k3nyeuySjbVBPxOhGQK6rHq3zEuyeHTDKY4+GmtPsibyNXJz1OviAD.vwogYPD7v23EaA2JSc6RLyjuOMjktSSv6dKzcwJNqnzuA2B.Z7LHnRPLxxpEcYqHDLkXnuEKSXNukYGI16qmcFkQ.rOxHtdmJ1H3vCXhXYZOShNlLq2kHZ5.mEpR462HPZ6B+5RrMjrMdUhTSH3uJEbyDj0ntgrq.+S.RCqn54BtLqY15rJUDIg2AmsP1Z7WjmG2pCObW.afqz+KCnF5+EzuTKmFhrpfYf8DZzYUcGWtOnRA7AkkLyaTZAtDm.jxTJL70c.rDzEWYYhcsOJKCgSpJ658ioMawSRP4v6P8RY3h.oav6qFm.vgRDzTIVSmKehOeBRrVw1z5mdRO1Hfwi.NqGJaFF6l8g2JFfHLaT4AA2MiUqDPt2H9fHh4jYDHb3kzfREILQsq.FrrDFTAGL88Ak8eVMPnDUKOHZ5KDt1BKZdjfKBIzy8iXuwSW.BCUFjEmZvfkNG9hfA9tvaIuzowqBI3gDT2a539L3rlxNTILBute96Pn3puCA0q3vV9doJL56chGO5MSXdq5hOzheYVMfgXqB9Uj31F9x3aaPF1z3N3UMjjoL0DFs5ECos1K.Zy2aA948V4BHeS43EHomY9E3uM3+r8mz9qmzkFQwKOI1u.ecBKHhigwBcY2xsYxqRoTwtrvaf80BGO9dCzJTdsb8YYV827p4pW20cbmnQpDFI.cTofaIvzwYZYssv6myxrtQyVlsp2TYBKblFVsaz1xb6Fs05OLS.AYCyVMwqOZ8cAYveUtvI+RbgdK3Bl6rSiVsazzp98cAXFqFvrK3Bs1wxpgoUqbtvWtVoeEWnqpK7MK5BcumKb9qxa3ncXBmaeGCMou8EEE2D5Xem3ZEaNbDZswp2N5O7owzYpa.fihMoGbL0XZ+ye5m926IOuIrGtHw4.PdGGW1E9gbDIHSVqOoc+a66qJdluyTWwaCnb4ingEOAtFp23GdqddvZOWcW0uZ2H45ZhecwK3Q1iVtMtwRrQX+5uE1X7839GKdzfAPWzLC7oEO96+s4Ra0ft13o.g2.IPj0Oe53dPMlMCztmGbZCfVgMPrR4XCbLFA5AuEmXv+EdhmzDGWHdRyjI0FSsC7u1VhUh2T7uSPArIOwspWp3Y3XxRfng5O90114Wp6In0iUv5OVAa7XEb6GqfMerB15wJ3NedAw+uB6OENZobail1YWbjngVgBG4QgJPQ0p1+CjbRLI.
const var knb_Gains = Content.getAllComponents("knb_Gain"); const var btn_Mutes = Content.getAllComponents("btn_Mute"); const var btn_Solos = Content.getAllComponents("btn_Solo"); const var laf_Knob = Content.createLocalLookAndFeel(); const var laf_Button = Content.createLocalLookAndFeel(); laf_Knob.registerFunction("drawRotarySlider", function(g, obj) { var a = obj.area; var x = a[0]; var y = a[1]; var w = a[2]; var h = a[3]; var knobHeight = 40; var labelHeight = 20; // Define knob drawing area (top 40 pixels) var knobArea = [x, y, w, knobHeight]; var cx = x + w * 0.5; var cy = y + knobHeight * 0.5; var r = Math.min(w, knobHeight) * 0.5 - 4; var angleStart = Math.PI * 0.75; var angleEnd = Math.PI * 2.25; var angle = angleStart + (angleEnd - angleStart) * obj.valueNormalized; // Drop shadow g.setColour(0x40000000); g.fillEllipse([cx - r + 2, cy - r + 4, r * 2, r * 2]); // Knob face gradient g.setGradientFill([ obj.itemColour1, cx, cy - r, obj.itemColour1 | 0x00202020, cx, cy + r, true ]); g.fillEllipse([cx - r, cy - r, r * 2, r * 2]); // Rim highlight g.setColour(0x22FFFFFF); g.drawEllipse([cx - r, cy - r, r * 2, r * 2], 1.0); // Glossy overlay g.setGradientFill([ 0x66FFFFFF, cx, cy - r, 0x00FFFFFF, cx, cy + r, true ]); g.fillEllipse([cx - r * 0.95, cy - r * 0.95, r * 1.9, r * 1.9]); // Indicator line var startDistance = r * 0.15; var endDistance = r * 0.93; var startX = cx + Math.cos(angle) * startDistance; var startY = cy + Math.sin(angle) * startDistance; var endX = cx + Math.cos(angle) * endDistance; var endY = cy + Math.sin(angle) * endDistance; var indicatorColour = obj.clicked ? 0xFFFF9900 : 0xFFFFFFFF; // bright orange or white g.setColour(indicatorColour); g.drawLine(startX, endX, startY, endY, 2.0); // === 6. Draw label text in bottom third (if not clicked) var textHeight = h / 3; var textArea = [x, y + h - textHeight, w, textHeight]; g.setColour(obj.textColour); //g.setFont(12); // Adjust size as needed var displayValue = Math.round(obj.value) + obj.suffix; var displayText = obj.clicked ? displayValue : obj.text; g.drawAlignedText(displayText, textArea, "centred"); }); for (i in knb_Gains) { i.setLocalLookAndFeel(laf_Knob); } laf_Button.registerFunction("drawToggleButton", function(g, obj) { var a = obj.area; var x = a[0]; var y = a[1]; var w = a[2]; var h = a[3]; var r = 6; // corner radius var isOn = obj.value == 1; var baseColour = isOn ? obj.itemColour2 : obj.itemColour1; // Main fill g.setColour(baseColour); g.fillRoundedRectangle([x, y, w, h], r); // Light direction gradient (for 3D lighting) g.setGradientFill(isOn ? [0x22000000, x, y, 0x00000000, x, y + h, false] : // Inset shadow [0x22FFFFFF, x, y, 0x00000000, x, y + h, false]); // Top light g.fillRoundedRectangle([x, y, w, h], r); // Glossy top reflection if (!isOn) { var glossHeight = h * 0.4; g.setGradientFill([0x22FFFFFF, x, y, 0x00FFFFFF, x, y + glossHeight, false]); g.fillRoundedRectangle([x + 1, y + 1, w - 2, glossHeight], r); } else { // Raised: light on top, shadow on bottom g.setGradientFill([0x22FFFFFF, x, y, 0x22000000, x, y + h, false]); } g.fillRoundedRectangle([x, y, w, h], r); // Draw text g.setColour(obj.textColour); g.setFont("bold", 14); var textArea = [x, y + 1, w, h]; // Shift 1px down g.drawAlignedText(obj.text, textArea, "centred"); }); for (i in btn_Mutes) i.setLocalLookAndFeel(laf_Button); for (i in btn_Solos) i.setLocalLookAndFeel(laf_Button);
-
@HISEnberg Thanks, it's been added.
-
@d-healey said in LAF Collection for everyone:
Anyone know how to draw curved text?
Not very efficient but fun for sure!
https://forum.hise.audio/topic/7986/how-to-detect-if-inside-ellipse/15Basically it computes the angle between two narrow points, approximating the derivative...
-
@ustk wow, I could've used this thread about 3 months ago. ha. Sick.