Best Practice for Creating a Draggable Filter Linked to Scriptnode
-
Hey Everyone,
I was wondering what the current best practice is to create a draggable filter display that connects to filter elements in scriptnode?
I have successfully managed to link the FilterDisplay up with the filters in scriptnode, and I was planning on overriding the look and feel to add draggable components to it. I'd ideally like to use the draggableFilterPanel but it appears that it is only compatible with the parametric eq. What would people suggest to do?
Thanks in advance for any help!
Noah
-
@Noahdeetz I have gotten around this by throwing a panel on top of the filter display, and allowing the panel to access mousecallbacks. It was a while ago but once I find the script I can share it.
-
Thanks a lot for the advice!
-
@Noahdeetz Okay here is my hacky solution to creating a draggable filter
HiseSnippet 2683.3oc2ZzzaabbcojWmH53TaizlzdZfPQAoirLIk+rJFlRhhVBVRlzT0N5TvpcGRNvK2Y8tCkDcgA5Qeq8VO1dqmKP+Aji8PKPAxef9Sn+CTeuY1OlkZEEsbZbb2CFZdy66ul2LzsB31zvPdfQgh6NxmZT3SL6LxSzes9VLOiMaXT3plMBr50yZeWZSlqfFXr5HeqvPpiQgBy9HDsBycAC42+4gqZ4Z4YSSAYX7LNyltEa.SjBsU8GybcaZ4P2kMPC6aUeSat2ZbW9PPkl0rhguk8Kr5Q2wBQaFSiMrB6aT35lcumSUaq6eKGZkaSocqbGq6T8d62sxsueMmkpYW6N2892s18pV0nvEW2gI3AcDVBZHvzU4Ni5zmenmR.OiEx.aCWT0nCHYEXi05ybcZE6eBMLJX1J0aMqxa8YlaybXIvS8ZWQtAIkBcmVgYljJU8sPkJnoRWPoRW0ric.yWjtCpOWxbSOH100BhM5phBWiYtwmZdya9f79HIgehJ9GRxEuhmF8Oakmt4Jqt05cNE5f.dnfbfUPD+qRd.QlCtXOpX8tco1hRyGs07kWtHHH0JRCVnuq0HcNHTaEsCxp03fg6IPlsFefO2CV.7aLDQFqXSWwSogBUJHPdkitWklxuTDVwVvNfpgRylwnTbbFuXHEDGSPGnve9ExHAk8PZY4Qc0riVdtnaO0gjuUjEsTavGYml9sTE0mTXO1iuenlrdr29MCnu7zkRLBo7Ohr1Sjl1wQKxldLAyxEHycHMjzkGP5phf9VAPgMlTULf1iXOTv61EE1PpmsL7UUp13lurokMTzHAtnxTHOkJBXzCn.kAAff0EghYDKOGRaR2.9.hnebNbQzBTH7LjBfmQNQzNVQ.bc+gBZopfEfn9xIhUsxINVo6Hf6VrHyyk4QIcG5AYKbOB2K1OFgRI6X20BJ0tbweaw4hEPnt.hAl3YhoX4huFD8YE1PlEIz0rbc2GZoV5DpCZC4qzseGz31Sol1dRpY6L53o0mo0J6r9VjMVYmFas4NO5TaRQtA9EgcU0phYKjPEoEzIW7T9PA3OJE6OJ0CsXB7gIEGxbD8gbBQeVHZQOGWWBzwXD5SY85KzvXCIfXTj+SuEgRA2UbcKoUzh1ItInsfmvdnKbNAwmGxjAEL4FSkU4uIRylEX6R+ZPbk11B5d5x6UROE+ljZUJC+axlXoU4xjqqLj7D4doBk2UISoPH6aAme.YGPkkL7lnDiZwCUVGqKoTTYyWIqXKSTtN7CQCUzXLtAoxhKgJWI.wnU3xZKq7RulPcComjAUV71juTmMR4.r49Kd+nUJ1n3xX9p8.NDEitdrjQFWFjZwWG07Za9PPxwIjDAmzGZo.9.G7bQlWOYGl97CnAvhbxjjLHIgNIUB5Z4IjEPnBM.QBicRvKdzxZf2KA7H.bw4.kZcuvgATYDQhBgEBQQHMySBSlJQ1mOzywB5OFpXlDZ0mGk0Nlhpm+pg8FwovmD8zj4j3sRKk9Bn9iTsrJ5kF1lpSG0OdEBEXFI3x6QQeukbOhMrY.l+IkUB6GSICn9XUbb81qUZiLSJGssx4Sa0OKmHORB3m.00.XmHM8v9TOhGWjlmLkp739VLoq76tSMg1j7NYWgAVGUpxBQ+MyqjVFyBQnVdbh2axDqxRhnduxwYKQsZ1h2CRPE8GvrICr78wxozytSvDyG8nGtl5D8G.MxfBVof74GJ6iEqdPwtlROlzvibfCmhaZk1EaTZeNrJB6aPrDjALGeNDMxnGQcdTcKJE4BtYlxkxQcszZTkqGp5Bp1M53GYpsS8xXvWxkuBa2o2EE+PbkMBWBaDl18D6nIo55jZZgrSzHUiGHweodqSjGJlbCknGiWoN2bmA.LujflFY4haMIts0PKd7DDOY28R4wL4zAYPQmGSeUVb29cgSpI9AxhsPsdox4G2mh4mx99XdyPQHyAZk.HBywhSeJwMmi.ZDcTwpXG4vRS2v7kWVaLrc3B5S7JIOunHbN13a0sat6EM2jKMH2swKeGLIBK4Mbv9z.8w8PDgKal8FrWb5tAqsxv0Pj6gWN3I9zn0M4tN3MSw+9j220HxyA27clHMDPUHu26mFcu2NtPPIvfALonYbRjgT+w2Y3u8W+KKeSu+Tciof9OxTldkR7+7efeyU232rYCKgEdA7HMBzRensOCcFEZPOfYSUWGeNyFzvWH39FELSB1FE9DQz6GnDZSWtELoYucYfSCE8kMaJVwyxczqfbAiizeOkQoK1qdj3Ux5mXtxPGFWRWHXC62K9kTl6hKszRGijjdr.B8Mu4MiAsFBtQiFRvB5QhTjiU.ooWXKSrIx7IgmMcl+WSlOV1UmeAb2M8bnGAvqIWAAWW9gOmG7hPeKaJ.uqEzMp3qMjSfBdnB+gBFFpQxvU+cCYLOwqcoyvqcMywOKbBttIHyrNoiO93emQZxWruNifx3qiE2XdUfOZ9uGmq+Kt5Oi26FUOC2mtOpnxGc43mABaIIcNWwLaGlymqwB0g3oYgj8eg4ZtL3uVfrgbPpeEItY23lugwwUP1Olm5iNYVYrNYbxBlIWkej9KIlZQ+YQcLSFeErjaPaLf6PGCh9SYdq5vo0IKey2UOTP86vdEU+0NCG1sKCvxzjrwq.5cf6EzJZRBDuBHZ9+w5NztVCcUmQkPe8eeccCbtyrMjl04jm0MqYaCck1fTOxjVR98cO7jZXrkjqFBvMN4CLdEys4N38Cy9dm3KAGsAxa8GYDe5QOPliz47awifVYhOB5zphW0rESX2OecblbzQ7Tl+GniQOc7kMUusYpBdAyle848chmr3KLil7mSI+qY1h6NxuO2iYG8v9nRLmYb6gS+Y9MLRKZT.qiGo1NZw2hGQtsr7Jlhund6gVti4cWk4ycsBdW87mwSjegoL83mk1If7tjGegoKHcFC5L04zXj4CG88maFEzIny9CG89SMa+iKk0TorEMSF1S8q7jL+UFcbU3bJZP1Su915sfq4vnGFMmZD3qTuvreOU5Ynd9zdv8cCjmRtyvAcfi3so364.ikDhCULCdNuZcEbMpDcndNxEvHSGGsYUbcgnMqFuotO4yUVxkLet0AT4ufjzo7Skq6xCFPdD0iFfQ1I0c6eMs+Hl9S8Oh4SrEfJrafkWnOOjVUmycnCX6By.DlA5XTTKWJx.sAULzKKqUfxfE5JZBtBM7935w.qoCDFbLCyf0Y3z1LsIM92ObcO7mHrCErbmmDZCNFzOqWSzZHLrp7YYppSXJ3Z5f2vJvAhg1YNTX1otpROyL6jIZ3myoEW78vuw62Oi27dbBrL+LzyEqicXC7coq6c.0EtarTGuFbYX4blwPyVGtM2iqFHQOpK+M950ilIYJWCZEg.tTRJjOq9SotTqPsZyeY8sXdTqfrim7V4Kd6+I4yMd8ElJ0kfMOHe3N47r+e8jySe0GzO7G2QwO2D5KWiHCkj2OwxeHFH3GBYLvxNf+M1pWPDK5+XIDvt8j++TZNysw0DsmNL1YBWAm8M11YY0IHr14kvkNuDdqyKg297R3cNuDd2yKg26rIDOQekgB9.UsALlSq0UuWWA0DNxxDi+KcEp4GB
This example uses HISE's stock filter, so it will have to be readjusted for controlling a Scriptnode filter. The code should support this ( I have done this in other projects). I have also added modulation to it in the past and it should, in most cases, display correctly.
I wrote this about a year ago so there is definitely some things I would do differently (the Q calculation is just an estimate based on the HISE stock filters, so will have to be readjusted depending on the filter algorithm you use), but this is a start on a potential solution.
I think it would probably be best to script a draggable filter using just the scriptPanel, or possibly incorporating an external C++ module from JUCE. That would certainly improve accuracy as well as allows for different slopes.
Either way I haven't had it crash on me and it performs well enough imo, here is the code:
//===================== Draggable Filters ===================== //===================== VARIABLES ===================== const var Filter1 = Synth.getEffect("Filter1"); //Filter Display const var FtFilterDisplay1 = Content.getComponent("FtFilterDisplay1"); const ftRestColour = 0x80FFFFFF; const ftActiveColour = 0xFFFFFFFF; FtFilterDisplay1.set("itemColour", ftRestColour); // Panel const var PnlDragFilter1 = Content.getComponent("PnlDragFilter1"); const panelColour = 0x30000000; //Knobs const var KnbFreq1 = Content.getComponent("KnbFreq1"); const var KnbQ1 = Content.getComponent("KnbQ1"); // Initial values for filter parameters reg cutoffFrequency1 = 1000; reg qFactor1 = 1.0; // Retrieve current values for cutoff and Q from the Filter var cutoffValue = Filter1.getAttribute(1); var qValue = Filter1.getAttribute(2); //Knob Control inline function onKnbFreq1Control(component, value) { Filter1.setAttribute(Filter1.Frequency, value); }; Content.getComponent("KnbFreq1").setControlCallback(onKnbFreq1Control); inline function onKnbQ1Control(component, value) { Filter1.setAttribute(Filter1.Q, value); }; Content.getComponent("KnbQ1").setControlCallback(onKnbQ1Control); //===================== PANEL HANDLING ===================== // ----- PANEL 1 ----- PnlDragFilter1.setPaintRoutine(function(g) { var width = this.getWidth(); var height = this.getHeight(); g.fillAll(panelColour); // Calculate position for the cutoff var circleX = (Math.log(cutoffValue / 20) / Math.log(1000)) * width; // Calculate Y position of the circle based on Q value var yPos; if (qValue <= 1.0) { yPos = ((qValue - 0.3) / (1.0 - 0.3)) / 2; } else { yPos = 0.5 + ((qValue - 1.0) / (9.9 - 1.0)) / 2; } var circleY = height * (1.0 - yPos); }); // Mouse Callback to handle dragging and hovering PnlDragFilter1.setMouseCallback(function(event) { var mouseX = event.x; var mouseY = event.y; // Ensure the mouse is within the panel boundaries var panel1Width = PnlDragFilter1.getWidth(); var panel1Height = PnlDragFilter1.getHeight(); if (event.hover == 1) { FtFilterDisplay1.set("itemColour", ftActiveColour); // Change to active color on hover PnlDragFilter1.repaint(); } else if (event.hover == 0) { FtFilterDisplay1.set("itemColour", ftRestColour); // Revert to rest color when not hovering PnlDragFilter1.repaint(); } if (event.drag) { FtFilterDisplay1.set("itemColour", ftActiveColour); mouseX = Math.max(0, Math.min(panel1Width, mouseX)); mouseY = Math.max(0, Math.min(panel1Height, mouseY)); // Logarithmic mapping for cutoff var newCutoff = 20 * Math.pow(1000, mouseX / panel1Width); // Compute Q value based on y position with 1.0 at midpoint var yPos = 1.0 - (mouseY / panel1Height); yPos = Math.max(0, Math.min(1, yPos)); var newQ; if (yPos < 0.5) { newQ = 0.3 + (1.0 - 0.3) * (yPos * 2); } else { newQ = 1.0 + (9.9 - 1.0) * ((yPos - 0.5) * 2); } Filter1.setAttribute(1, newCutoff); Filter1.setAttribute(2, newQ); KnbFreq1.setValue(newCutoff); KnbQ1.setValue(newQ); PnlDragFilter1.repaint(); } }); // This prevents the panel from being dragged outside its parent panel PnlDragFilter1.setDraggingBounds(Content.getComponent("PnlDragFilter1"));
-
@Noahdeetz there's a thread on here which uses broadcasters and the draggable filter display. Via this and global cables you can recreate the eq inside scriptnode. I did this for LFO-EQ. With LAF I just had the nodes visible from the filter panel, and used a filter display behind to show the eq curves. Only issue is creating more nodes as I had a pre-assigned amount (5). It can be done, however.
-
@HISEnberg said in Best Practice for Creating a Draggable Filter Linked to Scriptnode:
HiseSnippet
You might want to add this on the front of it...
Content.makeFrontInterface(600, 600);
-
@Lindon haha thank you yes that really makes a big difference
-
@HISEnberg Thanks so much for the snippet!
-
@DanH said in Best Practice for Creating a Draggable Filter Linked to Scriptnode:
@Noahdeetz there's a thread on here which uses broadcasters and the draggable filter display. Via this and global cables you can recreate the eq inside scriptnode. I did this for LFO-EQ. With LAF I just had the nodes visible from the filter panel, and used a filter display behind to show the eq curves. Only issue is creating more nodes as I had a pre-assigned amount (5). It can be done, however.
I am new to the Global modulators.
I am looking at this to start: https://forum.hise.audio/topic/7117/modulator-level-broadcaster/12
How can we control the intensity for each parameter for FX plugins?
-
@orange In Scriptnode? There is an Intensity node...
-
@DanH Similar to this?
HiseSnippet 2203.3oc6ZEzaabbEdVRMTRzotw0pIAEs.KT5AkTCAxUxRVnnPThRzlnhRzlLJAnFvcztCIWnc2Y6tKkMSPO0BzzS9ru0CoW6gBDfdq9GPJP.LJPOl9Ov8WP5a1YWtyRRISQIw5zDJ.ANu48l4Mu226MuYFV2ioS88YdHk7M64RQJuAtQOmfNk6PLcPU2AobcbMhe.0SUPZ6dtDeepARQI6c4DTleFT3mWt41DKhiNMgDBcHyTmtmosYPB05k9klVVUHFzll1RbuZop5LmxLKVWPexhKfbI5GSZS2mvYKCFcOheGjx6i0VeihqcjVAsMNZc5pTsVEoqbTq0MJVXkBqRztyJq0hrVQxFHkb6ZXFv7ZDPBn9HkY1lYzqQG1icDSvgl9lGYQ4MJhZ.yrfbElkAeIx+NpbGSKi5wFJeDLn0SLaYElsEv0LML6SOw78lgcnlHgrATISZ0KaJ0q3oodiPkTjToYDpzMvMz8LcCR5gqOWCW0A7lsHfeRVUD7hx7mUvkY.GNAKaSNlVwCZzWhkVqPgaoB+68944yC9J+.0SHdpssU+Ep65z1zgtbaZvcsXGQrd.qafoS6ZDGvC5sDHQh.5EAAZayYtLAVfKsnPF08pbfZwESyq1Yvq1hgZRwkA9cn5AMYhNqwL5ZQ.K6RKBrUbwaoF30kxGWsylUsDVgOs55nGXxbTYN6yBnG3rz6k+SxOe9ead0A6pUqQ1G2V5wrr3VfQzMO.v6rDbImt1GQ8tEXJr.sJlQvImF4ja7PN5BWqDiLmpNlAG3RiZm.8KNBbFJBa.e6CptCIfvgdQz.9bodAlb0QYG5IPfu.HNOdGp+wALWHzeHTJDeD6.jCZ3oVh5.rGoPpbzniuYPO4TOCFIMyoaOJLx.8QtZGS08F35lA5cFs9lYD5KX0tp02n7ReO7tsZAn8DkcFbkOZRSBU3bmDJeTRHXN4S9aD0TsxGUbToeT9TbRPfqG0k3QaxpaQ5sjOw10h9.PGuk5QVL8iaX9wzgibbEpv1bNVRuCAh0s7mj.rbWRolQ8SDF3Y9DjBd+t1Mfc3zokizNflRFdrkncAdaNFoA0wHrwWCeh5rHusRTmEi6TJrbeZviYdGG5Nh9NRYVwF4636FQRaEzVVVrGWlY6ZFgYAuPHs5LqdtcXNl5bRBNh00srYcgoIRggsiaRLs3f7Fc8gTHFG3z.XNrF.krGR87CG3YwEVF9C.86yLftlsBQGLs8pSB5vid3Yk.3I0aYcoxNRosxXEQ4.Cv.ejiKcPX9.M2laS3ENvcb0IdffvNY77SYTxJkuR.c4sffzLBfZU+C48pSrPGxgFbgBmEN6yHVH4DZZ6vMRdjNe6ITp01ag8Dd+kSwynVMoXPd0LetG9Wu2WO3J5Up+kEaywc.Q5+0wx6bhPI4qZR7fsW8iRlGKlvcU0fWzfY+jX8Mi7NlEKFajjwkqLws.NpY5DM+IY+pQdx.zd4lMBnt7PZY9ZbL8wB6oLm70W7DOzvrCsEoqUvPzQRdL4kSJ20MCghPVgkSXXXekr3mMrKsS5bXvuN10l7ntN9.7Cl5T1773ZvBzz0p2.l8LRl84lplcDZzlcDZqtALaHCZ3NgnqdETTdqv2L1XizJYpP6TtgABsiwJo3YTg1oX3JBwLG1hXX.V1TXkqgq3Q+McgLxCBVxd19hUKMju3SeQoWkuXAHQul1FaTX0aull1Jqdm0uysQiD27IK7Wt6me+OqzqK3FofpID1b147d4e+hqiX7VFFienmLPtO5HED9MwsLs33gki5cXvaeAOWvVdQCVzmDe.gJhYI4q7MobLnOIt9kcgRvfYwHTf3ZZRAWycU.WCoV52Y+OhRcjDqjdnJ8zQiSA5iMFnzJq7hMGPIe9W7Eu63ojn28+7kgJYV78STtO+E+yG9u9CuUoScOuyFSp87gwjZkNeXxbgmT6b.JuxJM3WeycdQjergMiEzAp5JkdU5e+w+9QEKGRGc0WxRN9QGoScSEP6TUo4w65vq2z3bTG0oVxwrRkVoy2+8x2LN1Zo7ljSPYsxUQfFbIlKLOA5xKIDjraSdRn9h9YO8Guw0+iOqzEa0cV0P1ut8sYrisIgmW7BeiNyI57GgG3h0JGe7tvRA9IwmBoe+p8Yn3Yb8xe43d8xti80Kqj8x55Wm4p5Fgmp2i0MGx03eodyamiqXOijJeCgJiwv4VQhHP9k59pUssMcYVDOd+Ias2u+uZSNFoZLD6O8rm88K8gjSnsXd1Qv79izdz1f4PF40jZ6xZzyQOUbc7FOoQdKTZOFyMNUqzvVuCwme0w9zfTCCLrMYhmcoL+hrj6rZaGlGUbczxzK20GJEIdAHt0CH0injpeEdsUWF9z5mw++Fkg+sxAWNsQWdOhQlwFmxuAi9tbNb807aHVnw8AgulnwiNvR6BEXo9vm9NkREX8U2+uk66Br9t.quEEXMwOVT1uo8XQWNpxz3IRjVtusX4dMLOnN7m6P3h8GhiCxUuKEpFk62lxUjdfd.nBM8HN9tLeZQoQ94Mn1lMYNTeYpCJgl7UN0WBszm2LnqSpgNhTJt3lhJfoPhu4JESTSlXchSpACZmZjpwcoIEcIxV2fBqbiC70ACCYfS4UuqkO8CMMB5TTVvDxZxjuGwyXvsKFrv9wrlzzO5rD+SyeCHS0jQW7GZ+x40hmOVGaXxu4vccNgZAm8LTG+A3nyAGSMcLYMlCK94JSP.OfBoRZ2ll9JOF0BZqf.hbg.KT5ATKJT9PBoeZo8fSmR7Bu+lIyVb9+46LR+06fEpqJOQh5+e7Cj3ao64M1QnP9yu43oeaLjSWSMzcq9+d+8znvhowbXSz8XOJ5AG4ILlKjBrtcBell4w03sUKhNYvab0F154Q55oGpgDTaREbkIUvUmTAu8jJ3ZSpfqOoBdmWsf7JChdDIdbBTtT8cEGsTo+4ZUxh9u.VNSXcA
-
@orange Yes looks good to me.
Also try the Bi-Polar node instead of Intensity for bi-polar behaviour.
FYI there is a Global Mod node in scriptnode itself - no need for the Global Cable. However you can't compile the network with a Global Mod inside it...
-
@DanH Yes bipolar does it better. But I guess we can't choose between different modulators with Global Mod?
-
@orange you can. Change the index. And I think you must make sure all the Global Modulators are in the same Global Mod container.