Is it me or the Macro script editor

I’m new to Lua and I wanted to see if I can get 2 controllers to connect via a script without a direct macro connection, so I did this:

I have a knob connected to a 5 step integer variable named “stepper” to create a stepped instead of smooth knob motion. The script parameter goes out to a text box with @pitchStep in it’s value field.

defineParameter ("pitchStep", Nil, 0, 0, 5, 1, function() pitchStepChange() end)

function pitchStepChange()
	stepChange = stepper

This worked and the text box reflected the knob value.

Next I tried this:

defineParameter ("pitchStep", Nil, 0, 0, 5, 1, function() pitchStepChange() end)

function pitchStepChange()
	stepChange = stepper
	this.program:setParameter(22, stepChange) 

parameter ID 22 is program coarse tune.
This didn’t work and I get a script error warning.

I tried this in the Lua midi module and it worked. The coarse tuning was shifted up 5 semitones.

	stepChange = 5
	this.program:setParameter(22, stepChange)

In my mind if the setParameter function works with a variable in the Lua module it should work in the Macro editor as well. I tried “this.program:setParameter(22, 1)” to remove the variable and still got an error warning.

Any input would be much appreciated.

I suddenly realised I didn’t need the variable and changed the code to this.

defineParameter ("pitchStep", Nil, 0, 0, 5, 1, function() pitchStepChange() end)

function pitchStepChange()
 this.program:setParameter(22, pitchStep)

When I put this script in the Lua module and connected the parameter to the knob element, all works fine. You get a 5 semitone transpose one the program layer.

However, if you put the same script on your macro page and connect the parameter in the knob value box, it doesn’t work and you get a script error. I know the script is connecting because the knob moves in a 5 step fashion and not gradual as usual.

I still don’t know if it’s something I’m doing wrong, but I have a feeling the macro editor has some issues. There have been other bugs creeping up with selection scope.

From a macro page script, use getElement() (edit:
) instead of “this” to access the module that the macro page is attached to.

Thanks this works.

My browser gave a privacy warning for the link you put here, I went to this instead. Same thing I suppose.

Does getElement only access the layer or module it is attached to, or can you still access zones etc? (I couldn’t get this to work). Or is it that UI script is really just for the UI and you have to use the Lua module for the more global tasks?

Found some good examples in Skylab that answered my question.

local zones = getElement():getLayer():findZones()

Yes, that’s the correct one. The URL was switched shortly before the release. I corrected my response.

As you already noticed getElement() gives you an element in the program tree that allows you to traverse it to find other elements.

Thanks for the feedback.

I’ve only messed around with Javascript a few years ago, so the concepts here are familiar, but it’s all still very confusing.

The biggest confusion when looking at examples, comes from keeping track of which are Halion or script functions. Obviously it is all on the page, but it’s still a lot of new information for a newcomer.

I think I should see if LuaEdit works . A bit of syntax highlighting is going to help a lot.

I’m trying to understand how to do this as well. I have a switch and a knob and when the switch is clicked I’m trying to reset the knob back to 0. I’ve been able to detect the switch change which I verified using prints but I have yet to figure out how to reset the knob. Am I trying to set the knob to 0 or the underlying parameter the knob is attached to?

From my standpoint it’s how to tie Lua into the Halion 6 that’s difficult. Lua isn’t hard in itself.

Parameters are global variables and you always have access to them.
So this should do the trick: (Lua script module)

function resetSwitchChange()
	if knob > 0 then
	knob = 0

defineParameter("knob", nil, 0, 0, 100, 1)

defineParameter("resetSwitch", nil, false, resetSwitchChange)

As it was explained to me, if it handles UI changes put the script in macro script, if it handles Halion engine matters use the Lua script module and link parameters via drag and drop to the UI controller.

There a re a few very important topics in the script reference to understand:

Creating Parameters

Working with Parameters

Threads in HALion

Understanding the class elements and hierarchy is also very important.


