@d-healey The panel can also save an array.
The linking is a good point.
@d-healey what do you call this on? The Convolution Reverb reference? Is it per audio file?
What are the advantages of using SliderPack vs. using a custom scripted panel (other than the obvious instant functionality)?
What could the panel implementation be missing? E.g. in the knob/slider comparison, the panel currently doesn't support midpoint which makes it problematic for DAW automation (I wrote about this in the other thread).
SliderPack doesn't seem to offer DAW automation funcitonality, though that could be added via the panel.
@virtuscapeaudio You can write it in C++ or perhaps even in Faust/Scriptnode.
The EQ in HISE is near limitless. What you need (essentially) is a filter and a delay for each channel, and a bunch of algorithms that dictate how each of these filters behave.
Keep in mind that you can only ever "ballpark" it, as everyone's head is different. I haven't done any algorithmic binaural panning so I can't tell you for sure about all that goes into one such algorithm, but plenty of papers have been written on HRTF and how it all works.
I'm sure you can find something on github as well.
Ah of course. Ideally I'd like to be maintaining one doc per plugin so I would host it... on github? Written in markdown? Then reference it on the webpage and use the docs system in the plugin to pull in the docs from the target repo?
Can it play MP4 files with sound?
@Christoph-Hart I'm thinking of having built-in full fledged docs instead of just widget info on hover, is WebView something that I can leverage here, to, say point at my own website where I have the docs? This could also let me painlessly update the docs that the user sees in the plugin. Are there limitations in terms of content playback, or is it the same as the system native browser (that would be Edge/Safari)?
Another solution is to put a button at the end of your component tree and put your code in its callback, this will be called after all the other components. Or instead of adding a dummy button, use the actual last component in your tree if suitable.
That's a good one. Kontakt has on persistence_changed which executes after on init, meaning that on init has to pass first, which does not happen if the track is muted in the DAW or the VEPro instance isn't connected. So my instruments there always load up with the "loading" image which says exactly that, and all the UI controls get their visibility set only in persistence_changed.
But if in HISE the controls get executed after the init callback passes, then simply adding a dummy control at the end is not a big deal. Much like the PersistentData thing, or the colorPalette, or my dummy DAW automation controls. or my dummy switcheroo volume sliders. Hey, we need a dummy component list!
If you have controls you do want to save in preset and they call some function that you don't want to be called on load, then the simplest solution is to have a flag that you set at the end of on init.
Alright, tried both with .data and a var, and it doesn't work. Looks like the entirety of the script gets executed, and then the control callbacks get executed in declaration order.
The solution is to add a check in the function (or the callback)
if (flag) callback; else flag++;
then, the flag gets ticked on the first execution. A bit dirty but it is what it is. Even dirtier for non-panel widgets as they don't have .data storage.
Another one would be using the PersistentData panel trick and storing which of the panels should be active, disabling saveInPreset for the buttons, then recalling that saved persistent data on init and calling its function.
Turn off saveInPreset and the callback won't be triggered (and the value won't be saved in the preset).
Ah, this is the information that I was looking for.
Just need an all-clear.
I have a few scriptPanels that act as buttons to switch between different GUI panels/boards. I have a simple function which is called in each of their callbacks resets all of them to 0, and switches the one calling it to 1, then executes that control's things.
Hitting F5 (so load up) executes this in order for all these buttons, as init executes all control callbacks.
Now, I can easily get around this since I'm using the panel and can simply move the function to the panel's mouse click callback.
But what about other controls? How would you handle this using the standard button?
Is there any way to prevent the onControlCallback from being executed on init?
Yes, I use basically the same UI for all my instruments
Yeah this is all part of setting up my design language within the HISE environment. I'm also exploring all the new cool shit I can do here and seeing how much eye candy I can stuff in this baby before it starts to cry.
The idea is that once I set it up, I can forget about it, just change the colors as needed and single-line-add any sort of control I want now or in the future.
@d-healey Right, but is it a single line of code then?
If so, please teach.
Do you mean declare an object for each control, and then pass that object into the function which accesses pulls out its properties into vars and uses that to do the work?
Sounds like an ugly function :p perhaps break it into several smaller functions.
It already has several smaller functions!
I mean here it is, it's all the things a control could care about.
inline function createKnob (curveAmt, curveMin, curveMax, name, fullName, x, y, width, height, paintRoutine, defval, fontSize, parentComponent, isDawAutomatable)
@Christoph-Hart Again, my code works right now, it just requires me to call an additional function in the onControlCallback for each control that I want to be DAW-automatable.
I use a helper function to create controls, it takes a simple bool whether it's supposed to be DAW automatable, if yes, it creates a hidden knob and stores a reference into widget.data.dawAutomation by calling another helper function, which defines the hidden knob using parameters that I used to define the actual visible panelKnob and just assigns it the generic callback. That generic callback finds the parent/panelKnob reference by string operations with a pre-set naming scheme, sets the value of the parent and triggers its callback under the Artificial flag, which just tells the function in the panel callback to not trigger the sending of its value to the child because the callback is being called by the child.
it works pretty well in HISE and in compiled plugin, at least visually. I haven't tested in in use because... I'm still working on the UI.
I do believe the playback/DSP setup will be pretty easy as the internals of this fucking spaceship framework are pretty nuts (most of my feedback/requests over the past month have been UI design-related). I'm just pushing the UI/UX part really hard, but I do believe that part of a plugin/product more often than not makes or breaks its success.
Btw. what's up with the mentioned 5 parameter restriction for inline functions? Mine has like 12 and works without issues.
@Christoph-Hart Yep, that's me right there.
If the Slider object could take parameters like
that would allow us to disable it, that would be quite simple to use (although I don't know how simple is that implementation upstream).
setKeyPressCallback already exists, so we can technically check for any key combination already. I saw that David implemented isCtrlDown a while ago, I guess Shift and Alt can be implemented the same way, and then these modifiers which are used 99.9% of the time can be checked for using a single line of code.
008a031 - Added Content.isCtrlDown (#314)
Fine control can already be changed by changing the mouseSensitivity property. So in this case it would be a single line in the controlcallback:
slider.isShiftDown() ? slider.set("mouseSensitivity", 0.3) : slider.set("mouseSensitivity", 1.0);
The only thing I don't know (because I skipped on the base controls when I realized I cannot implement custom modifiers) is if it can take doubleClick, but I think that's in the broadcaster (correct me if I'm wrong).
@maxtownsley You want to use the panel's timer for this. https://docs.hise.audio/scripting/scripting-api/scriptpanel/index.html#settimercallback
Start it with
panel.startTimer(1000/framerate). Stop it with
In your timer callback, you just want a variable that's increasing every step with a modulo that equals the number of frames in your animation.
i = (i+1) % numFrames;
so that it resets to 0 once it reaches the strip end. If you instead want it to go back down, you'll have to write a flip flop by having a flag that gets ticked on the first and the last frame, and according to the have the value increasing/decreasing.
If you need this to be happening consistently so that whenever you re-open the GUI, the animation is in the correct spot, you'll need to create a timer object because the panel timer doesn't run when the GUI is closed.
const var lottieTimer = Engine.createTimerObject();
Start and stop are the same.
If you want the position of it to be saved and loaded on project load in DAW, set the panel's range to the number of the strips, set its
"saveInPreset" property to true, use its value as the target for counter in the timer, and then its value to set the correct lottie frame.