Adressing Quick Controls

Wrote this code below. I have a quick control tied to several parameters in a layer. I’ve named the layer “Engine”. I wanted to create a parameter to control the quick control. The code for some reason seems to work in reverse. Instead of my newly created parameter controlling the quick control, the quick control, controls the parameter (moving SControl1 does nothing to the quick control but moving the quick control moves SControl1). This sort of behavior seems to be specific to the quick control. Any one know the reason for this? Another question I have is also the proper way to address quick controls. Quick controls should fall under the layer class, right? So “Layer=this.parent:getLayer(“Engine”)” should be able to address my Engine layer quick controls, no?

--Rename Engine layer "QUICK CONTROL 1" to "SControl1" and convert increments
Layer=this.parent:getParameter("QuickControl.QC3")

function onSControl1Change()
  Layer:setParameter(131073, SControl1)
end

defineParameter("SControl1", "SControl1", 0, 0, 100, 1, onSControl1Change)

Quick controls should fall under the layer class, right? So “Layer=this.parent:getLayer(“Engine”)” should be able to address my Engine layer quick controls, no?

Yes. You can address them as any other layer parameter.

Change the second line of your code to:

Layer=this.parent:getLayer("Engine")

This is what confused me. I did exactly that and it still didn’t work. Is this a bug maybe?

Can you post a screenshot of Program Tree?

So I updated the line like you said just to verify again. It still gives me an error when I adjust the parameter, but when I adjust the actual quick control the created parameter moves. It’s really weird that it works in reverse. Here’s a screenshot. You can see the error I get in the screen shot. I got the error adjusting SControl1 but when I turned the quick control completely up it moved SControl1 to 100. Why is it working one way? Below is the code I use with the new updated line. Here’s the picture you requested here

--Rename Engine layer "QUICK CONTROL 1" to "SControl1" and convert increments
Layer=this.parent:getLayer("Engine")

function onSControl1Change()
  Layer:setParameter(131073, SControl1)
end

defineParameter("SControl1", "SControl1", 0, 0, 100, 1, onSControl1Change)

Thanks for the screenshot.

In this case the Engine layer is the parent of the script module so you can address its layer object simply by “this.parent”.

It should work if you change the second line to:

Layer=this.parent

or you could delete the second line and change the function to:

--Rename Engine layer "QUICK CONTROL 1" to "SControl1" and convert increments

function onSControl1Change()
  this.parent:setParameter(131073, SControl1)
end

defineParameter("SControl1", "SControl1", 0, 0, 100, 1, onSControl1Change)

Ooooohhhhhh! I see now. Thank you so much. My understanding of lua coding is getting stronger and stronger everyday because of help like this. Much appreciated. I just have one question to make sure I understand how to address the proper objects. If I want to target the top layer (SIMPLE) quick control instead of the Engine layer I can’t use this.parent because it will default to the immediate layer or program that the script itself resides in? I would have to use…

Layer = this.program:getLayer("SIMPLE")

right?

Also if you don’t mind can you help me address effects? I tried to use the manual but failed. I’m trying to tie two effect parameters (from different effects) to the same parameter. I feel like I have the right idea but the issue has to do with the position of the parameter definition or function line.

bus = this.parent:getBus("Internal FX")
if bus then
    --locate the distortion effect of the bus
    effect1 = bus:getEffect("Overdrive")
    effect2 = bus:getEffect("Distortion")
    if effect then
        function onDistortionMixChange()
            effect2:setParameter(13, DistortionMix)
            effect1:setParameter(0, DistortionMix)
        end
        defineParameter("DistortionMix", "DistortionMix", 50, 0, 100, 1, onDistortionMixChange)
    end
end

Yes that’s right.

You need to be careful when using “this.program” though.
It should work fine in your program as it is now. But if you loaded the entire program as a layer into another program then what was originally program becomes a layer of the new program. Calling “this.program” would return a different object (program) and your script might not work as expected.

But you could also address the “SIMPLE” layer as parent of the parent of the script module (parent of “Engine” layer)

Engine = this.parent
SIMPLE = Engine.parent

Or you could do it directly. Even though it looks like a typing mistake it should work:

SIMPLE = this.parent.parent



Also if you don’t mind can you help me address effects? I tried to use the manual but failed. I’m trying to tie two effect parameters (from different effects) to the same parameter. I feel like I have the right idea but the issue has to do with the position of the parameter definition or function line.

This is actually quite clever. Just change line 6 to:

if effect1 and effect2 then

So only if it finds both effects then it defines the parameter and its function.

