Groups are fundamental to MA2 plugin operation. Plugins use groups to select fixtures, apply effects, and organize complex operations. This guide covers how plugins interact with the group system.
-- Select a single groupcmd('Group '..groupNumber)-- Select multiple groupscmd('Group '..group1..' + '..group2)-- Example from PulseWaveGencmd('Group '..rows[grpAct1]..' + '..rows[grpAct2])
local groups = {"A", "B", "C", "D", "E", "F", "G"}local grpStart = 1for group=grpStart, #groups do local presetCurrent = presetStart + ((group-1)* presetWidth) for start=1,colNb do local preset = presetCurrent+start-1 cmd("Group "..group.." At Gel 1."..colSwatchIndex[start]) cmd("Store Preset 4."..preset) cmd("Label Preset 4."..preset.." \""..groups[group].." "..colSwatchBook[start].."\"") end clear()end
Notice how the plugin iterates through groups numerically but uses letter names for labeling. This is a common pattern for organizing fixtures by position or type.
The getGroup() function extracts all fixtures from a group by exporting and parsing XML:
function getGroup(grpNum) gma.cmd('SelectDrive 1') -- select the internal drive local file = {} file.name = 'tempfile_getgroup.xml' file.directory = gma.show.getvar('PATH')..'/'..'importexport'..'/' file.fullpath = file.directory..file.name -- Export group to temporary XML file gma.cmd('Export Group ' .. grpNum .. ' "' .. file.name .. '"') -- Read XML file into table local t = {} for line in io.lines(file.fullpath) do t[#t + 1] = line end -- Clean up temp file os.remove(file.fullpath) -- Parse XML to extract fixture IDs local groupList = {} for i = 1, #t do if t[i]:find('Subfixture ') then local indices = {t[i]:find('"%d+"')} indices[1], indices[2] = indices[1] + 1, indices [2] - 1 -- Identify as fixture or channel local fixture if t[i]:find('fix_id') then fixture = 'Fixture ' .. tostring(t[i]:sub(indices[1], indices[2])) elseif t[i]:find('cha_id') then fixture = 'Channel ' .. tostring(t[i]:sub(indices[1], indices[2])) end -- Handle subfixtures if t[i]:find('sub_index') then local indices = {t[i]:find('"%d+"', indices[2]+2)} indices[1], indices[2] = indices[1] + 1, indices[2] - 1 fixture = fixture .. '.' .. tostring(t[i]:sub(unpack(indices))) end -- Add to list groupList[#groupList + 1] = fixture end end return groupListend
This function creates a temporary XML file in the importexport directory. Ensure this directory is accessible and has write permissions.
-- Collect group numbers from userlocal rows = {}local loopct = 1while true do local displayMessage if loopct == 1 then displayMessage = {'DS Group #'} else displayMessage = {'Row '..loopct..' Group #'} end local t = text(displayMessage[x], endMessage) if tonumber(t) then rows[loopct] = tonumber(t) loopct = loopct + 1 elseif t == endMessage then break endend-- Generate group arrayslocal groups = {} -- groups[group][fixture]for i = 1, #rows do groups[i] = getGroup(rows[i])end
local PG_grp = 0local function PG_setup() PG_grp = text('Enter Group Number', PG_grp) -- ... other setupendlocal function PG_create() cmd('Group '..PG_grp) -- ... operations on groupend
local PWG_groups = {}local function PWG_setup() PWG_groups = {} if PWG_batch or PWG_singleStack then local grpCollect = true while grpCollect do local grpInput = text("Enter Group " .. (#PWG_groups + 1) .. " (empty to finish)", "") if grpInput == nil or grpInput == "" then grpCollect = false else table.insert(PWG_groups, grpInput) end end else local grpInput = text("Enter Group Number", "0") if grpInput and grpInput ~= "" then table.insert(PWG_groups, grpInput) end end if #PWG_groups == 0 then fb("No groups entered, exiting.") return false end fb("Collected groups: " .. table.concat(PWG_groups, ", ")) return trueend
Allow users to enter groups one at a time until they provide empty input. This provides flexibility for working with varying numbers of groups.
-- Select group and apply valuescmd('Group '..grp)cmd('At 100')cmd('At Gel 1.1') -- Apply color-- With MAtricks for group manipulationcmd('Group '..PG_grp)cmd('MAtricksWings '..PG_wing)if PG_rnd == 'true' then cmd('ShuffleSelection')endcmd('MAtricksInterleave '..PG_amount)
function createPresets() for group=grpStart, #groups do local presetCurrent = presetStart + ((group-1)* presetWidth) for start=1,colNb do local preset = presetCurrent+start-1 cmd("Group "..group.." At Gel 1."..colSwatchIndex[start]) cmd("Store Preset 4."..preset) cmd("Label Preset 4."..preset.." \""..groups[group].." "..colSwatchBook[start].."\"") end clear() endend
function createCues() fb("--- Creating Cues") for group=grpStart, #groups do local presetCurrent = presetStart + ((group-1)* presetWidth) for start=1, colNb do local preset = presetCurrent + start - 1 local seqCurrent = seqStart + group - 1 cmd("Group "..group.." At Preset 4."..preset) cmd("Store Cue "..start.." Sequence "..seqCurrent) cmd("Label Sequence "..seqCurrent.." Cue "..start.." \""..groups[group].." "..colSwatchBook[start].."\"") end end clear()end
local function PWG_pickRandomAvoid(list, lastPick) if #list == 0 then return nil end if #list == 1 then return list[1] end local available = {} for _, item in ipairs(list) do if item ~= lastPick then table.insert(available, item) end end if #available == 0 then available = list end return available[math.random(1, #available)]endlocal function PWG_getRandomGroups(groupList, count) local result = {} local lastGrp = nil for i = 1, count do local newGrp = PWG_pickRandomAvoid(groupList, lastGrp) table.insert(result, newGrp) lastGrp = newGrp end return resultend
This pattern ensures variety by avoiding consecutive repetition of the same group.
local function PWG_getWing(direction) if direction == "in" or direction == "out" then return 2 else return 0 endend-- Apply to groupcmd("Group " .. grp)local wing = PWG_getWing(direction)if wing > 0 then cmd("MAtricksWings " .. wing)end
for i, grp in ipairs(PWG_groups) do progressStep = progressStep + 1 if PWG_progressHandle then gma.gui.progress.set(PWG_progressHandle, progressStep) gma.gui.progress.settext(PWG_progressHandle, "Adding G" .. grp .. " to Full cue") end cmd("Group " .. grp) if wing > 0 then cmd("MAtricksWings " .. wing) end cmd("PresetType \"DIMMER\"") cmd("At 100") PWG_sleep(0.05) cmd("Delay " .. delayStr) PWG_sleep(0.05)endcmd("Store Sequence " .. PWG_seq .. " Cue 1")
for i, grp in ipairs(groupList) do cmd("Group " .. grp) cmd("At 100") cmd("Delay 0 Thru " .. (i * 0.2)) -- Stagger timing per group cmd("Store Sequence "..seqNum.." Cue "..cueNum)end