Widget Graphics



  • Well I seem to be on a bit of a roll, so I'll keep going.

    I cant see where I can replace the graphics for the widgets(slider button etc.) if its not there yet then we will need it. KSP uses a stacked image paradigm - with an external txt file for the following parameters:

    Has Alpha Channel: yes/no
    Number of Animations: int
    Horizontal Animation: yes/no
    Vertical Resizable: yes/no
    Horiziontal Resizable: yes/no
    Fixed Top: int
    Fixed Bottom: int
    Fixed Left: int
    Fixed Right: int

    However any approach that would allow new widget types would be welcome, there's no x/y control for example, so some drawing paradigm might work…but I understand there is no Graphics Lib implemented in the JUCE implementation...so that might be a massive task.

    Anyway simple bit-blitting an animation works for most situations. Of course if this is already there please just point me at it...



  • You can use a filmstrip image for sliders and buttons without having to define an external txt file.

    Simply select the image in the component property panel (filmstripImage), enter the amount of film strip states (numStrips) as well as the direction (isVertival)

    About adding custom graphic components, as I stated in another thread, I'd rather add more ready to use component types with customizable appearance(a XY pad is not on my priority list, but I'll add one when I find the time) because I think the total amount of useful widgets for virtual instruments is limited.

    In the mean time you can play around with the existing components and combine them. This is an example for a XY pad, which is controlled with two sliders. It has limited real world usage, but you can see what is possible.

    
     <processor type="ScriptProcessor" id="XY Pad Example" bypassed="0" script="// [onInit]
    // ===============
    
    Content.setHeight(240);
    
    bg = Content.addPanel(&quot;bg&quot;, 10, 10);
    // [JSON bg]
    Content.setPropertiesFromJSON(&quot;bg&quot;, {
      &quot;text&quot;: &quot;bg&quot;,
      &quot;visible&quot;: true,
      &quot;x&quot;: 10,
      &quot;y&quot;: 10,
      &quot;width&quot;: 200,
      &quot;height&quot;: 200,
      &quot;itemColour&quot;: 805306368,
      &quot;itemColour2&quot;: 805306368,
      &quot;textColour&quot;: 603979775,
      &quot;zOrder&quot;: &quot;Normal order&quot;,
      &quot;borderSize&quot;: 2,
      &quot;borderRadius&quot;: 6
    });
    // [/JSON bg]
    
    ySlider = Content.addKnob(&quot;ySlider&quot;, 216, 15);
    // [JSON ySlider]
    Content.setPropertiesFromJSON(&quot;ySlider&quot;, {
      &quot;text&quot;: &quot;ySlider&quot;,
      &quot;visible&quot;: 1,
      &quot;enabled&quot;: 1,
      &quot;x&quot;: 216,
      &quot;y&quot;: 10,
      &quot;width&quot;: 15,
      &quot;height&quot;: 200,
      &quot;min&quot;: 0,
      &quot;max&quot;: 1,
      &quot;tooltip&quot;: &quot;&quot;,
      &quot;bgColour&quot;: 0,
      &quot;itemColour&quot;: 973078527,
      &quot;itemColour2&quot;: 16777215,
      &quot;textColour&quot;: 16777215,
      &quot;macroControl&quot;: -1,
      &quot;zOrder&quot;: &quot;Normal order&quot;,
      &quot;mode&quot;: &quot;Linear&quot;,
      &quot;style&quot;: &quot;Vertical&quot;,
      &quot;stepSize&quot;: 0.010000000000000000208,
      &quot;middlePosition&quot;: 0.5,
      &quot;suffix&quot;: &quot;&quot;,
      &quot;filmstripImage&quot;: &quot;Use default skin&quot;,
      &quot;numStrips&quot;: 0,
      &quot;isVertical&quot;: 1
    });
    // [/JSON ySlider]
    xSlider = Content.addKnob(&quot;xSlider&quot;, 13, 218);
    // [JSON xSlider]
    Content.setPropertiesFromJSON(&quot;xSlider&quot;, {
      &quot;text&quot;: &quot;xSlider&quot;,
      &quot;visible&quot;: 1,
      &quot;enabled&quot;: 1,
      &quot;x&quot;: 13,
      &quot;y&quot;: 218,
      &quot;width&quot;: 200,
      &quot;height&quot;: 15,
      &quot;min&quot;: 0,
      &quot;max&quot;: 1,
      &quot;tooltip&quot;: &quot;&quot;,
      &quot;bgColour&quot;: 0,
      &quot;itemColour&quot;: 1073741823,
      &quot;itemColour2&quot;: 16777215,
      &quot;textColour&quot;: 16777215,
      &quot;macroControl&quot;: -1,
      &quot;zOrder&quot;: &quot;Normal order&quot;,
      &quot;mode&quot;: &quot;Linear&quot;,
      &quot;style&quot;: &quot;Horizontal&quot;,
      &quot;stepSize&quot;: 0.010000000000000000208,
      &quot;middlePosition&quot;: 0.5,
      &quot;suffix&quot;: &quot;&quot;,
      &quot;filmstripImage&quot;: &quot;Use default skin&quot;,
      &quot;numStrips&quot;: 0,
      &quot;isVertical&quot;: 1
    });
    // [/JSON xSlider]
    dotPanel = Content.addPanel(&quot;dotPanel&quot;, 15, 264);
    // [JSON dotPanel]
    Content.setPropertiesFromJSON(&quot;dotPanel&quot;, {
      &quot;text&quot;: &quot;dotPanel&quot;,
      &quot;visible&quot;: true,
      &quot;x&quot;: 15,
      &quot;y&quot;: 264,
      &quot;width&quot;: 20,
      &quot;height&quot;: 20,
      &quot;itemColour&quot;: 1996488703,
      &quot;itemColour2&quot;: 4194303999,
      &quot;textColour&quot;: 4294967295,
      &quot;zOrder&quot;: &quot;Normal order&quot;,
      &quot;borderSize&quot;: 2,
      &quot;borderRadius&quot;: 20
    });
    // [/JSON dotPanel]// [/onInit]
    
    // [onNoteOn]
    // =================
    // onNoteOn Callback
    
    function onNoteOn()
    {
    
    }
    // [/onNoteOn]
    
    // [onNoteOff]
    // ==================
    // onNoteOff Callback
    
    function onNoteOff()
    {
    
    }
    // [/onNoteOff]
    
    // [onController]
    // =====================
    // onController Callback
    
    function onController()
    {
    
    }
    // [/onController]
    
    // [onTimer]
    // ================
    // onTimer Callback
    
    function onTimer()
    {
    
    }
    // [/onTimer]
    
    // [onControl]
    // ==================
    // onControl Callback
    
    function onControl(number, value)
    {
    	if(number == xSlider)
    	{
    		dotPanel.set(&quot;x&quot;, value * 180 + 10);
    	}
    	if(number == ySlider)
    	{
    		dotPanel.set(&quot;y&quot;, (1.0-value) * 180 + 10);
    	}
    }
    // [/onControl]
    
    "><editorstates bodyshown="1" visible="1" solo="0" oninitopen="1" onnoteonopen="0" onnoteoffopen="0" oncontrolleropen="0" oncontrolopen="0" ontimeropen="0" contentshown="1">
      <childprocessors><content>
        <bg value="0" visible="1">
        <yslider value="0.63999998569488525391" visible="1" rangemin="0" rangemax="1">
        <xslider value="0.70999997854232788086" visible="1" rangemin="0" rangemax="1">
        <dotpanel value="0" visible="1"></dotpanel> </xslider></yslider></bg></content></childprocessors> </editorstates></processor>
    
    

    As for animations (like fancy peak meters), you can use a slider, set it to read only and use the filmstrip states as animation frames.



  • ..Great!



  • One quick comment. To be honest I think an X/Y control wouldn't be the first thing on the list people would like. I think a range slider would be much more useful. Here you could treat it like a table, a background custom graphic only, and the range-bar and handle colours settable programatically.

    Thinking even more….

    Radio Buttons/Groups and Tabs would be a really really useful addition too.

    .. and being able to set z-order too..which might already be there..because I haven't looked yet.



  • All the things you mentioned are already there:

    1. The range slider is a subtype of the knob widget:

    rangeSlider = Content.addKnob("rangeSlider", 48, 0);
    rangeSlider.set("style", "Range");
    rangeSlider.set("itemColour", 0x22FFFFFF); // so you can see the text...
    
    

    There is no background image yet, but you can always just put a image behind the widget.

    2. It is quite simple to put some buttons in a radio group:

    button1 = Content.addButton("button1", 231, 8);
    button1.set("radioGroup", "1");
    
    button2 = Content.addButton("button2", 350, 8);
    button2.set("radioGroup", "1");
    
    

    Tabs can be achieved by changing the visibility of widgets - Widget.set("visible", false) - in the button callback of the tab buttons (which ideally are in a radio group).

    3. The z-order is defined by the definition order. There is also an additional property which allows bringing widgets to the front ('z-order'), but I realize it's broken somehow. I'll take a look (I honestly didn't use the feature at all because I got quite far by using the definition order as z-order).



  • BTW, I kept on thinking about the user defined widgets and I came up with a pretty neat solution:

    You can enable mouse callbacks for "Panel"-widgets which will cause an onControl callback when the mouse is clicked or dragged.

    I created a XY-Pad and put it in an external script file. This is the new widget in action:

    [attachment=0:1f6cx2y1]XYPad.gif[/attachment:1f6cx2y1]

    Use it like this:

    include("XYPad.js");
    
    var pad = new XYPad("pad", 200, 20);
    
    xValue = Content.addLabel("xValue", 330, 26);
    yValue = Content.addLabel("yValue", 330, 60);
    
    function onControl(number, value)
    {
    	pad.handleCallback(number, value);
    
    	xValue.set("text", "X-Value: " + parseInt(pad.xValue*127)); // Do something with the values
    	yValue.set("text", "Y-Value: " + parseInt(pad.yValue*127));
    
    }
    
    


  • Very nice…



  • Could a similar technique be used to allow the contents of panels to be scrolled if its child components go beyond its borders?



  • There is a viewport component in JUCE that handles scrolling of bigger components so I'd have to add this feature to the panel.



  • How many image states are there for buttons? It seems like the default HISE graphics have on, off, and mouse over but when I use my own graphic it's only reacting to on and off.



  • Yeah, there are only two, but since you can morph a panel into a button with just a few lines of code I'd like to keep the button rather simple.


 

2
Online

353
Users

1.1k
Topics

7.6k
Posts