bus = this.parent:getBus("Internal FX")
if bus then
    --locate the distortion effect of the bus
    effect1 = bus:getEffect("Overdrive")
    effect2 = bus:getEffect("Distortion")
    if effect1 and effect2 then
        function onDistortionMixChange()
            effect2:setParameter(13, DistortionMix)
            effect1:setParameter(0, DistortionMix)
        end
        defineParameter("DistortionMix", "DistortionMix", 50, 0, 100, 1, onDistortionMixChange)
    end
end

That “parent.parent” trick is really good to know. This being my first trip into development, I’ve learned a ton. I may not use this sort of nested layer next time. I just have to continue learning lua but I’m getting more and more confident as I write this stuff.
Thanks for the help!

Ok I’m back again. So this has taken me hours and still no luck. I’m not sure if I should be using the macro script for this. The developer manual is super vague when it comes to macro script stuff and the example file they give don’t even have macro scripts. To top it off I checked out the macro scripts in the libraries that come with Halion and for the most part I can’t seem to see what the purpose of them are. They seem to be doing things all possible without the macro script. I wanted to create an animation that tied into the same parameter but I wanted it to update every 33 increments. I was thinking that using “getParameter” would allow me to read the parameter after I already set it but that didn’t work.

Layer=this.parent

function onSControl1DisplayChange()
  Layer:getParameter(131075, SControl1)
end

defineParameter("SControl1", "SControl1", 0, 0, 100, 1, onSControl1DisplayChange)

So I went to the Macro script thinking maybe since it’s basically just a display that I may need to use the macro script so I edited the code and still couldn’t get it to work. Truth be told I don’t even understand how I am supposed to be address objects from the macro script because the wording of the element page is confusing to me. I don’t understand how I should be addressing anything with “getElement”. Is it “getElement(Layer:Engine)”? I don’t get it. How exactly can I create a display tied to the same parameter that I set earlier?

Hi abject39,

You can connect an animation to any parameter even without scripting.
Halion will try to distribute available frames to values of the connected parameter. Same way like with macro page knobs.You get best results if the number of frames matches possible values of the parameter. But depending on the animation this can get heavy on graphics.

In my example I used only 3 frames and connected it to quick control (without any scripting).
It works but it changes at 25 and 75 so it didn’t split the range “very” equally. If this is important to you then you could either increase the number of frames or create a script parameter for the animation.

defineParameter("QC1", nil, 50, 0, 100, 1, function() qc1Change() end)
defineParameter{name = "Animation", default = 1, min = 1, max = 3, increment = 1, readOnly = true}

function qc1Change()
  this.parent:setParameter("QuickControl.QC1", QC1)
  if QC1 < 33 then
    this:setParameter("Animation", 1)
  elseif QC1 >= 33 and QC1 <= 66 then
    this:setParameter("Animation", 2)
  else
    this:setParameter("Animation", 3)
  end
end

qc1Change()

In this example the QC1 parameter will change the quick control but also change the Animation parameter value. This way you can decide when exactly the animation should change.

I know how to setup an automation but I think what I’m trying to do might not be possible. Your code creates a new parameter for the display to react from. I already have a created parameter and I just wanted something to react from the position of that created parameter without moving all of the increments but in a way I wanted. I was hoping “getparameter” would able to pull the value of an already existing parameter in that way instead of setting it but it seems not. I guess I’ll just use the way I know by setting multiple frames for points I don’t particularly need. Shame the frames aren’t automatically divided evenly.

I already have a created parameter and I just wanted something to react from the position of that created parameter without moving all of the increments but in a way I wanted. I was hoping “getparameter” would able to pull the value of an already existing parameter in that way instead of setting it but it seems not.

You can use getParameter to get the value of a parameter. But then you need few more lines to tell it what you actually want to do with that value.
When you change the SControl1 parameter in this script the only thing it will do is get the value of parameter(131075) and print it.

Layer=this.parent

function onSControl1DisplayChange()
  qc3Value = Layer:getParameter(131075)
  print(qc3Value)
end

defineParameter("SControl1", "SControl1", 0, 0, 100, 1, onSControl1DisplayChange)

After looking at this again I realize I was overthinking what I was trying to do and that this indeed is enough to help me do what I want to achieve. Thank you!

I do have a few questions. Is there any particular reason why you defined the parameter first and then did the function? Does the order make a difference? What’s the purpose of the restating the “qc1Change()” at the very end? What does that line tell the code?

Have a look at this: 3rd-Party Developers Support & SDKs | Steinberg
and scroll down to Change Callback with Anonymous Function

Is there any particular reason why you defined the parameter first and then did the function?

No, in this case it doesn’t matter and either way would do.

Does the order make a difference?

Sometimes.
With anonymous function you can pass arguments to the function directly when defining the parameter.
Example of that could be defining parameters in loop.

What’s the purpose of the restating the “qc1Change()” at the very end? What does that line tell the code?

It calls (and executes) the “qc1Change” function. To make sure that Animation is set to correct value.