HISE Logo Forum
    • Categories
    • Register
    • Login

    Discussion about the Interface Designer

    Scheduled Pinned Locked Moved Scripting
    11 Posts 5 Posters 2.7k 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.
    • Christoph HartC
      Christoph Hart
      last edited by

      Hi everybody,

      I'd like to get a little feedback about how (and if) you use the interface designer (which is the list of properties that change the script widgets and generates these JSON code snippets). I've been thinking about a more robust implementation, which might have an impact on existing workflows, but in the other hand vastly improve the general workflow (as far as I can think of).

      The proposed change

      The idea is to remove the code snippets that the interface designer creates:

      // [JSON MyKnob]
      Content.setPropertiesFromJSON("MyKnob", {
        "max": 20000,
        "mode": "Time",
        "stepSize": 1,
        "middlePosition": 1000,
        "suffix": " ms"
      });
      // [/JSON MyKnob]
      
      // [JSON MyOtherKnob]
      Content.setPropertiesFromJSON("MyOtherKnob", {
        "max": 19000,
        "mode": "Time",
        "stepSize": 1,
        "middlePosition": 800,
        "suffix": " ms"
      });
      // [/JSON MyKnob]
      

      and instead create a internal JSON object for all widgets, which will be updated directly from the property list:

      {
          "MyKnob": {
            "max": 20000,
            "mode": "Time",
            "stepSize": 1,
            "middlePosition": 1000,
            "suffix": " ms"
          },
          "MyOtherKnob": {
            "max": 20000,
            "mode": "Time",
            "stepSize": 1,
            "middlePosition": 1000,
            "suffix": " ms"
          }
      }
      

      This JSON object will be persistent across script compilation and when a Script widget is created, it will fetch its properties from this list.

      There are a lot of advantages using this method, which I will sketch below:

      Way more robust

      Currently I am going totally bogus on Regex using this expression:

      "(const)?\\s*(global|var|reg)?\\s*" + id.toString() + "\\s*=\\s*.*;[\\n\\r]";

      in order to find the correct place to insert the JSON, which sometimes fails if the UI widget is defined in an external file. With the new method, it has exactly one place to look (and internally it doesn't have to parse any text but operate on the object directly), so it's faster and safer.

      Cleaner code

      Your script will not be scattered with all these // [JSON myWidget] code snippets. Instead it will be all saved into one big JSON file which will be separately saved in your script folder.

      Support for custom templates

      Let's say you have 20 sliders which all share the same filmstrip image, but differ in their range (which was the case in literally every project I've worked on so far). The current solution is not ideal for this, because you'll end up writing a lot of widget.set("min", 0.2); functions after you've set the common properties using either a common JSON object or a UI Factory method. With the new method, you can simple duplicate the slider, change the range in the properties editor and don't care about how and which properties are updated behind the scenes.

      Backward compatible

      It's crucial for a change like this that it doesn't affect backward compatibility. The methods

      widget.setPropertiesFromObject();`
      widget.set("property", value);
      

      will stay functional, however I advise to not use the first function anymore unless you have a very good reason to do so as in general it will become deprecated with the new approach (but for dynamic stuff it might still be useful).

      However, before I proceed with this step and implement it, I'd like to open a discussion about general use cases and issues that the new method might create. So my (slightly suggestive) questions are:

      1. Are you using it at all, or do you do all your interface design with pure coding.
      2. If not, why? And how do you set your widget's properties then? Do you eg. pass around an object and use the Content.setPropertiesFromObject() method?
      3. If you're using it, do you bother about the auto generated code or do you consider it as noise in your script?
      4. If you're using it, how do you handle the problem that you have a set of widgets which have some shared properties (eg. the filmstrip skin), but differ in other properties?
      5. Are you using the UI Factory method paradigm when applicable (that is the const var myWidget = createMyWidget("myWidget", x, y, additionalParameters);

      Please feel free to only answer the questions you like :)

      BTW: the "Connect to module" wizard will also be removed soon, as there are processorId and parameterId properties, which do the exact same thing but more robust.

      1 Reply Last reply Reply Quote 0
      • d.healeyD
        d.healey
        last edited by

        I don't use it much, except to position object and play around with their size, once I get the values I want I add them into my code and delete any JSON noise ;)

        If it's for modules I plan to reuse in other projects or share with others I mainly use raw HISE script (sometimes incorporating a factory function) to create my GUI. If I'm doing this I use a lot of control.set() commands to set up properties. It's a little verbose but I like to keep things compatible and simple if I intend to share them with others.

        If I'm creating something that's a little more complicate then I will use factory functions that take an x and y parameter and an object with all the other properties I wish to use. I haven't actually used the setPropertiesFromObject() function, but I'll try it out.

        I use code more than the UI designer because I find it quicker and it's what I'm used to.

        Libre Wave - Freedom respecting instruments and effects
        My Patreon - HISE tutorials
        YouTube Channel - Public HISE tutorials

        1 Reply Last reply Reply Quote 0
        • Christoph HartC
          Christoph Hart
          last edited by

          Ah, OK, for smaller script interfaces which are supposed to be reusable (eg. a legato script or whatever), your approach is indeed better. However for big interface scripts, it quickly gets out of hand (I am currently working on an interface with hundreds of controls) which made me think about a clearer way.

          1 Reply Last reply Reply Quote 0
          • alexaudio10A
            alexaudio10
            last edited by

            Hello,

            the idea is good and I feel that it will be easier after meeting. That being said, I am currently working on several projects and it really should that when I open an old project with the new version, I do not go to rewrite the whole code ... but from what I understood it is what is going to be (googles translations are not always the best).

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

              This is the problem for me:
              "a internal JSON object for all widgets"

              -- if this means that this JSON (which defines the UI) is now ONLY accessible via property lists then this is BAD BAD BAD.

              I use a stand-alone code-generator for UI layout etc. that I then import into Kontakt (in the currently working product). I planned to port this across to write the JSON/UI part of products in HISE but if there's nowhere to import this "internal JSON" then this would be a big problem for me...

              HISE Development for hire.
              www.channelrobot.com

              1 Reply Last reply Reply Quote 0
              • d.healeyD
                d.healey
                last edited by

                From what Christoph said I'm guessing the "JSON object" will be accessible as a separate file in the project folder so you should still have access to it for use with your UI generator

                Libre Wave - Freedom respecting instruments and effects
                My Patreon - HISE tutorials
                YouTube Channel - Public HISE tutorials

                1 Reply Last reply Reply Quote 0
                • Christoph HartC
                  Christoph Hart
                  last edited by Christoph Hart

                  Hi Lindon,

                  long time no see :)

                  The internal JSON list will indeed be accessible only via the UI elements. However when you save them / load them it will be stored directly in the XML element (I've played around and this is much more versatile as it allows sharing of modules without having to rely on another JSON file like David suggested).

                  This is an example script with one Knob that has it's max property set to 40:

                  <Processor Type="ScriptProcessor" ID="Interface" Bypassed="0" Script="Content.makeFrontInterface(600, 500);&#10;const var Knob = Content.addKnob(&quot;Knob&quot;, 37, 20);&#10;// [JSON Knob]&#10;Content.setPropertiesFromJSON(&quot;Knob&quot;, {&#13;&#10;  &quot;max&quot;: 40&#13;&#10;});&#10;// [/JSON Knob]function onNoteOn()&#10;{&#10;&#9;&#10;}&#10;function onNoteOff()&#10;{&#10;&#9;&#10;}&#10;function onController()&#10;{&#10;&#9;&#10;}&#10;function onTimer()&#10;{&#10;&#9;&#10;}&#10;function onControl(number, value)&#10;{&#10;&#9;&#10;}&#10;">
                    <EditorStates BodyShown="1" Visible="1" Solo="0" contentShown="1" onInitOpen="1"
                                  Folded="1"/>
                    <ChildProcessors/>
                    <Content>
                      <Control type="ScriptSlider" id="Knob" value="0"/>
                    </Content>
                  </Processor>
                  

                  As you can see, it stored the JSON data in the script with some weird white space replacements that are terrible to the human eyes :)

                  Now it looks like this:

                  <Processor Type="ScriptProcessor" ID="Interface" Bypassed="0" Script="Content.makeFrontInterface(600, 500);&#10;const var Knob = Content.addKnob(&quot;Knob&quot;, 31, 19);&#10;function onNoteOn()&#10;{&#10;&#9;&#10;}&#10;function onNoteOff()&#10;{&#10;&#9;&#10;}&#10;function onController()&#10;{&#10;&#9;&#10;}&#10;function onTimer()&#10;{&#10;&#9;&#10;}&#10;function onControl(number, value)&#10;{&#10;&#9;&#10;}&#10;">
                    <EditorStates BodyShown="1" Visible="1" Solo="0" contentShown="1" onInitOpen="1"
                                  Folded="1"/>
                    <ChildProcessors/>
                    <Content>
                      <Control type="ScriptSlider" id="Knob" value="0"/>
                    </Content>
                    <ContentProperties>
                      <Knob type="ScriptSlider" max="40"/>
                    </ContentProperties>
                  </Processor>
                  

                  Now there's just another child element called ContentProperties which contains all non-default values. No more weird JSON comments / autogenerated boilerplate stuff in the script.

                  Basically, this adds another data layer before the script code. If you don't need it, it won't change anything for you (you can still set the properties using Javascript). The problem was that the UI widgets (the property list, the dragger, etc) had no own data model so they kept interfering with the script which was a theoretically nice idea, but very error prone.

                  I will also add some functions that update / change the "global" UI data object using a JSON from Javascript. I'll also think about some handy migrating tools in case you want to switch your UI to the new scheme. In fact, I think this scheme will be even better for important any kind of autogenerated data.

                  The only breaking change so far is that if your interface was creating only by using the autogenerated JSON data from the property list, it will become some sort of "read-only", which means that it still loads the correct properties, but the property lists (and the UI dragger) will not change the JSON code anymore, because their property changes get overwritten by the already existing JSON data.

                  1 Reply Last reply Reply Quote 1
                  • M
                    musictranscriber
                    last edited by

                    Hi,
                    I've been diving in headfirst and absolutely loving HISE! I was wondering, is there a way, perhaps a setting, to go back to code snippets being added to the script editor when creating components in the interface designer?

                    My brain is so used to seeing the variable declaration for elements in my oninit, and it might help my transition coming from Kontakt. If not, I totally understand, I just figured I would ask since that legacy functionality also appears in some of the tutorials.

                    d.healeyD 1 Reply Last reply Reply Quote 0
                    • d.healeyD
                      d.healey @musictranscriber
                      last edited by

                      @musictranscriber No. :p

                      But you can declare all of your components in code if you want instead of using the interface designer. I do this for all of my scripts except my main interface script.

                      For example to create a knob you write const var aKnob = Content.createKnob("aKnob", 0, 0); I wrote some helper functions for this ages ago, I no longer use them but you might find them useful.

                      If you want to see the underlying JSON code for any of the controls on your interface, select the control in the widget list and press J.

                      Libre Wave - Freedom respecting instruments and effects
                      My Patreon - HISE tutorials
                      YouTube Channel - Public HISE tutorials

                      1 Reply Last reply Reply Quote 0
                      • M
                        musictranscriber
                        last edited by

                        Thank you. Yeah, I learned a lot from your youtube interface designer tutorial.

                        To that end, perhaps you could clarify for me why my interface in the interface designer shows wonderfully, but in the Container>Midi Processor>Script Processor, the interface doesn't show at all?!
                        Screen Shot 2020-04-30 at 12.26.01 PM.png Screen Shot 2020-04-30 at 12.26.10 PM.png

                        d.healeyD 1 Reply Last reply Reply Quote 0
                        • d.healeyD
                          d.healey @musictranscriber
                          last edited by d.healey

                          @musictranscriber Front interface doesn't show in HISE's main view, not sure why exactly but that's how it's been for a long time. You can add a script content view to the left hand panel to view your interface (this is what I do). It has the added bonus that you can scroll up and down the tree and try out different things with your interface in view all the time.

                          Libre Wave - Freedom respecting instruments and effects
                          My Patreon - HISE tutorials
                          YouTube Channel - Public HISE tutorials

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

                          52

                          Online

                          1.7k

                          Users

                          11.7k

                          Topics

                          102.2k

                          Posts