In addition, you might want to prevent that the reset switch can be automated or is being saved with the program. You can do this if you define the parameter with named arguments. For example:

defineParameter { name = "resetSwitch", longName = "Reset Switch", default = false, onChanged = resetSwitchChange, writeAlways = true, automatable = false, persistent = false }

The documentation of parameters with named arguments can be found here:



Thanks guys, hopefully I can give it another shot tonight.

You’re welcome!

Btw, the new instruments Anima, Skylab, etc. are not protected. You can learn from them by inspecting their macro pages and scripts.



I saw that with Skylab. My biggest issue is how to interface lua with the Halion 6 object model. I’m not sure exactly how the two are connected yet. I’m not sure if I should be attempting to change an interface control or if I should be trying to change the underlying parameter in the halion engine, etc. But I’ll read through the links you both giving me and see if those help.

While having some instruments pre-made and unprotected is helpful I think a walk through on how to create one from scratch would have been a bigger help. The instrument I’m doing is simple so if I get it working maybe I’ll turn it into a beginner’s tutorial.

Hi DodgingRain.

If a parameter needs to be connect directly or via script mainly depends on the question if you want to customize it or not.

  • If you are happy with the range of a parameter and how it works, then you can connect it directly to the control on the macro page.
  • If you need to customize a parameter, you usually must put a script modue in between and use defineParameter and a change callback to customize the behavior. The change callback uses setParameter to adjust the parameter.

In our instruments we used both ways.



The Creating Parameters and Working with Parameters sections explained a lot. I didn’t look at the advanced section of the scripting documentation as I considered what I was doing not very advanced. We’ll see how it goes later when I get at Halion and try to fix my script.

Thanks all, between everyone’s comments I got it working. It wasn’t obvious to me that I should use element:setParameter instead of this.program:setParameter in the macro script.

-- read the ID of the parent layer's level parameter
local lQC3 = getElement():getParameterDefinition("QuickControl.QC3").id
local lQC4 = getElement():getParameterDefinition("QuickControl.QC4").id
local lQC5 = getElement():getParameterDefinition("QuickControl.QC5").id
local lQC6 = getElement():getParameterDefinition("QuickControl.QC6").id

defineParameter("iMode", nil, 0, 0, 1, 1, function() switchChange() end)

function switchChange()
 if iMode==0 then 
  getElement():setParameter(lQC5, 0)
  getElement():setParameter(lQC6, 0)  
 elseif iMode==1 then
  getElement():setParameter(lQC3, 0)
  getElement():setParameter(lQC4, 0)

Per why would I want to address a parameter by name? Why wouldn’t I always display the parameter id in the ParamsList and use that number in the setParameter statement? The only reason I can think of to use a parameter by name would be if I was dynamically adding elements to the program?

Hi DodgingRain,

looking at your code, I would say, you shouldn’t use the UI script for your switch. Here’s why:

  • The UI script runs only when the UI is open. If you close the UI, the UI script won’t be executed anymore.
  • The parameters you define in the UI script cannot be automated.

Therefore, the major part of your script should be executed in the Lua Script MIDI module in the Program Tree. The UI script is mainly for adopting or customizing the UI, for example, switching pages, special control behavior, etc. In many cases you might not need the UI script at all.

If you execute your code in the Lua Script MIDI module, it will be executed even if the UI is closed. Instead of “getElement()” you have to write “this.parent”. Using “this.program” can be tricky, because if you load your instrument in HSSE, the element with the macro page won’t be equal to the element of the Program anymore. If the Lua Script MIDI module is a direct child of the element with the macro page, “this.parent” should work.

Regarding you question about adressing parameters by name: The names are more convenient and more readable. Adressing parameters via IDs is faster, but this is only needed for very demanding scripts. Till now, I never needed this.

I hope, these insights are of help for you.

Thanks for the feedback. I’ll give that a try and see if I can get it to work.

You’re welcome :slight_smile: