HISE Logo Forum
    • Categories
    • Register
    • Login

    Best Practice for Creating a Draggable Filter Linked to Scriptnode

    Scheduled Pinned Locked Moved General Questions
    14 Posts 5 Posters 514 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • N
      Noahdeetz @HISEnberg
      last edited by

      @HISEnberg

      Thanks a lot for the advice!

      HISEnbergH 1 Reply Last reply Reply Quote 0
      • HISEnbergH
        HISEnberg @Noahdeetz
        last edited by

        @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"));
        
        LindonL 1 Reply Last reply Reply Quote 2
        • DanHD
          DanH @Noahdeetz
          last edited by

          @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.

          DHPlugins / DC Breaks | Artist / Producer / DJ / Developer
          https://dhplugins.com/ | https://dcbreaks.com/
          London, UK

          orangeO 1 Reply Last reply Reply Quote 0
          • LindonL
            Lindon @HISEnberg
            last edited by

            @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);
            

            HISE Development for hire.
            www.channelrobot.com

            HISEnbergH 1 Reply Last reply Reply Quote 0
            • HISEnbergH
              HISEnberg @Lindon
              last edited by

              @Lindon haha thank you yes that really makes a big difference 😊

              N 1 Reply Last reply Reply Quote 0
              • N
                Noahdeetz @HISEnberg
                last edited by

                @HISEnberg Thanks so much for the snippet!

                1 Reply Last reply Reply Quote 0
                • orangeO
                  orange @DanH
                  last edited by orange

                  @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?

                  develop Branch / XCode 13.1
                  macOS Monterey / M1 Max

                  DanHD 1 Reply Last reply Reply Quote 0
                  • DanHD
                    DanH @orange
                    last edited by

                    @orange In Scriptnode? There is an Intensity node...

                    DHPlugins / DC Breaks | Artist / Producer / DJ / Developer
                    https://dhplugins.com/ | https://dcbreaks.com/
                    London, UK

                    orangeO 1 Reply Last reply Reply Quote 0
                    • orangeO
                      orange @DanH
                      last edited by

                      @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
                      

                      Screen Shot 2024-11-13 at 23.50.17.png

                      develop Branch / XCode 13.1
                      macOS Monterey / M1 Max

                      DanHD 1 Reply Last reply Reply Quote 0
                      • DanHD
                        DanH @orange
                        last edited by

                        @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...

                        DHPlugins / DC Breaks | Artist / Producer / DJ / Developer
                        https://dhplugins.com/ | https://dcbreaks.com/
                        London, UK

                        orangeO 1 Reply Last reply Reply Quote 0
                        • orangeO
                          orange @DanH
                          last edited by

                          @DanH Yes bipolar does it better. But I guess we can't choose between different modulators with Global Mod?

                          develop Branch / XCode 13.1
                          macOS Monterey / M1 Max

                          DanHD 1 Reply Last reply Reply Quote 0
                          • DanHD
                            DanH @orange
                            last edited by

                            @orange you can. Change the index. And I think you must make sure all the Global Modulators are in the same Global Mod container.

                            DHPlugins / DC Breaks | Artist / Producer / DJ / Developer
                            https://dhplugins.com/ | https://dcbreaks.com/
                            London, UK

                            1 Reply Last reply Reply Quote 0
                            • First post
                              Last post

                            17

                            Online

                            1.8k

                            Users

                            12.1k

                            Topics

                            105.5k

                            Posts