Best Practice for Creating a Draggable Filter Linked to Scriptnode
-
@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.