How to create and animate a signal/gain custom meter in GUI?



  • Hey @Christoph-Hart ,

    I was wondering if you could please share some enlightenment on how to create a simple animated vertical meter that displays signal level?

    I have added several samplers (one for each drum set component) and created a mixer with vertical sliders each connected to a different sampler. I would like to add a simple vertical meter display for each mixer channel. Here is the PNG I would like to animate:

    0_1543120440658_level-meter@4x-8.png

    It should be at scale 0.5.

    Thanks so much!



  • @gorangrooves You need to look at a program called knobman. All these kind of meters are just a number of .png images stitched together. Have a look through some of the examples that you can download at https://www.g200kg.com/en/webknobman/gallery.php

    Another way to do it, which would give you more flexibility, is to manually stitch the .png files together in something like photoshop, or print an animation out of After Effects or something. If you look at what Knobman does you'll understand what I mean. Once you've got your images stitched together, just tell Hise how many steps (frames) it has and you're good to go! (You can do it with the paint routine too, so it's not using .png's, you can see how that's done in the demo projects.)

    A .png vu meter is basically a slider. Take a look at the demo projects, the music box and the one titled MultichannelPlugin, and take a look at this post. I was trying to figure out the same thing a couple weeks ago...

    https://forum.hise.audio/topic/1026/can-t-change-slider-style/19



  • I've been using Inkscape to make my film strips. Works pretty well and is free



  • @duno thanks very much. Making a filmstrip is not a problem for me. I've made sliders in illustrator. It is good to know that is what is required as the first step. I will look into your example to see how to animate it.
    Thanks a lot!



  • That seems like such a simple graphics, I'd just do it with a paint routine in HISE, no need for image files.



  • @gorangrooves Yeah, listen to @d-healey, he knows way more than me! Filmstrips are good for detailed stuff. For sharp clean styles the paint routine's better. There's an example below just using the built in sliders, hopefully will show what's going on.

    HiseSnippet 1470.3oc6X0saaaCEVxNZHwsoacnXXWJDrKbA5BrbcbZVwPch+oMqIMFQtoaWLzQKQayUIRMJpzZTTf8n0Gg8nz2fsCIkijcbRs2ZtXsU2wyue7bN7vCUWNyCGGy3Flq0abD1v75VtiohQMGgHTi8aYXVx5jD6CwBL2XuwQn3XrugoYwGJ4at1JFpu28f8PAHpGNijgwILhG9.RHQjQsaiGSBB5f7w8Hg4jtVi88Xzlr.VBfkhVULhPdu.MD+DjTrBVFleQaehfwcEHAN1vbk8X9icGwdIUK+IjXR+.rbgigKXHM4Nr.eIhkTMZNhD32cxdN1vvzpaVDnnNBbKqCI9jynmEI9JEC6LMxGOLKbYvyIO7pr3vyLG7VQCuaZ45wIQhLNRrcMq8oPJZ.BRA4gkVViBmVzpICjfJ1LD8BbGNr3LMJWuRk6XuUkJ299qWZ8RPhHVXeJhaeHJFD4jjCvCD1+n8DKLDKZxBiXTXQ4MxKzFRKjoenhkp3I0DphKkAj6U0JvB651q8wyn6DydLY3n2uyURcwdehQdete8R1vWl6c.cpb+YoVMkZdmIsda5PBEuoGGC0.x5a9Q8+crmnr1zqWRrYLVnXzDEDzGpvKOHg5IHLZ4aKE30yC.yDEUvOgyg8+A3SwAkct8bQ3ra+yoWZ5NyQo3GjqE1izGGD2gwkGz6f7fR6xoRJUKyMKlRUyTRWoHiDmfBRvm2poYyYkPYh2nwLvTf35PY4sTaj2LIRZynOgIvGAgzRutzZkdSoY4LXv7XIKv3rf.vhygq1UWrZkoIg8w76.IA.xSjCN0NcaAqKtsP9tVd5h8bBxn6SIhihvzKpYgQ5IDnsQgTPAhJTMMtQZSC2.hOzHm3KIkOcXnfcV+3e4sFKfM9RqoxXywHOc+VHAR1IKEc.hivbAQFLLagOEthP2WaMqV33WHXQfCO6.tg4pK5F3Um42F+Ziwms3OeTiXwXYDFtHS5XOTfQH5U4unJj36Gf6xhIxbZFm8eaX9K4TwjE.XyFUx7UTbdj8SWQHqjH8dLMx5DvPBBcXOB3KM9xSxIG99sg4wmWizblNAUx5w3w8YHtuQ+gSto95V0pduZaWem6duJFDANbBiqYU6t0qVY65NakidUsF6Tam5aWcmsLD3WIxaJfwVNNfJpplB9lVpNha.d9YDewnM9AamZ2QQpEINJ.M9HOA5T7STG9.tCPAwXs.GvdInFPaG85GQzKcptslPyjXAK7gbTzHhW7zJ2BO.kDH1MJBi3xAa.1BdRJ28BfV2f0NFhhLfSkMqui9SyuGa3v.7gLe7zVUN+.LOAkhCj.QS7ow3SvxVkyGI.6NAHgqrTYFq0s8jLx4X3JaOl4ppmwnM0OGBpC8MggxN2PFvnNL+DvsSO+irsdJCY4X9AMjCSPgxzw4GJ7JYnnEEt2zpKQ3MZ93svbvqrw4ULdSGwbcq1CF.47LvthUme9pedx7PY0KXd+UszyC8gXZ+nEdZeyh+Gmtux++lt+ym69T7b2MzP4ZVtvXypydJf7Mp01OCtLy9gXJlKCpNWxgv+5C+gP8co8f66hiXwSYXWbHoGLeQbdhxql33+PcKXd5MgqjlKq28fNvlbt53hDIbU4xtgrDpXpxihKbNYId5+Jet4fBtEWL39d96DqMAitjvn.baJ7BSXReEF+ZqzwolPc555CYTVzHFk3kOoeLVvICGh44w9b2P6JDv3XYTtUiiwAXT9B3uqwAPgGhKGI6eYrvYwiEWV95aszv0VdXz9iil5E+zro9wrD4inNDAEpvanrfGg3B8R8voCXKetuYAY+P85Jx05loTe0h+F9RY5HWalxzYByOZ7QHxiydtm9WJHOurphBDaopev6Zvalg01NS9GBx3O75Wxy87jIzuGx.yWipKsF2co0n1RqwVKsF0WZM1do03dWhFxK31MAdPr93MPnaa0qvMMaSQvoC0IIi+QGL33L
    


  • Seems like a perfect candidate for a customized ScriptPanel:

    Content.makeFrontInterface(600, 500);
    
    const var Panel1 = Content.getComponent("Panel1");
    
    // Use this variable to update the change rate 
    // (0.7 - 0.99, higher = slower decay)
    const var DECAY_RATE = 0.9;
    
    // use any colours you like, this goes from green to red
    const var colours = 
    [ 0xFFFF0000,
      0xFFFF1100,
      0xFFFF2200,
      0xFFFF3300,
      0xFFFF4400,
      0xFFFF5500,
      0xFFFF6600,
      0xFFFF7700,
      0xFFFF8800,
      0xFFFF9900,
      0xFFFFAA00,
      0xFFFFBB00,
      0xFFFFCC00,
      0xFFFFDD00,
      0xFFFFEE00,
      0xFFFFFF00,
      0xFFEEFF00,
      0xFFDDFF00,
      0xFFCCFF00,
      0xFFBBFF00,
      0xFFAAFF00,
      0xFF99FF00,
      0xFF88FF00,
      0xFF77FF00,
      0xFF66FF00,
      0xFF55FF00,
      0xFF44FF00,
      0xFF33FF00,
      0xFF22FF00,
      0xFF11FF00,
      0xFF00FF00
    ];
    
    // Grab the module you want to meter
    const var MasterChain = Synth.getChildSynth("Master Chain");
    
    
    Panel1.data.currentLevel = 0.0;
    
    Panel1.setPaintRoutine(function(g)
    {
        // Invert the peak (the colour array is actually the other way around)
        // and limit the value for clipping
        var invPeak = Math.range(1.0 - this.data.currentLevel, 0.0, 1.0);
        
        // Fake a logarithmic scale by multipling the value with itself
        invPeak = invPeak * invPeak;
        
        // calculate the index in the colour array
        var index = parseInt(invPeak * (colours.length-1));
        
        g.setColour(colours[index]);
    	
        // fill the circle
        g.fillEllipse([8, 8, this.getWidth()-16, this.getHeight()-16]);
    	
        // give it some funky lighting effect
        g.addDropShadowFromAlpha(colours[index], 8);
    	
    });
    
    Panel1.setTimerCallback(function()
    {
        // grab the value
        var peakl = MasterChain.getCurrentLevel(false);
        var peakr = MasterChain.getCurrentLevel(false);
        
        // don't care which channel, if you do, don't do this.
        var peak = Math.max(peakl, peakr);
        
        // this logic makes sure that sudden peak increases are
        // reflected instantly on the UI, but the decay will get
        // smoothed (which is how analog VU meters work)
        if(peak > this.data.currentLevel)
        {
            this.data.currentLevel = peak;
        }
        else
        {
            this.data.currentLevel *= DECAY_RATE;
        }
        
        // Repaint the panel
        this.repaint();
    });
    
    
    Panel1.startTimer(30);
    

    Example preset (make sure to turn the volume down, it has a sequenced saw generator on 0dB).

    HiseSnippet 2061.3oc2Y08aajaDeW6rGh0U0dGZd3d3dfHnEU9NEcZk+FAtmr0GoF0NV0xI2EDbHfdWJIBuK4VtbsiZwAb+o126K8+f1gj6pcoitT6fjCoUHIP+FNC4vg+lgCUFI3AjzTtvwcsymmPbb+Udimyjy5MCSYNG02w8W6cBNURDHinCmmfSSIgNttq9Dk.20tmi9y+5aODGgYAjRQNNOmSCHGSioxRoi59moQQCwgjyowUzdytGEvY83Q7LveV0qsSBN3R7TxSwJ0Vwyw8SFDRkbwXIVRRcbu2g7v4imwulYz+4zT5EQDEv2YLLQFwC4QgJOV8cmdynQgiJ12oNNtdiJiBqZhBOv6DZHcg7xnwmoG.UZQ03g6JuM2y+cz8bq3d2y3det23.AMQVNhx29TuiXvA0DLbDT0sL55rR5Zd83fFLYqX7kjgB.rvhFa2tcSzVsau9iqWqdM3fHUhtBKPivLRjOZeTgsSIxd73DNC.MdnY3GZr5a9FzyRIH4LZpxVJF1sHIGkkDBQDPNAELCylRPBEVaPi1s1A8HT6V6sWSzL5zY.UaeTZD+Z3Kgj.770q5N8Gz6fW7pyN37AfVfQEqaFrtX1bTfl9jhlyyPQzKIMMdyTNIEMQviQSEDBS4TBRX0Itvv8A25kn1udH7oM7oY8ZnbnuuErSGK3FaXA2bSK3VaYA2daK3N6XA2cWK3d6YAO3.K3gGZA60yB1uuEbv.KnZKt.NXfEreeKXudVvCOzBdvAVv81yBt6tVvc1wBt81Vvs1xBt4lVvM1vB1oiEz22B1ts5u0q8C4jjmHvWnYgw7vLfZpHIWiYREcHl.YBUIDlxd5TefTnqJp49pDTMpwCqVYLOEndMSFQKfwiaEjIDPZxwjqHQZ9Z6GWQkThbDXo7LdljxHMljwBjTNqwz0q82U6ADBb5iXWQDRsamPvWhZnSizrUDVHvyQ.+FGHyvQQy0pwkpjnqgQvBdFKb8EyElEBYEP0XsdWgixHnIbf7GQSRnroFEU6dJ6pQpUaeHN.abgJqsgeq1PppJg5M2dMU6tlHPEUfPMMKV0gP0FDFEwmB0DjyhoAnz.LD+uXNJNKRRShf0thKcMnEhJSIQSLSRo2T7sup3a2bwfINHKpnbCkERdM7unaFzptSUprOJAKRIP8vFkKQi7hBshHroxYOxe8h8Vs0lpN9LWVUn1K0S0OnzYM3OfyLAtnyrzTQPDotxLkrAQP.Okz3k61DsqoDkha8czPfVs9i72tT1eh.0DkZgUm4ozqfcmDkxigivL1kygCVPQUfjLYBIPpWLbXXeAOY7LbH+Znhe7AQIyv2vgAePOy09w0erE6Tc+rnGvqt.tHtjdVkcNsHkRexUFUUT0HM6YQVjN6oBiowDbTJoHhVXj3tXzB2Hjy9CR3rW.jmYzfY56YXJVIchNMOj2LWoPtI1ZurED8X7qan88lFu4MVI80I.UFHwpaQSQoYBEWCCmEYggvcK5oixBDDbJLN3SKLVPlDAGMjPX7TIT4AxX4Fx4yNpI5hLSho9ZOHK.HOv1eg0owbUpcHpgYOBNBzbAjTiA+A87mYpgkhtlKtLOmmNQuaP+welr1b0xOOUeVtdp7CUxlVseznMANHtsl+U6W4laqYYwt6LRhpXnoPmhBVaM8jILxa.bSC+rjgJwBCGswFPUmB9IDQeJWRNUSTUr5Z2bjISV1PpFbD7nHX5Vxnl04m2rFrr3KHhllDgB8fV1r6I7Stc8DFXZ1phhb1QLp7zDRNtrqQ+kz0nSd2Zv2d1Q8giCUij4x.8RfaTnJ2wsO4JnCcSakq40mjdojmn0MuEOvkk5QqWzzoJ36Pgk99dlCBmWW1DeX24K.+zy6dsphV4n86NSWNqpDm2r+VnKa0EzXocq2p2ajO.D5s5wU0GKKkJmW88H2g9wauz9wWZj8V5tet2HpLX1x82UVh+BmPen827W2T2af9FhRm8ddC+920mx7t4JOv3Jep22guhnamR6HOPigVRhQOgvHBUL88waNSt0u47z.I3AmCM7jlvSI9Um4aLVmpi0mHyX1paDYokZ2MD1cUz69cKD1opPH0xZx.r0LcBsRV2+3aGvTO1ZLA1MgmlF.aVcnqRjZTFTuV2ggeUCKE2opX2UemdKqcJZE8+H4c2u+yy+fVV5N7yDrxn232x4y7FSiShHCfWPDA07yqK0mLACccuPZUG9DNimLiynAU4ZmQjB5zoDK9zR2aGHkPqhkRdP2yHQp9fJE865dL7XGr.BYj2VXY0aWX418Klrzituvy3tHUMAzGU2rT231ddGO7Tsu9aTeCsXS7e2EGJH+0LBKnhPTWUAviX2rfjpbadG.4x+xtGSlBqS0I7bBzQ.To1hYLV2RJ7niJkU+o+4ewo6wbdholTX0IoWVpjGWrnNt+duNa1x9yUmB+yjuV8085owNikjDcSLtuzaas9S95+1wyOdSZzKh3mt.2g9hnW3e5IyOd9t5wM1qweOn5tigucgFumYs.klaFuky6OB3J2RB3uUent33Sc79QdWMFOdA25+A732ZeXq9+Q8g4+A3pMnIiOBpKZ98wlBuOWnZ5w6oYwig90BH8LOxGVHO2UTO5wfaqv5pSDVnF7ugO4C5qvt4C5WL3uHqQLNPveUf48hp5D2WKA12L8+CGq4chBi7czugzDahg9ddUPfha7HH5rbK5bmsXi6rEadmsXq6rEaemsXm6rE69VrP0j4AYvMTF9NHXz.yEOtKtLycUm+CklLE9
    


  • @christoph-hart said in How to create and animate a signal/gain custom meter in GUI?:

    Master Chain

    Thank you.

    I am having troubles getting your code to work. What am I looking for to get the following line setup correctly?

    // Grab the module you want to meter
    const var MasterChain = Synth.getChildSynth("Master Chain");

    I have a Sampler titled KICK, which I want to meter. Is this what I need to specify and if so, what would the exact syntax be? If not, where from do I get the correct name for a particular Sampler?

    I am getting an error that getCurrentLevel is Uknown function.

    Thank you.



  • Hey guys,
    after spending several hours banging my head on this, I am no closer to making this work than I was at the beginning. 😞 I read and re-read everything several times.

    I messed around with both the paint technique and filmstrip, unsuccessfully. At this stage I prefer to animate a filmstrip, as it will be a lot more straightforward for me.

    I made a slider and assigned a filmstrip to it. It displays as it should and it works by dragging it with the mouse. It is located on the main canvas.
    Now the challenge for me is to make it "dance" by reacting to incoming level. It doesn't need a separate left/right. Just the overall level. It is not connected to processorid or parameterid.

    Here are the specific labels I used:

    Sampler- KICK
    slider with the meter filmstrip- Knob13

    I'd like to see the "Knob13" display the signal output level of Sampler KICK.

    @Christoph-Hart 🙏🏻 Can you please give me code that I can copy+paste to see this magic happen? 🙏🏻

    Once I have this one channel going, I will be able to easily replicate to the other channels.

    Thanks so much!



  • @gorangrooves You might need to change the response of the slider. In the same properties window as you load in the filmstrip, under component specific properties, try selecting something like min -100, max 0. See if that helps. Might be an idea to export where you're up to as a snippet and post here if you're still having no joy.



  • Make sure you've got it set to vertical in the same section too, not knob.



  • @duno I can not make the filmstrip show up if I set the style as vertical. It only shows up when used within Knob style.
    While I was able to see your example from hisesnippet, I wasn't able to get anything connected properly for my needs.
    My brain hurts at this point ☺



  • Ha, I know how you feel! Gave you some bad info there, sorry. Keep it on knob for filmstrip, but try taking the min / max down to -100 to 0 or something, and play with the middle position too. And make sure all your components and modules that you're wanting to control are declared, and nothings spelt wrong, ie space where there shouldn't be one, or caps etc. If you right click on them you can copy a variable direct from there, and just paste it into your script.

    Doesn't take long to wrap your head around whats going on, just look through as many snippets and demos as you can to see how everything connected.



  • Hey guys,
    So, I managed to get a single meter working successfully. Thank you @A-Former-User and @Christoph-Hart !

    I am struggling with replicating that single meter for other channels (samplers). I get the following error message:

    Interface:! Line 62, column 11: const var declaration must be on global level
    

    The line in question is this:

    const var StereoLevel = Content.getComponent("SnareMeter");
    

    The working slider id is KickMeter and the sampler ID I am metering is KICK.
    I created a new slider with ID SnareMeter and it is supposed to meter sampler id
    SNARE.

    Here is the full script I tweaked and changed labels to make a bit clearer as to what is what.

    // KICK METER
    
    const var StereoLevel = Content.getComponent("KickMeter");
    const var masterMeterLeft = Synth.getChildSynth("KICK");
    const var masterMeterRight = Synth.getChildSynth("KICK");
    
    // Use this variable to update the change rate 
    // (0.7 - 0.99, higher = slower decay)
    const var DECAY_RATE = 0.9;
    
        var PeakL = 0;
        var PeakR = 0;
    
    const var t = Engine.createTimerObject();
    
    
    t.setTimerCallback(function()
    
    {
        var PeakL = masterMeterLeft.getCurrentLevel(1);
        var PeakR = masterMeterRight.getCurrentLevel(0);
    
    PeakL = Engine.getDecibelsForGainFactor(PeakL);
    PeakR = Engine.getDecibelsForGainFactor(PeakR);
    
    // Combine left and right channels to measure the sum
        var peak = Math.max(PeakL, PeakR);
        
      
    StereoLevel.setValue(peak);
    });
    
    t.startTimer(50);
    }
    
    1. What do I need to change in order to get it working for subsequent channels (samplers)?

    2. As you can see, I used const DECAY_RATE, but the following line of code in the script, later on, did not work:

    this.data.currentLevel *= DECAY_RATE;
    

    What needs to be changed here for decay to work properly?

    Thanks a lot!



  • This isn't the full script, you are opening a bracket somewhere before that.

    The error you are seeing is created like this:

    if(something)
    {
        const var s = 2; // const var must be on global level
    }
    
    const var s2 = ok;
    

    The reason for this is that a const variable slot MUST be declared and can't be depending on the value of something.

    Also there are a few irregularities - you're creating a timer object which has no data property.

    I'd recommend you post a full snippet with the thing you want to show - it's impossible to spot the error with a partial code example like this.



  • @Christoph-Hart Thanks, Christoph.
    I tried declaring the value of SnareMeter, but as soon as I try to do it, I get the same error that constant must be declared on a global level.

    I exported my script panel as a HISE snippet:

    HiseSnippet 7616.3oc68zzbabbkCH0HIBSZSY6MUJW6V6DlOL3FQR7E+xpTL.A.onM+J.TNQUVE4g.M.FKfYPMy.JRqnXkrNwaRkrQ6dZyM+CXqsxw8VzwspcOji6Qu9z5ZqTkOtUtj885YFL87AHlg.ThRZjFI.zc+598U+52q6d5dOUkpDMMEUtXSr+wcHbwljuxwx5MKzTTRlayhbwtB+1hZ5D0BJx5PZDUt0NtinlFoFWrXiuAVrXSbANNtO829a+h2dMwVhxUIlIk6+9C+3e+6oHUkrkTaIcyTg+rWt2UpUq0EqQ1WpMwN8r41rphbAkVJcATZb9jbcDqdWwFjcDwhMFOWrKVpljthZEcQchFWrKrlRsiqzT4dxFk+8jzjNnEA+QJtJPEYj75JspgXLlJWglRspsmEoqwwE6U1ylQLtAi3042VplTuzsYHSSyPvFBV9QrwNIzKEK5kL3nWLFz6BFn2U3qTUUpitcNHt8R7aJCxp5hfHfEsLJK2X+0SyWRtAHEmukhXs0AQZdsDyb+8Ju66Tpv92Y8c2pXoxOnrXKx8DOdtxjFcaIpNutd8YtpPYhiTm8ZSEOD00VRMZp6plnoEx5YMfS4pZvjvZYp3nNJQVe91h2krtJ7idbiDoRmL4UEVIYRiRNU7EV36QNPSRmHzRR9tSEGz6zzENTTUXst55JxoEttfU80fnWPocGEY3GIlwL+YLpIIY.dhP8txU0kTjETjMyGAVUoUhpVPdUn1a0kL6Twu+TwEf+XR1JcHxl3RhYZpq2Q6sVXgVRGnJpd77MTTEkanpnbHQadnpns5CbPs8A6lWCSmhCEDa05.niTB2HmAIrvB6s6d2bOgJk1e+M2YiJB6kemRaMm2+fE1lOcPi8DkIsX3Sh0pQSJwLl4ARozKB78EWAaoEVP3G7NU1cGKHusMM.3JnI2gnpKQz.QWarbrUCkkMy8jpo2bl2RXUPXRSnIA0gfTxZkBvEaaX.ARM4Qqudc5ebmYZG4BrTKDbAWXHKECXotjbCMen60AkWLu8kZARQGEDv9kRsHvDR5fI3nLClU3tJcxPPtrSFR5UWxHkNhpP01SCAxxls5gtciT8k5SGXxOMfriXxOsG5OSxmvzel.S+Y.jMyHlAj4oBCnZSQYH0hh5h.0az93nQXMhiIVvH+sjzzmwnoQq4XttF6fI2JReHBOvenIYz4DaAHQZKLwL5jiz60idFrSa1Z3emAy9AVVCsQy1.probmt59hjUf5AFw7oIBJ1sljRESFsubyBc0zUZaUjAgqBgAYOngCTcskKlLUxTFMwfHEiZsnpzgDLec0tDyjHGBN44Hoc6pCh.GIsV250Ipl3ncxUDa2oEoL3vjij2nkxAhsVausgTqK1Rypz5pDw1.aYakZDmYsgpXmlRUKSjqQTgR3BvpfKDqKVE7NyYyC7Zv2tBEbV7BsHhpTsZWYXftaoTUDGu2Ea3ftV3kYpFxdG8prFXF5KhhlDLcqv9hNsz4tvdzc7.RF2fzq+fkqOdcYYewCRcx9qLwBKjuVMgiAMCgpTsSgVJMjpJzjnRle948pki0Ye8gBybFKuOLMHhoMX6fTHsr9oJBbiMTU51gptNio4LrR64zhe91HTZmhU54Ri0es.R3c2rv6Jrco8KUVXsRar4N8wAnJfykDksHG5vY.mD56JU8taSfBRoVFiTzfpn4rEoNZphF2EEZz+e5u.vALo+PVFM0OPPor3apQDzaJogUgjHDBhfthP2N0fdcP5Dps8FDAU72T.Rjb9kElSH47qt5UEZBMDQEZIsVJ2C9RMRUwimkEqJVpP9acmx42uDTJ.HZ6hN4hYtGQ7tagoeMmoU1LM1JBoGSGiqB8z0oQHpt6Ae.opdBKMXp1AMidt1ZoMmXVr.22ai6hiSYWcUwgFoRvDol0GryMy1CTlwSX0HlXNTphjpRGPZosthJFjrggmDzxgfX0.AAfx8jhfh0AXW2VnJinbMAUpFfoEDMTl1lHp0U0Pnp0ssMI0ApInA2VDTUZKdjApbUgdM.VN7+mJNidMxmeOzJPBDbZrGFHCHAzEUMjAIL7r4AL8gX5AAc0Xifvr.U1Ie4R8sOlOEhoZXLbsihNYWPlG+9wmH9Ch6Nm508KKSKcs.L2mbMHo9CVB4tsOfnZYcDJm18jzq1zLcP8aB.zIfmphPmNzd0aA+.sgNwDR0ELKmv0uNMOZ4o4Y5TFxxSLygFSTvLVMy0vR.+6AXQAQMQ3TTUeMy5xnLPuq6dMqp7An36Abwtfy4ufu+yeA6zqT0v1GSAUj2TVReWHz19MqFblFL43hkzj0BEUmN6Fup4raPp8dRj60QQUmSpFN8FV+LEGkTrm4Hy5isRlxrR1RD5VQg+x7zu2C3o3uQ9cJdKghku41UBQEj1pBdM92Y2arivZ6tyMxusPk8u0Vk7VMurY0TokD3WBsdljGGWvLAVJgNIZAoF.bSF7qeXphI4ugnt1vUC6qzN0PWCoG5ZHyPWCYGtZnL78goFdE9BphZMICk33042Er5qV331fiyCUM8xlS56vTGuJ+dDUvUQMv5YnqGioohVOwo8U1tqNI.848A9WxnmxouBhS6mLLvi8RFR3SOjvmYHgO6v.O163zC+TV8MN8UwK2qmwouNllQe9zWKSZ1yJj0.S+pWxPcDcI8zVAT8wgrBROrUPlgsBxNTU.Um7zWAubOkxSec7J1Zkm9J4JrpkArZ75XyKylRO+itH+cASugvwnLVPdIdMznaH.Mqci1DzuCAjKZCoNnXGBHWxAjoCAjK6.xLg.xUb.Y1P.4p1PpBh+f.4DlN7lrmRAeUC01v.cO8gWhWAUXEpdb6v.eZashNft57AxP4E4wPZ7QY9lahypEtpnlAPXOKQPZFyDowZjNAeQh1c0U5.XduojAR1I9tYawFDS9L86o3NxtA+x29X1VutTKy0hdId2KQ46nzTVXME4lhsEjrV3QAbxIZnpzUt17ePmFbz4quWM93+obFyWuca7KxogSTocB2JWGkNc6rqLcBHJzB6QFK13bLTT7.G0DCkUJmMk83ebNmH1u5ezMh8P4bVScLj1E+yvevjsWQML0LYxPK7gVgIFabhLNaS0bixS5THPCW0THP+tCTkiyFU+c+7bChG9vxNP0s2daePUuollMYbhvQ8xCTzw45rCE+NPQEL6VVrlTWMVryHcbhsYSEUP6QuubeUzmf2bMYYn3G+gLBGtL4bsDNLbIW7BcO5SqkyfTdC99sjxbrLq+3e7Op5kY8EewW7uXp92VSGH.iNMwlwSmf6wrn5y2QtAml8ztaiTe1aKo8dXeVHSTyPS7Pxlx6oRzH5t0Tt7.5txx23tAKea6b1cWeSOXJKaXtVJMTnnqS9IWMO5VMM4mWjGggyGcZejwX3cjZR5ZloYiwS9HFL98+jbN4KRn6Eh6IpBz.NzdrXiYz5SXUgdDII8PnGPay4pZ.vbo0v41IW1ilakSR.4jQj6G5gQrVtSRpM4.mCFFolJqT6cxUGrqaH0lf2beevI1RpgbaZUCbdRccN6kpxa+VmSriSRoSGO8QVm1jN6+VzHM8iaYfGFK1lC48KMvoIxlF26m3jFchSOpqO3jAo32TL4Oo6GaigFtHOtQY37iRYIpo0M29SFDE6BaapJylDqX7wefSRbvCW74e9m6mMXHk+Lm8DDZLX9z74OPoKLPQChwfETu.h8uweeyk5rywzICeGEcikhbFykMEmTxsfjj0H0J0VTpkyU+CxE5wo4do7VqqTqZEculjlaSmaVdKWM.3CRstUoreG.bSMhwZ4R6cZsPh3LshKWKqjxoBw+9m3VgX5ixstGQWxb1rtLHqqa2tbVcCr4yuwa7F+YWCKeB5w1iECAqJcDQ0HAaA8CyyHn+xOzkt7G6w0gOS0st.mWcAqQM8pK3CAYUE95YTrEBwnGYXsC85Lz0C2gYziukGipsQFybLN24cvCcOLhbxdGI2AOlUp7ZAa1iYDKaw1+614ZKUqVKxdJfFKncyZaWta6J3PF1Nw7P2VjdXIOVjNHWMUwFEkTIUMpv378FqRRauVcaHI6XnpNVy1+lT+4w0DhqiUALRit+Q0v9fne96ghSLLAnq9gfXxwXgtGna0SdDcMJ6YtdPkdfi3UiTWraKik6hcRJOYQl0.NnHQvTlvJFuR.mBea4nvANkiiNBO.xcNOx8GKlqeLr9pNDLIpC8iKwSWsOeUP5ul7oSlEL4ii0GgQ7z9rR73pGXQ2RhO8.WtGFZ4huJ.8SXcJ35rBzKyeiMm6F422WI5nQ9vr5S1xmo0eZ18wOgVnEStjxmMxmKwu+taKj5rU7j1i34QGeVIdBTeifLzmGYXtp4BOyN7VG8Q7j9rU7jwq0sOJnNQL5Db8iCNZLu4TsvkntfOd43iXHSn7aYjIdx5Q7r2O87i3I.b6QliCtrx5Qr899J1xNj8dlNXq3OyXO+ryJiaCgP3D319KdBnPvqYRWBgKxWdyhkNyrf4dOSXKF9Cex47dIAaRQ6iXn+xyAIfbab603KTNekaTpxcJr6N6meycJU9LSZ46lSwVj8O+KexKxBRemQ0PSm19TelnSQ1D7Et01qkeqJCof5UC5d+wVDciGcZEQo8HhLZBy3kE5U9Qa2ogUZ30QPA2Qf4P138Uk0OYjwDF7J7NXAijAk7YGWYK899+ZmRuStACfZ44jdniLYuCQ4j76UpbgaVoxl6tiuRQVIxTAYuqwLMi6vHIlti6HHutGq1q5wOh452h7zFZJOqvyInx52rxcYdiWcXNcEkV5R3pmyij.80hne9LDb82oBzN0iYZMOvI6Z33EAZjWWRj21iD4Z4F7bW0iM5+biNB3WLaLQF1U6QI6JP80bwt9NdXWuUt.LyP83WAY9VuHkzC3puxrALs4SI0O2ym7cFZBHaJDblzt3LO93mQ3LoOq4LYbwYd+O5oMm45Aiyj4rlyj0Emo4O8oMmI.Fo8YJAFwbldazYF6L+rye5LWavwoORYLN2A217l+mO4bOuYZ9xJcwc6.9hyoJczYHWx0lT2lM869km6YS8IrzQJ+wyFv2lCczu1IGJTA23Gw8DfEGv3M5wBCFSxw6WfMC5u8Qm6sOOfnmOEpRu5Ir8+68dYy55bQFlTta6NvrTdluSwbm7VTv6dwqE9R0NGknlymY8va7t49tmtY2XevM40TNBwp9En9lO18F3qsDS125wsEcrGbaqTybSUSeQkGIBhIMC4ykjH26ytSbBjjHb3d+4ImMxvQvbVvHQcK2FESdD6qUDyxAdWmBhPYX8ENwTP4z1u+ULbZsHN8YBmNsaN8iNJhSelvoy3Qm9GGwoOS3zYcyo+u9IQb5QOm19cDkYgJ+3HN8nlS65kokYQq9jHl8nlY69sNlwb8uLhaOp41de8rs4Ae1uJhee532SFv2i8iXmsAlW20xt2xmeWOyNwJ8dO+nuC7CdQo7+Exx46qyR4FvKok+unYSNvW6dlIw3G5jPCxpoY815Gx2qLeHMOjQ.3yggRyxPoepTXozQLsYofPOuBFwD5hLDZG0yIDJ83UXDSnKwZP7dmeHzziZBcY1NoO37CglYTSnqvPn+8+jyODZ1QMgtJquSebXHz.N5yYDuv5zCYvDp84GBSnl+7vO.i8wNhqyqf88P4KdVP4ghXYcaXuegSh0fbXOGTb4V1s8PPKcVPPgd8zNoSmElUZ7W4G4ZcrsDJ+S24ICivmiAEuuGySvadfXhjJer+jwAJBer2B9hEZewOdbiFpGZewGEiymWTYuuJ6oYS1+yHjD458tWyb.gbQuxoS38t2wo7rAkzXLSJIMKk7m3bSIILoDORPaNiiW19qv657b2wYDh06muS9x+wi8kuXkrwqq+EwWW+G3mBZeI7ocR3oMn7WgyOJ+pwFVJeZdmm85iHBer+0XlGTAuXb5oSuzex2Voqr91cwMQZKIWD8H57U2IpQu5AdKgefwoYbx4MNG7wusr0WSY847o6kTuxkF+31CoFZFCMzqE6rQCcJdlqwfyv9kC5XxhMTrU96X2b4eqbm.sXenJjvyrJXcNVOmTUEYW6Y2SXqErpmgZ9N4BCkvFq0izNETx2vmiGhZRgjJ9NCfJFzIYwR8amLb5ohFPWTWTQHQ5IFz46FiGz+CL372+S7rEU91dPOqdcyg3o1bF6XkS6t79g48PJ4yw48h2ZZdv.D35gty6DL7kBvLCbhqXu7svKgJYMI8iYOU4NStnvBJ5dE98vSrb+w2w7AeAeUNqw2wsrtUBFlqptMxdA90+9Ogui0F257CD26eDn4MXZN2IfobhTi6DoFOXGb59vSLaEysaXru1NcaaXr2zcL7TYO1z3KAqwuSh+F89rBLxcueXlYJ1LS4JyzrYl1UlYXyLiqLyxlYVWYtHalK5JykXybIWYtLalK6JyUXybEWYtJalq5lI3fEkxCOxISxMWJkC1TJ27oTNXTobyoRQ4NXOHZ1t4Uon7mXVY2iaw1y3uZeqS2QKm2LbQx3J+y7M3I3WJiz+32kx3q2mKkwhNtTFiyWutX5phqjAvQBdk84LNsGmy1QU6T+c4X7HzN42OmIoTlzgHpuswJTXgk4JWld2t3FpuZNp4q8UEqdWfavRW6JSfNc5rVZKnpnoUGnJZc43babutpMPVlcJkIfy4ZNSC5.x10CEV2TifczkpZ0K0tzzVI49hzN6eS9zYm24eNbW3+p+swutZA5uM.IU3AIc3AIS3AIa3AYwvCxRgGjkCEHFJZaK1A6z7M3ugnbsiuSQ0ts0tCdvsdGiCt06Pmfg6PWxG22EFWJXlzglf5YESIWSpQul2HE1Ai5ofRoGl6xTeFk5hmqunRex4tz3ACc8gCN1ddtyamluhDJcJIeHXPCRwX39hFuBx8RkEI2VQVoSSEYopNsd.VCZzfnxlnuzSdccQTEiEVHfXMBqizaIIiwH6znHWHXEmrmF9csx5q35qxaftB33BBmq7x8xFnMtLwsTphsNhvekd+TnG4jN8fQWvrtoME6z1DD+p5NGQvbEzcJY9x21pQo0gQb0C11zgo1czIRGIA.L9yZA.b5MFLPm9875+7Dwmede84eLW97a4Tou972ykR+7n7jTMfP0oCUITAueuNmGH6j7TOADPmVeZgpOIjcVSLFpxxbcQxwd7pOFcO4v1kUCbDGQow34Bd7DVuK6if.J5Dna4cLfh5qjsVZxHHfhNmp.JD5W.Ee4aGEPQT.EAHfhu4.BnvX+UEEQQTDECcDEnKompHJd35QQTbZin3uvuHJhBn34z.JdhZ5Jxg6Wrc3t2ogzSLOtQd74NWsil69HWsGIycOc23+Bkm1il4+5BVa8OycOYubP74U3KzT4tvXTz7x3.cLRiar+uKwatQkv6c7aP2LElWM7Lo+8vccQhkRlz3djGLKooSue5gQ+ZPzEttfUgge0amjjXFirmY1qwBhguw8GFi7mAaJOPkdPfkdF2nXMRUwi6KXzbovDegEDDxKKjWUEJujlfXKMEAQAZMIJqeUAvTkLdCtKoKbOvhsvADA7trAFskTS.+eUAEYlVlbnNt21f19Gb6qQq+1hf3PqqJAqilhZBDYktMZJnAJFhMHB5PCdnhTMnsaYtW5Dp0E2XeB5MIBxJ5jckEpB4hWhMwMaf4wyTB0CIIVJ6rWqdWY5qgEfJ6PKdhYieeiMJGVksDrt94E1FzTfFEYHXI2gldhYE91BotlA.z+SpNyMVuIWFggdbbBE+G8iD7jeZlBLKsVLQAazfx3oEAPE5OXf4Z1k19a.hvBz0ERNqclL0O9GfWmu08DOVSnqFgx6pqnJ.FlDjjADPoCJGOVoqPME42TWPl.RPrTRx0HG4nl.3RfBd8MqgvZxxm0QYb03lH.5bROwlfR85fpT61fYPJtfYzPB0nn0tfTMO0Qkik0aNOUnWu9ZGWx.KrvFnSEagePue8.argPu2pNGyiPudD.WC6wmlpObAwZ0dOkVcaSPHrZrqxnEcUg4Rg1mFLSINS6S2PqXuMZiqYy3L6YUEyOgYsZTaHOE4Lr8Jnl47pyy1R62DLo.OxDzBsn5wf4iphHmGYwT6I2E+udJLPbER0kpJAH2wBnVyM1rRI1ZrpH1IGxjBmYwEMoDprDracfTKL9WvEVMvtTOvs56iFjx2qgRvv9Xao70PIOf7aVDMQgnXKzvVBI82Da5ZFJF1XroN8lEm0CGsSWslIXL8XoUOaOl7Ch61FV85tMhcXnrecXPEReOhoZthfTCYEUROwwbX+21FsHKDVckU5.8jaJMG3Hi.Lrg0PD2kP5Hf1ugGnmkG9uQqP4AIvMGs+LAyad2VH4E+9wmvYtXTC9lgIXlJpWUfds7ZUNOdaEOXdaU0XXTlBpHuorj9t.Cv52FC7XkRRtdhQ1jrIJ1ToDiOEyNIeBtzbncv2nKDfKe6KwSsZ35VJ9ObTNO2vwSaBL3uvAJ3w3jwN20PSxE7Obi.B+D7VyNnqJnT.qf3VUPZ20v54NcWzxWp+665S9N.8p4bL6P3cUpXOmXcdfWgo3du5lw8YD1cxYcPqS8bslv9FrZedggNAAKy1S9Gwhfe4uueu872JmlNoiyHn+x2l8UwO2uIm0DEvyKzVy7cjaR7EyGbWjF4tKh48cropuTPTo5GqMUNqq1XCO5MYK3aGfF2X+mw3iWXtzwK70g+qH9O7Kkf+sN9O7Gaf+C+Rd7e3WVCAXtTHPo.fRg.kB.JE.TJDnT.PoPfRA.kBAJE.D.PR.ljwKBOvGkRFec3A91FvC7Qd3A9XMnTXkC0KV0PMCUJVuPUh0JTgXcBUITJD0ArFQb.uATFwZ.gQbFPWDiADFJUFnfYhWDdfOJkI95vC7sMfG3i7vC7wZPoxBELa7hvC7QorwWGdfusA7.ejGdfOVCJ0hPAWLdQ3A9nzhwWGdfusA7.ejGdfOVCJ0RPAWJdQ3A9nzRwWGdfusA7.ejGdfOVCJ0xPAWNdQ3A9nzxwWGdfusA7.ejGdfOVCJ0JPAWIdQ3A9nzJwWGd95qvQ053i8QFWlpAR+w1jByaSPM+TfrBIbeyxGoA8hiFzDg3lO9SqcFYY+JNU.EREJTj8Ly3wZOgPwzAteHyHyLudtZQcDi5HFsl3iv0DunuqIdnXEQqIt8Zhm474ZhOezZhGsl3QqI9yPaBUia9lmaVR7G+Wxc67QuNaQKI9SkkDmdtsEs4Si17oOEcztPji1u.3nczlOMxQ6HGseVyQ6zuXr2SibzNxQ6ybGsSG4ncji1OMcztTji1iRGsyF4ncji1QNZG4n8nvQ6LOe4nMWji1QNZ+zxQ6LQNZG4ncji1O23n8hQNZG4ncji1QNZOJbzN6yUNZe49Mi1SG4ncji1m0NZmMxQ6HGsibz94FGsWJxQ6HGsibzNxQ6gyQ6KxWdyhijyI3r96mctey4lcNxqG4mcje1mo9YSuSdi7yNxO6mh9YuUje1iR+rWIxO6H+ri7yNxO6gyO6I3KbqsWK+VUFEtZKzGWs+nyMtZyE4pcjq1Ckq1u4.b0t5wsOPrkVj21QdaGMq1O23s8pQm7HQWueC6c5c5n62unvId9NbhI42qT4B2rRkM2cmnW6ynHJhhnXvQT72LfHJ5PTq1USidN.GETQTPEQmxJOmDTwxQSgezT3GME9Q9bOHetMMoLIO8JlwlY9Z7EJmuxMJU4NE1cm8yu4NkJ+j0oa2wv5T9jrelINY4SjGEOMP2Sz.7Xuva.dP2xlzNh88jNhK1G74C6hn8ahB4MJj2mSB48aMnEQSUTqYzYczymg6Nd.C280bGtapLQqh1yLA79U7If2TYeAaYzBm5c1yT06WOma0atuQj58YnSyQyZQzrVDsRgCHjo9dKLjKSl+2nPlhBYJJjoPDxTz8vvymgLcgSsOkKFExzy1gLs3KXgLEBVyRQQSdB87WJJZxnnIihlLJZxmgil7IAV5pM9Z91FSOTsgYloYgLsqLyvBYFWYlkExrtxbQVHWzUlKwB4RtxbYVHW1UlqvB4JtxbUVHW0MSvAKJkGdjSljatTJGroTt4SobvnR4lSkxAqJkadUJGLqT83VbsEqppbmpJx5pJTM1KSSAzUkEoSo.+13uERwcnXqtl81ZCgpbmpUQigyA8x7GhzgFhLgFhrgFhECMDKEZHVNzPrxI.AFWX9t5JsMFZDRXuRFlShUpm4jw49+gEQizO
    

    Everything shows as compiled OK, until I try to declare a new element. Please let me know what I need to add/change and where exactly. I look forward to your findings.
    Thank you so much!


Log in to reply
 

8
Online

503
Users

1.8k
Topics

13.7k
Posts