<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://www.visualsorcery.com/LightForgeWiki/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://www.visualsorcery.com/LightForgeWiki/index.php?feed=atom&amp;namespace=0&amp;title=Special%3ANewPages</id>
		<title>Light Forge Wiki - New pages [en]</title>
		<link rel="self" type="application/atom+xml" href="http://www.visualsorcery.com/LightForgeWiki/index.php?feed=atom&amp;namespace=0&amp;title=Special%3ANewPages"/>
		<link rel="alternate" type="text/html" href="http://www.visualsorcery.com/LightForgeWiki/index.php?title=Special:NewPages"/>
		<updated>2026-04-25T09:58:54Z</updated>
		<subtitle>From Light Forge Wiki</subtitle>
		<generator>MediaWiki 1.20.0</generator>

	<entry>
		<id>http://www.visualsorcery.com/LightForgeWiki/index.php?title=Sample_Addons</id>
		<title>Sample Addons</title>
		<link rel="alternate" type="text/html" href="http://www.visualsorcery.com/LightForgeWiki/index.php?title=Sample_Addons"/>
				<updated>2013-05-09T23:22:47Z</updated>
		
		<summary type="html">&lt;p&gt;Chris Monson: /* Lamps On */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Select Children=&lt;br /&gt;
&lt;br /&gt;
This script will get a list of all the groups that you currently have selected and then it will select all of their child groups and deselect the parent.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#called when the addon is selected in the addon's menu&lt;br /&gt;
def onExecute():&lt;br /&gt;
	#get list of selected groups&lt;br /&gt;
	groupList = api.groups.getSelectedGroups()&lt;br /&gt;
&lt;br /&gt;
	if groupList != None:&lt;br /&gt;
		for group in groupList:&lt;br /&gt;
			selectChildren(group)&lt;br /&gt;
&lt;br /&gt;
#select all the children for a given group			&lt;br /&gt;
def selectChildren(groupPath):&lt;br /&gt;
	childCount = api.groups.getChildCount(groupPath)&lt;br /&gt;
&lt;br /&gt;
	if childCount &amp;gt; 0:&lt;br /&gt;
		api.groups.deselectGroup(groupPath)&lt;br /&gt;
	&lt;br /&gt;
		for i in range(0, childCount):&lt;br /&gt;
			#build the group path for the next group&lt;br /&gt;
			newPath = groupPath&lt;br /&gt;
			if len(newPath) == 0:&lt;br /&gt;
				newPath = str(i)&lt;br /&gt;
			else:&lt;br /&gt;
				newPath = newPath + &amp;quot;,&amp;quot; + str(i) &lt;br /&gt;
			#select group&lt;br /&gt;
			api.groups.selectGroup(newPath)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Lamps On=&lt;br /&gt;
This addon allows you to specify a list of profile names and the value that the lamp channel must be assigned to in order to strike the lamp for that particular fixture. This addon runs automatically on startup asking if you'd like to turn the lamps on.&lt;br /&gt;
&lt;br /&gt;
This example is a little more complicated, utilizing file operations for saving and loading settings, asynchronous processing, as well as using Windows Forms for dialog boxes to adjust the addon's settings in Lightforge. The bulk of the code is devoted to setting up the forms and laying out controls for the dialog boxes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
import clr&lt;br /&gt;
clr.AddReference(&amp;quot;System.Drawing&amp;quot;)&lt;br /&gt;
clr.AddReference(&amp;quot;System.Windows.Forms&amp;quot;)&lt;br /&gt;
from System.Drawing import Point&lt;br /&gt;
from System.Windows.Forms import Application, Button, ListView, ListViewItem, View, Form, ContextMenu, TextBox, NumericUpDown, Label&lt;br /&gt;
from System.Windows.Forms import MessageBox, MessageBoxButtons&lt;br /&gt;
from System.Windows.Forms import FormBorderStyle, DialogResult&lt;br /&gt;
&lt;br /&gt;
profilesAndValues = []&lt;br /&gt;
&lt;br /&gt;
#called when the script is loaded&lt;br /&gt;
def onInitialize():&lt;br /&gt;
	load()&lt;br /&gt;
	&lt;br /&gt;
#called when the script settings are edited in the script settings dialog&lt;br /&gt;
def onEdit():&lt;br /&gt;
	dlg = LampOnDialog()&lt;br /&gt;
	if dlg.ShowDialog() == DialogResult.OK:&lt;br /&gt;
		save()&lt;br /&gt;
&lt;br /&gt;
#executes asyncronously when clicked from the Lightforge interface		&lt;br /&gt;
def onExecuteAsync():&lt;br /&gt;
	onStartupAsync()&lt;br /&gt;
&lt;br /&gt;
#called as Lightforge is starting up&lt;br /&gt;
def onStartupAsync():&lt;br /&gt;
	global profilesAndValues&lt;br /&gt;
	if MessageBox.Show(&amp;quot;Would you like to turn lamps on?&amp;quot;, &amp;quot;Lamp Startup&amp;quot;, MessageBoxButtons.YesNo) == DialogResult.Yes:&lt;br /&gt;
		print(&amp;quot;&amp;quot;)&lt;br /&gt;
		print(&amp;quot;Turning Lamps On&amp;quot;)&lt;br /&gt;
		&lt;br /&gt;
		#find profiles that match those in our profilesAndValues list and set values appropriately&lt;br /&gt;
		findProfiles(&amp;quot;&amp;quot;, profilesAndValues)&lt;br /&gt;
		&lt;br /&gt;
		#wait 5 seconds to allow the fixtures to process the command&lt;br /&gt;
		print(&amp;quot;Waiting...&amp;quot;)&lt;br /&gt;
		api.wait(5)&lt;br /&gt;
		&lt;br /&gt;
		#release the rig to remove the changes we made&lt;br /&gt;
		print(&amp;quot;Releasing Fixtures&amp;quot;)&lt;br /&gt;
		api.groups.releaseGroup(&amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
		&lt;br /&gt;
#Search through rig to find the specified profiles and assign them the given values&lt;br /&gt;
def findProfiles(groupPath, profileList):&lt;br /&gt;
	currentPath = groupPath&lt;br /&gt;
&lt;br /&gt;
	#step through all children of the current group&lt;br /&gt;
	for i in range(0, api.groups.getChildCount(currentPath)):&lt;br /&gt;
		#build the group path for the next group&lt;br /&gt;
		if len(currentPath) == 0:&lt;br /&gt;
			currentPath = str(i)&lt;br /&gt;
		else:&lt;br /&gt;
			currentPath = groupPath + &amp;quot;,&amp;quot; + str(i) &lt;br /&gt;
&lt;br /&gt;
		found = False&lt;br /&gt;
		&lt;br /&gt;
		#step through all the profiles we've listed to see if this fixture's profile matches  any of them&lt;br /&gt;
		for prf in profileList:		&lt;br /&gt;
			if prf[0] in api.groups.getProfileName(currentPath):&lt;br /&gt;
				#set the value of this fixture to the value in the profile list&lt;br /&gt;
				api.groups.setAttribute(api.attributeTypes.lamp, int(prf[1]) * 256, currentPath)&lt;br /&gt;
				found = True&lt;br /&gt;
				&lt;br /&gt;
		#call this function on the tested group to work recursively through the groups&lt;br /&gt;
		if found == False and api.groups.getChildCount(currentPath) &amp;gt; 0:&lt;br /&gt;
			findProfiles(currentPath, profileList)&lt;br /&gt;
&lt;br /&gt;
#Save settings to file&lt;br /&gt;
def save():&lt;br /&gt;
	global profilesAndValues&lt;br /&gt;
	strOutput = &amp;quot;&amp;quot;&lt;br /&gt;
	for prf in profilesAndValues:&lt;br /&gt;
		strOutput += prf[0] + &amp;quot;;&amp;quot; + str(prf[1]) + &amp;quot;\n&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
	f = open(addon.getDirectory() + &amp;quot;Lamps On.settings&amp;quot;, &amp;quot;w+&amp;quot;)&lt;br /&gt;
	f.write(strOutput)&lt;br /&gt;
	f.close()&lt;br /&gt;
&lt;br /&gt;
#Load settings in from file	&lt;br /&gt;
def load():&lt;br /&gt;
	global profilesAndValues&lt;br /&gt;
	profilesAndValues = []&lt;br /&gt;
	try:&lt;br /&gt;
		f = open(addon.getDirectory() + &amp;quot;Lamps On.settings&amp;quot;, &amp;quot;r+&amp;quot;)&lt;br /&gt;
		for line in f:&lt;br /&gt;
			profilesAndValues.append(line.rstrip().split(';'))&lt;br /&gt;
		f.close()&lt;br /&gt;
	except: &lt;br /&gt;
		pass&lt;br /&gt;
	&lt;br /&gt;
#Dialog box for assigning values to profiles			&lt;br /&gt;
class LampOnDialog(Form):&lt;br /&gt;
&lt;br /&gt;
	def __init__(self):&lt;br /&gt;
		global profilesAndValues&lt;br /&gt;
		self.Text = 'Lamp On Settings'&lt;br /&gt;
		self.FormBorderStyle = FormBorderStyle.FixedDialog&lt;br /&gt;
		self.MinimizeBox = False&lt;br /&gt;
		self.MaximizeBox = False&lt;br /&gt;
		&lt;br /&gt;
		margin = 10&lt;br /&gt;
		&lt;br /&gt;
		#Cancel Button&lt;br /&gt;
		btnCancel = Button()&lt;br /&gt;
		btnCancel.Text = &amp;quot;Cancel&amp;quot;&lt;br /&gt;
		btnCancel.Location = Point(self.ClientRectangle.Right - (btnCancel.Width + margin), self.ClientRectangle.Bottom - (btnCancel.Height + margin))&lt;br /&gt;
		btnCancel.Click += self.clickCancel&lt;br /&gt;
		self.Controls.Add(btnCancel)&lt;br /&gt;
		&lt;br /&gt;
		#Ok Button&lt;br /&gt;
		btnOk = Button()&lt;br /&gt;
		btnOk.Text = &amp;quot;Ok&amp;quot;&lt;br /&gt;
		btnOk.Location = Point(btnCancel.Left - (btnOk.Width + margin), self.ClientRectangle.Bottom - (btnOk.Height + margin))&lt;br /&gt;
		btnOk.Click += self.clickOk&lt;br /&gt;
		self.Controls.Add(btnOk)&lt;br /&gt;
		&lt;br /&gt;
		#List Box&lt;br /&gt;
		self.lstProfiles = ListView()&lt;br /&gt;
		self.lstProfiles.Location = Point(margin, margin)&lt;br /&gt;
		self.lstProfiles.Width = self.ClientRectangle.Width - (margin * 2)&lt;br /&gt;
		self.lstProfiles.Height = btnOk.Top - (margin * 2)&lt;br /&gt;
		self.Controls.Add(self.lstProfiles)&lt;br /&gt;
		self.lstProfiles.View = View.Details&lt;br /&gt;
		self.lstProfiles.Columns.Add(&amp;quot;Profile&amp;quot;)&lt;br /&gt;
		self.lstProfiles.Columns.Add(&amp;quot;Value&amp;quot;)	&lt;br /&gt;
		self.lstProfiles.Columns[0].Width = self.lstProfiles.Width * 0.7&lt;br /&gt;
		self.refreshList()&lt;br /&gt;
		&lt;br /&gt;
		#Context Menu&lt;br /&gt;
		listContext = ContextMenu()&lt;br /&gt;
		listContext.MenuItems.Add(&amp;quot;Add Profile&amp;quot;)&lt;br /&gt;
		listContext.MenuItems[0].Click += self.addProfile&lt;br /&gt;
		listContext.MenuItems.Add(&amp;quot;Edit&amp;quot;)&lt;br /&gt;
		listContext.MenuItems[1].Click += self.editProfile&lt;br /&gt;
		listContext.MenuItems.Add(&amp;quot;Remove&amp;quot;)&lt;br /&gt;
		listContext.MenuItems[2].Click += self.removeProfile&lt;br /&gt;
		self.lstProfiles.ContextMenu = listContext&lt;br /&gt;
	&lt;br /&gt;
	#reload the profilesAndValues data into the ListView control&lt;br /&gt;
	def refreshList(self):&lt;br /&gt;
		global profilesAndValues&lt;br /&gt;
		self.lstProfiles.Items.Clear()&lt;br /&gt;
		for prf in profilesAndValues:&lt;br /&gt;
			lvItem = ListViewItem(prf[0])&lt;br /&gt;
			lvItem.SubItems.Add(str(prf[1]))&lt;br /&gt;
			self.lstProfiles.Items.Add(lvItem)&lt;br /&gt;
	&lt;br /&gt;
	#handle Ok button click&lt;br /&gt;
	def clickOk(self, sender, args):&lt;br /&gt;
		self.DialogResult = DialogResult.OK&lt;br /&gt;
		self.Close&lt;br /&gt;
		&lt;br /&gt;
	#handle Cancel button click	&lt;br /&gt;
	def clickCancel(self, sender, args):&lt;br /&gt;
		self.DialogResult = DialogResult.Cancel&lt;br /&gt;
		self.Close&lt;br /&gt;
&lt;br /&gt;
	#add profile called from the context menu	&lt;br /&gt;
	def addProfile(self, sender, args):&lt;br /&gt;
		global profilesAndValues&lt;br /&gt;
		dlg = ProfileValueDialog(&amp;quot;&amp;quot;,0)&lt;br /&gt;
		if dlg.ShowDialog() == DialogResult.OK:&lt;br /&gt;
			profilesAndValues.append([dlg.profile,dlg.value])&lt;br /&gt;
			self.refreshList()&lt;br /&gt;
	&lt;br /&gt;
	#remove profile called from the context menu	&lt;br /&gt;
	def removeProfile(self, sender, args):&lt;br /&gt;
		global profilesAndValues&lt;br /&gt;
		if self.lstProfiles.SelectedIndices.Count &amp;gt; 0:&lt;br /&gt;
			profilesAndValues.pop(self.lstProfiles.SelectedIndices[0])&lt;br /&gt;
			self.refreshList()&lt;br /&gt;
		&lt;br /&gt;
	#edit profile called from the context menu	&lt;br /&gt;
	def editProfile(self, sender, args):&lt;br /&gt;
		global profilesAndValues&lt;br /&gt;
		if self.lstProfiles.SelectedIndices.Count &amp;gt; 0:&lt;br /&gt;
			index = self.lstProfiles.SelectedIndices[0]&lt;br /&gt;
			dlg = ProfileValueDialog(profilesAndValues[index][0],profilesAndValues[index][1])&lt;br /&gt;
			if dlg.ShowDialog() == DialogResult.OK:&lt;br /&gt;
				profilesAndValues[index] = [dlg.profile,dlg.value]&lt;br /&gt;
				self.refreshList()&lt;br /&gt;
&lt;br /&gt;
				&lt;br /&gt;
#Dialog box for assigning values to profiles			&lt;br /&gt;
class ProfileValueDialog(Form):&lt;br /&gt;
&lt;br /&gt;
	profile = &amp;quot;&amp;quot;&lt;br /&gt;
	value = 0&lt;br /&gt;
&lt;br /&gt;
	def __init__(self, profileName, lampValue):&lt;br /&gt;
		global profilesAndValues&lt;br /&gt;
		self.Text = 'Profile Value Dialog'&lt;br /&gt;
		self.FormBorderStyle = FormBorderStyle.FixedDialog&lt;br /&gt;
		self.MinimizeBox = False&lt;br /&gt;
		self.MaximizeBox = False&lt;br /&gt;
		&lt;br /&gt;
		margin = 10&lt;br /&gt;
		&lt;br /&gt;
		self.Width = 350&lt;br /&gt;
		self.Height = 150&lt;br /&gt;
		&lt;br /&gt;
		#Label&lt;br /&gt;
		lblPrompt = Label()&lt;br /&gt;
		lblPrompt.Text = &amp;quot;Enter profile name and 8 bit value for lamp on.&amp;quot;&lt;br /&gt;
		lblPrompt.Location = Point(margin, margin)&lt;br /&gt;
		lblPrompt.Width = self.Width&lt;br /&gt;
		self.Controls.Add(lblPrompt)&lt;br /&gt;
		&lt;br /&gt;
		#Text Box&lt;br /&gt;
		self.txtProfile = TextBox()&lt;br /&gt;
		self.txtProfile.Location = Point(margin, margin * 4)&lt;br /&gt;
		self.txtProfile.Text = profileName&lt;br /&gt;
		self.txtProfile.Width = 200&lt;br /&gt;
		self.Controls.Add(self.txtProfile)&lt;br /&gt;
		&lt;br /&gt;
		#NumericUpDown&lt;br /&gt;
		self.numValue = NumericUpDown()&lt;br /&gt;
		self.numValue.Maximum = 255&lt;br /&gt;
		self.numValue.Value = lampValue&lt;br /&gt;
		self.numValue.Location = Point(self.txtProfile.Right + margin, self.txtProfile.Top)&lt;br /&gt;
		self.numValue.Width = (self.Width - margin) - (self.txtProfile.Right + (margin * 3))&lt;br /&gt;
		self.Controls.Add(self.numValue)&lt;br /&gt;
		&lt;br /&gt;
		#Cancel Button&lt;br /&gt;
		btnCancel = Button()&lt;br /&gt;
		btnCancel.Text = &amp;quot;Cancel&amp;quot;&lt;br /&gt;
		btnCancel.Location = Point(self.ClientRectangle.Right - (btnCancel.Width + margin), self.ClientRectangle.Bottom - (btnCancel.Height + margin))&lt;br /&gt;
		btnCancel.Click += self.clickCancel&lt;br /&gt;
		self.Controls.Add(btnCancel)&lt;br /&gt;
		&lt;br /&gt;
		#Ok Button&lt;br /&gt;
		btnOk = Button()&lt;br /&gt;
		btnOk.Text = &amp;quot;Ok&amp;quot;&lt;br /&gt;
		btnOk.Location = Point(btnCancel.Left - (btnOk.Width + margin), self.ClientRectangle.Bottom - (btnOk.Height + margin))&lt;br /&gt;
		btnOk.Click += self.clickOk&lt;br /&gt;
		self.Controls.Add(btnOk)&lt;br /&gt;
		&lt;br /&gt;
	def clickOk(self, sender, args):&lt;br /&gt;
		self.profile = self.txtProfile.Text&lt;br /&gt;
		self.value = self.numValue.Value&lt;br /&gt;
		self.DialogResult = DialogResult.OK&lt;br /&gt;
		self.Close&lt;br /&gt;
		&lt;br /&gt;
	def clickCancel(self, sender, args):&lt;br /&gt;
		self.DialogResult = DialogResult.Cancel&lt;br /&gt;
		self.Close&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Chris Monson</name></author>	</entry>

	<entry>
		<id>http://www.visualsorcery.com/LightForgeWiki/index.php?title=Addon</id>
		<title>Addon</title>
		<link rel="alternate" type="text/html" href="http://www.visualsorcery.com/LightForgeWiki/index.php?title=Addon"/>
				<updated>2013-05-09T20:34:17Z</updated>
		
		<summary type="html">&lt;p&gt;Chris Monson: /* getDirectory() */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Methods=&lt;br /&gt;
&lt;br /&gt;
==getDirectory()==&lt;br /&gt;
'''getDirectory() As String'''&lt;br /&gt;
&lt;br /&gt;
This function returns the path of the current addon's folder.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
path = addon.getDirectory()&lt;br /&gt;
print(path)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Chris Monson</name></author>	</entry>

	<entry>
		<id>http://www.visualsorcery.com/LightForgeWiki/index.php?title=Addons</id>
		<title>Addons</title>
		<link rel="alternate" type="text/html" href="http://www.visualsorcery.com/LightForgeWiki/index.php?title=Addons"/>
				<updated>2013-05-09T20:31:00Z</updated>
		
		<summary type="html">&lt;p&gt;Chris Monson: /* API */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
The Lightforge API allows you to create new tools, new input and output methods, automate complex operations, and much more.&lt;br /&gt;
&lt;br /&gt;
Lightforge addons are written in IronPython. IronPython is an open-source implementation of the Python programming language which is tightly integrated with the .NET Framework. It allows you to use both .Net and Python libraries and allows very tight integration between Lightforge and addons. For more information on IronPython you can visit [http://www.ironpython.net www.ironpython.net]. For more information on Python in general you can visit [http://www.python.org/doc/ www.python.org/doc/].&lt;br /&gt;
&lt;br /&gt;
==Your First Addon==&lt;br /&gt;
To create an addon go to Addon Menu and click Addon Settings. You will find a button labeled Addon Folder. Clicking this will open up the Lightforge addon folder.&lt;br /&gt;
&lt;br /&gt;
In this folder create a new folder named &amp;quot;Hello World&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Open the Hello World folder and create a new file named base.py. Open this file with your preferred Python editor, or Notepad if you have none.&lt;br /&gt;
&lt;br /&gt;
Type the code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def onExecute():&lt;br /&gt;
	print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Save the script, and return to Lightforge.&lt;br /&gt;
&lt;br /&gt;
In the Addon Settings dialog click &amp;quot;Reload Addons&amp;quot;, and if all went well, your addon will appear.&lt;br /&gt;
&lt;br /&gt;
Click the check box next to the Hello World addon to enable it, then close the Addon Settings Dialog.&lt;br /&gt;
&lt;br /&gt;
In the Addon menu the Hello World addon should be visible. Clicking on it will run the addon.&lt;br /&gt;
&lt;br /&gt;
Now in the Window menu click &amp;quot;Console&amp;quot;, this will open up the python console and you should see the text &amp;quot;Hello World!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Congratulations! You've made an addon!&lt;br /&gt;
&lt;br /&gt;
==Where To Go From Here==&lt;br /&gt;
I would suggest investigating the [[API]] and seeing what all there is to do. Also be sure to check out the [[Sample Addons]].&lt;br /&gt;
&lt;br /&gt;
=Addon Structure=&lt;br /&gt;
The file structure of a Lightforge addon is very simple. It consists of a folder with at least one required script file named base.py, and optionally a xml file named addonInfo.xml.&lt;br /&gt;
&lt;br /&gt;
==base.py==&lt;br /&gt;
This is the entry point for your addon. It's the script file that Lightforge interacts with directly.&lt;br /&gt;
&lt;br /&gt;
==addonInfo.xml==&lt;br /&gt;
This xml file gives Lightforge additional information about your addon. This info will appear in the Addon Settings panel.&lt;br /&gt;
&lt;br /&gt;
The addonInfo.xml file can contain the following information:&lt;br /&gt;
&lt;br /&gt;
===Author===&lt;br /&gt;
The author of the addon.&lt;br /&gt;
===Version===&lt;br /&gt;
The current version number.&lt;br /&gt;
===Website===&lt;br /&gt;
A website associated with this addon.&lt;br /&gt;
===Support===&lt;br /&gt;
An email address or website for providing addon support.&lt;br /&gt;
&lt;br /&gt;
===XML Structure===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;addonInfo&amp;gt;&lt;br /&gt;
	&amp;lt;author&amp;gt;Visual Sorcery&amp;lt;/author&amp;gt;&lt;br /&gt;
	&amp;lt;version&amp;gt;1.0.0&amp;lt;/version&amp;gt;&lt;br /&gt;
	&amp;lt;website&amp;gt;http://www.visualsorcery.com/&amp;lt;/website&amp;gt;&lt;br /&gt;
	&amp;lt;support&amp;gt;support@visualsorcery.com&amp;lt;/support&amp;gt;&lt;br /&gt;
&amp;lt;/addonInfo&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Classes=&lt;br /&gt;
==API==&lt;br /&gt;
This class contains all access for working with Lightforge.&lt;br /&gt;
&lt;br /&gt;
[[API]]&lt;br /&gt;
&lt;br /&gt;
==Addon==&lt;br /&gt;
This class gives you access to information about your addon.&lt;br /&gt;
&lt;br /&gt;
[[Addon]]&lt;br /&gt;
&lt;br /&gt;
=Sample Addons=&lt;br /&gt;
On this page you can find sample code for learning how to create addons.&lt;br /&gt;
[[Sample Addons]]&lt;/div&gt;</summary>
		<author><name>Chris Monson</name></author>	</entry>

	<entry>
		<id>http://www.visualsorcery.com/LightForgeWiki/index.php?title=Api.cues</id>
		<title>Api.cues</title>
		<link rel="alternate" type="text/html" href="http://www.visualsorcery.com/LightForgeWiki/index.php?title=Api.cues"/>
				<updated>2013-05-07T21:43:00Z</updated>
		
		<summary type="html">&lt;p&gt;Chris Monson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Methods=&lt;br /&gt;
&lt;br /&gt;
==getCuelistCount==&lt;br /&gt;
'''getCuelistCount() As Integer'''&lt;br /&gt;
&lt;br /&gt;
Returns the number of cuelists in this show.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
cuelistCount = api.cues.getCuelistCount()&lt;br /&gt;
print(cuelistCount)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==getCuelistLength==&lt;br /&gt;
'''getCuelistLength() As Double'''&lt;br /&gt;
&lt;br /&gt;
Returns the length of the current cuelist in seconds or beats&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
cuelistLength = api.cues.getCuelistLength()&lt;br /&gt;
print(cuelistLength)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==getCuelistIndex==&lt;br /&gt;
'''getCuelistIndex() As Integer'''&lt;br /&gt;
&lt;br /&gt;
Returns the index of the current cuelist.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
index = api.cues.getCuelistIndex()&lt;br /&gt;
print(index)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==selectCuelist==&lt;br /&gt;
'''selectCuelist(index As Integer)'''&lt;br /&gt;
&lt;br /&gt;
Changes to a different cuelist.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
api.cues.selectCuelist(2)&lt;br /&gt;
print(api.cues.getCuelistIndex())&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Chris Monson</name></author>	</entry>

	<entry>
		<id>http://www.visualsorcery.com/LightForgeWiki/index.php?title=Api.scriptDirectory</id>
		<title>Api.scriptDirectory</title>
		<link rel="alternate" type="text/html" href="http://www.visualsorcery.com/LightForgeWiki/index.php?title=Api.scriptDirectory"/>
				<updated>2013-05-07T21:36:37Z</updated>
		
		<summary type="html">&lt;p&gt;Chris Monson: Created page with &amp;quot;=scriptDirectory=  Contains the path of the script directory  Usage:    print(api.scriptDirectory)&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=scriptDirectory=&lt;br /&gt;
&lt;br /&gt;
Contains the path of the script directory&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
   print(api.scriptDirectory)&lt;/div&gt;</summary>
		<author><name>Chris Monson</name></author>	</entry>

	<entry>
		<id>http://www.visualsorcery.com/LightForgeWiki/index.php?title=Api.output</id>
		<title>Api.output</title>
		<link rel="alternate" type="text/html" href="http://www.visualsorcery.com/LightForgeWiki/index.php?title=Api.output"/>
				<updated>2013-05-06T23:29:54Z</updated>
		
		<summary type="html">&lt;p&gt;Chris Monson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Methods=&lt;br /&gt;
&lt;br /&gt;
==getDMX==&lt;br /&gt;
'''getDMX(universe As Integer) As Byte()'''&lt;br /&gt;
&lt;br /&gt;
Returns a byte array containing all current dmx data for the specified universe. If the specified universe doesn't exist this function returns null.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
dmxValues = api.output.getDMX(0)&lt;br /&gt;
print(dmxValues[42])&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==getUniverseCount==&lt;br /&gt;
'''getUniverseCount() as Integer'''&lt;br /&gt;
&lt;br /&gt;
Returns the number of DMX universes in the current show.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
universeCount = api.output.getUniverseCount()&lt;br /&gt;
print(universeCount)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Chris Monson</name></author>	</entry>

	<entry>
		<id>http://www.visualsorcery.com/LightForgeWiki/index.php?title=Api.attributeTypes</id>
		<title>Api.attributeTypes</title>
		<link rel="alternate" type="text/html" href="http://www.visualsorcery.com/LightForgeWiki/index.php?title=Api.attributeTypes"/>
				<updated>2013-05-06T22:46:34Z</updated>
		
		<summary type="html">&lt;p&gt;Chris Monson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;syntaxhighlight lang=vbnet&amp;gt;&lt;br /&gt;
Enum AttributeTypes&lt;br /&gt;
	intensity&lt;br /&gt;
	pan&lt;br /&gt;
	tilt&lt;br /&gt;
	colorRed&lt;br /&gt;
	colorGreen&lt;br /&gt;
	colorBlue&lt;br /&gt;
	colorWheel_Secondary&lt;br /&gt;
	strobe&lt;br /&gt;
	gobo&lt;br /&gt;
	gobo_Rotate&lt;br /&gt;
	gobo_Secondary&lt;br /&gt;
	prism&lt;br /&gt;
	prism_Rotate&lt;br /&gt;
	focus&lt;br /&gt;
	beam&lt;br /&gt;
	zoom&lt;br /&gt;
	iris&lt;br /&gt;
	frost&lt;br /&gt;
	shutter&lt;br /&gt;
	pan_Tilt_Speed&lt;br /&gt;
	lamp&lt;br /&gt;
	macro&lt;br /&gt;
	control&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Chris Monson</name></author>	</entry>

	<entry>
		<id>http://www.visualsorcery.com/LightForgeWiki/index.php?title=Api.groups</id>
		<title>Api.groups</title>
		<link rel="alternate" type="text/html" href="http://www.visualsorcery.com/LightForgeWiki/index.php?title=Api.groups"/>
				<updated>2013-05-06T22:34:16Z</updated>
		
		<summary type="html">&lt;p&gt;Chris Monson: /* Methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
=Information=&lt;br /&gt;
&lt;br /&gt;
==Group Paths==&lt;br /&gt;
A group path is a method for specifying a group in the group hierarchy. It is defined by use of a string. &lt;br /&gt;
&lt;br /&gt;
An empty string (&amp;quot;&amp;quot;) will specify the main group. &lt;br /&gt;
&lt;br /&gt;
To specify a child of the main group you use that child's index number ex. &amp;quot;1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note: the indexes are 0 based so fixture 1 in a group is 0, fixture 2 is 1, etc. &lt;br /&gt;
&lt;br /&gt;
To specify a child of a child, you use a comma, and the index of the next child you want to select ex. &amp;quot;1,3&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can continue in this fashion throughout the group hierarchy. If you are looking at something nested deeply it may look like &amp;quot;1,3,0,2,4&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=Methods=&lt;br /&gt;
&lt;br /&gt;
==getAttribute==&lt;br /&gt;
&lt;br /&gt;
'''getAttribute(attribute As [[api.attributeTypes]], groupPath As String) As Integer'''&lt;br /&gt;
&lt;br /&gt;
Returns the value for a specified attribute on a specified group&lt;br /&gt;
Returns -1 if the group can't be found&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
print(api.groups.getAttribute(api.attributeTypes.intensity, &amp;quot;0,0&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==getChildCount==&lt;br /&gt;
'''getChildCount(groupPath As String) As Integer'''&lt;br /&gt;
&lt;br /&gt;
Returns the number of children in a group&lt;br /&gt;
Returns -1 if the group can't be found&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
print(api.groups.getChildCount(&amp;quot;0,0&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==getName==&lt;br /&gt;
'''getName(groupPath As String) As String'''&lt;br /&gt;
&lt;br /&gt;
Returns the name of the requested group&lt;br /&gt;
Returns -1 if the group can't be found&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
print(api.groups.getName(&amp;quot;1,1&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==getProfileName==&lt;br /&gt;
'''getProfileName(groupPath As String) As String'''&lt;br /&gt;
&lt;br /&gt;
Returns the name of the profile in use by the specified group. If this group is not a fixture and does not have a profile this function will return -1.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
print(api.groups.getProfileName(&amp;quot;1,0,3&amp;quot;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==getSelectedGroups==&lt;br /&gt;
'''getSelectedGroups() As String[]'''&lt;br /&gt;
&lt;br /&gt;
Returns a list of group paths for all selected groups. If there are no groups selected then null is returned.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
groupList = api.groups.getSelectedGroups()&lt;br /&gt;
	for group in groupList:&lt;br /&gt;
		print(group)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==releaseAttribute==&lt;br /&gt;
'''releaseAttribute(attribute As [[api.attributeTypes]], groupPath As String)'''&lt;br /&gt;
&lt;br /&gt;
Releases the specified attribute on the specified group.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
api.groups.releaseAttribute(api.attributeTypes.intensity, &amp;quot;0,1&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==releaseGroup==&lt;br /&gt;
'''releaseGroup(groupPath As String)'''&lt;br /&gt;
&lt;br /&gt;
Releases the all attributes on the specified group.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
api.groups.releaseGroup(&amp;quot;1,0&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==setAttribute==&lt;br /&gt;
'''setAttribute(attribute As [[api.attributeTypes]], value As Integer, groupPath As String)'''&lt;br /&gt;
&lt;br /&gt;
Sets the value of an attribute on a specified group.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
api.groups.setAttribute(api.attributeTypes.intensity, 65535, &amp;quot;1,1&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==selectGroup==&lt;br /&gt;
'''selectGroup(groupPath As String)'''&lt;br /&gt;
&lt;br /&gt;
Sets the given group as selected.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
api.groups.selectGroup(&amp;quot;0,1,1,2&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==deselectGroup==&lt;br /&gt;
'''deselectGroup(groupPath As String)'''&lt;br /&gt;
&lt;br /&gt;
Deselects the given group.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
api.groups.deselectGroup(&amp;quot;0,1,1,2&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==clearSelection==&lt;br /&gt;
'''clearSelection()'''&lt;br /&gt;
&lt;br /&gt;
Deselects all selected groups.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
api.groups.clearSelection()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Chris Monson</name></author>	</entry>

	<entry>
		<id>http://www.visualsorcery.com/LightForgeWiki/index.php?title=API</id>
		<title>API</title>
		<link rel="alternate" type="text/html" href="http://www.visualsorcery.com/LightForgeWiki/index.php?title=API"/>
				<updated>2013-05-06T22:23:34Z</updated>
		
		<summary type="html">&lt;p&gt;Chris Monson: /* getBPM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Types=&lt;br /&gt;
&lt;br /&gt;
==api.attributeTypes==&lt;br /&gt;
[[api.attributeTypes]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Classes=&lt;br /&gt;
&lt;br /&gt;
==api.cues==&lt;br /&gt;
Used for working with cues.&lt;br /&gt;
&lt;br /&gt;
[[api.cues]]&lt;br /&gt;
&lt;br /&gt;
==api.groups==&lt;br /&gt;
Used for working with groups.&lt;br /&gt;
&lt;br /&gt;
[[api.groups]]&lt;br /&gt;
&lt;br /&gt;
==api.output==&lt;br /&gt;
Used for getting information about DMX output.&lt;br /&gt;
&lt;br /&gt;
[[api.output]]&lt;br /&gt;
&lt;br /&gt;
=Methods=&lt;br /&gt;
&lt;br /&gt;
==getTime==&lt;br /&gt;
'''getTime() As Double'''&lt;br /&gt;
&lt;br /&gt;
Gets the current playback position.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
print(api.getTime())&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==setTime==&lt;br /&gt;
'''setTime(time As Double)'''&lt;br /&gt;
&lt;br /&gt;
Sets the current playback position to the specified time.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
api.setTime(36.5)&lt;br /&gt;
print(api.getTime())&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==getBPM==&lt;br /&gt;
'''getBPM() As Double'''&lt;br /&gt;
&lt;br /&gt;
Gets the BPM of the current cuelist&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
print(api.getBPM())&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==wait==&lt;br /&gt;
'''wait(seconds As Double)'''&lt;br /&gt;
&lt;br /&gt;
Causes execution to wait for the specified number of seconds.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
api.wait(3.5)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==isPlaying==&lt;br /&gt;
'''isPlaying() As Boolean'''&lt;br /&gt;
&lt;br /&gt;
Checks to see if the timeline is currently playing back.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
if(api.isPlaying()):&lt;br /&gt;
	api.stopPlayback()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==startPlayback==&lt;br /&gt;
'''startPlayback()'''&lt;br /&gt;
&lt;br /&gt;
Starts timeline playback.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
if(api.isPlaying() == False):&lt;br /&gt;
	api.startPlayback()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==stopPlayback==&lt;br /&gt;
'''stopPlayback()'''&lt;br /&gt;
&lt;br /&gt;
Stops timeline playback.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
if(api.isPlaying()):&lt;br /&gt;
	api.stopPlayback()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==NextCue==&lt;br /&gt;
'''nextCue()'''&lt;br /&gt;
&lt;br /&gt;
Advances timeline to the next cue.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
api.nextCue()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PreviousCue==&lt;br /&gt;
'''previousCue()'''&lt;br /&gt;
&lt;br /&gt;
Moves timeline to the previous cue.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
api.previousCue()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Event Handling=&lt;br /&gt;
&lt;br /&gt;
==onInitialize==&lt;br /&gt;
Called when the script is loaded.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
def onInitialize():&lt;br /&gt;
	print(&amp;quot;Script Loaded&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==onDispose==&lt;br /&gt;
Called when the script is being disposed by either it being disabled, or by Lightforge closing.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
def onDispose():&lt;br /&gt;
	print(&amp;quot;Addon Disposing&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==onEdit==&lt;br /&gt;
Called when the script settings are being edited. Editing a script's settings from the Script Settings Dialog is only possible if this function is implemented in your code.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
def onEdit():&lt;br /&gt;
	print(&amp;quot;Settings Edit&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==onExecute==&lt;br /&gt;
Called when this script is specifically executed.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
def onExecute():&lt;br /&gt;
	print(&amp;quot;Script Executed&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==onExecuteAsync==&lt;br /&gt;
Called when this script is specifically executed. Code run from this function is executed asynchronously.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
def onExecuteAsync():&lt;br /&gt;
	print(&amp;quot;Script Executed Asynchronously&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==onStartup==&lt;br /&gt;
Called when Lightforge starts up.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
def onStartup():&lt;br /&gt;
	print(&amp;quot;Lightforge Started&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==onStartupAsync==&lt;br /&gt;
Called when Lightforge starts up. Code run from this function is executed asynchronously.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
def onStartupAsync():&lt;br /&gt;
	print(&amp;quot;Lightforge Started (Async)&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==onPlaybackStart==&lt;br /&gt;
Called when timeline playback has started.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
def onPlaybackStart():&lt;br /&gt;
	print(&amp;quot;Playback Started&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==onPlaybackStop==&lt;br /&gt;
Called when timeline playback has stopped&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
def onPlaybackStop():&lt;br /&gt;
	print(&amp;quot;Playback Stopped&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==onFrameChange==&lt;br /&gt;
Called on every frame change during playback, scrubbing, and time changes.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
def onFrameChange(seconds As Double):&lt;br /&gt;
	print(&amp;quot;Frame Changed &amp;quot; + seconds)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==onShutdown==&lt;br /&gt;
Called when Lightforge is shutting down.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;	&lt;br /&gt;
def onShutdown():&lt;br /&gt;
	print(&amp;quot;Lightforge Shutdown&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==onCuelistChange==&lt;br /&gt;
Called when the current cuelist has been changed.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
def onCuelistChange():&lt;br /&gt;
	print(&amp;quot;Cue List Changed&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==onShowLoaded==&lt;br /&gt;
Called when a new show has been loaded.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
def onShowLoaded():&lt;br /&gt;
	print(&amp;quot;Show Loaded&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Chris Monson</name></author>	</entry>

	<entry>
		<id>http://www.visualsorcery.com/LightForgeWiki/index.php?title=Show_Controls_Panel</id>
		<title>Show Controls Panel</title>
		<link rel="alternate" type="text/html" href="http://www.visualsorcery.com/LightForgeWiki/index.php?title=Show_Controls_Panel"/>
				<updated>2013-02-27T07:07:28Z</updated>
		
		<summary type="html">&lt;p&gt;Chris Monson: Created page with &amp;quot;The Show Controls Panel gives you various functions used to create and run your show.  ==Previous Cue== Moves playback time to the start time of the previous cue.  ==Play Back...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Show Controls Panel gives you various functions used to create and run your show.&lt;br /&gt;
&lt;br /&gt;
==Previous Cue==&lt;br /&gt;
Moves playback time to the start time of the previous cue.&lt;br /&gt;
&lt;br /&gt;
==Play Backward/Pause==&lt;br /&gt;
Starts playing backward from the current position. If currently playing backwards then pause.&lt;br /&gt;
&lt;br /&gt;
==Play/Pause==&lt;br /&gt;
Starts playing forward from the current position. If currently playing forward then pause.&lt;br /&gt;
&lt;br /&gt;
==Pause==&lt;br /&gt;
Pauses playback.&lt;br /&gt;
&lt;br /&gt;
==Next Cue==&lt;br /&gt;
Moves playback time to the start time of the next cue.&lt;br /&gt;
&lt;br /&gt;
==Add Audio==&lt;br /&gt;
Adds an audio file to the timeline.&lt;br /&gt;
&lt;br /&gt;
==Add Cue==&lt;br /&gt;
Creates a cue from all the held values in groups.&lt;br /&gt;
&lt;br /&gt;
==Update Cue==&lt;br /&gt;
Opens a dialog prompting you to either:&lt;br /&gt;
&lt;br /&gt;
'''Update Selected Cue'''&lt;br /&gt;
Add the held values to the current tracking data in the cue.&lt;br /&gt;
&lt;br /&gt;
'''Overwrite Selected Cue'''&lt;br /&gt;
Overwrite the tracking data in the cue with the held values in the groups panel.&lt;br /&gt;
&lt;br /&gt;
==Delete==&lt;br /&gt;
Deletes the selected cues or audio files.&lt;br /&gt;
&lt;br /&gt;
==Crossfade==&lt;br /&gt;
Toggles crossfading on intensity presets, palettes, and showlist changes. &lt;br /&gt;
&lt;br /&gt;
==Keyboard Shortcuts==&lt;br /&gt;
Play/Pause - '''Space Bar'''&lt;br /&gt;
&lt;br /&gt;
Play Backwards - '''Backspace'''&lt;br /&gt;
&lt;br /&gt;
Skip to Next Cue - '''Right Arrow'''&lt;br /&gt;
&lt;br /&gt;
Go to Previous Cue - '''Left Arrow'''&lt;/div&gt;</summary>
		<author><name>Chris Monson</name></author>	</entry>

	<entry>
		<id>http://www.visualsorcery.com/LightForgeWiki/index.php?title=Show_List_Panel</id>
		<title>Show List Panel</title>
		<link rel="alternate" type="text/html" href="http://www.visualsorcery.com/LightForgeWiki/index.php?title=Show_List_Panel"/>
				<updated>2013-02-27T06:54:45Z</updated>
		
		<summary type="html">&lt;p&gt;Chris Monson: /* Rearranging Cuelists= */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Show List panel allows you to create multiple cuelists and move between them in a single show.&lt;br /&gt;
&lt;br /&gt;
==Adding a Cuelist==&lt;br /&gt;
To add a new cuelist, right click on an area of the show list panel that doesn't contain a cuelist, then select &amp;quot;New&amp;quot; from the menu.&lt;br /&gt;
&lt;br /&gt;
==Deleting a Cuelist==&lt;br /&gt;
To delete a cuelist, right click on it and select delete.&lt;br /&gt;
&lt;br /&gt;
==Clearing All Cuelists==&lt;br /&gt;
To clear all cuelists, right click on the show list panel and select &amp;quot;Clear All&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Renaming a Cuelist==&lt;br /&gt;
To rename a cue right click on it and select &amp;quot;Rename&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Rearranging Cuelists==&lt;br /&gt;
To rearrange cuelists, click and drag them to the position you'd like them to occupy.&lt;/div&gt;</summary>
		<author><name>Chris Monson</name></author>	</entry>

	<entry>
		<id>http://www.visualsorcery.com/LightForgeWiki/index.php?title=Timeline_Panel</id>
		<title>Timeline Panel</title>
		<link rel="alternate" type="text/html" href="http://www.visualsorcery.com/LightForgeWiki/index.php?title=Timeline_Panel"/>
				<updated>2013-02-27T05:16:47Z</updated>
		
		<summary type="html">&lt;p&gt;Chris Monson: /* Command Markers */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The timeline panel is your main work space for working with cue timings, audio synchronization and midi show control.&lt;br /&gt;
&lt;br /&gt;
==Time Scales==&lt;br /&gt;
===Time===&lt;br /&gt;
The default time scale in Lightforge is &amp;quot;Time&amp;quot;. This measures your progression through time in hours, minutes, and seconds. &lt;br /&gt;
&lt;br /&gt;
===Beats===&lt;br /&gt;
The Beats time scale allows you to specify a tempo (beats per minute), and number of beats per measure. You can then record your cues and set your timings to this time scale. Adjusting your tempo will automatically scale the playback of your cues and effects to the new tempo. You can enable beats mode by clicking on the &amp;quot;Beats&amp;quot; toggle button in the time section of the Timeline panel. Once selected you can adjust your tempo by clicking the &amp;quot;bpm&amp;quot; button below the &amp;quot;Beats&amp;quot; button&lt;br /&gt;
&lt;br /&gt;
==Cues==&lt;br /&gt;
===Important Concepts===&lt;br /&gt;
By default, cues in Lightforge function in a tracking system. What this means is that for each cue you create the only thing that is being saved is the changes since your last cue. In short, if you turn a light on, it stays on until you tell it to turn off in a later cue. It's important to understand this because there are various positive and potentially negative ramifications to this approach.&lt;br /&gt;
&lt;br /&gt;
'''The Positive:'''&lt;br /&gt;
If you forgot to add something into your show and it's supposed to be in every cue, all you have to do is add it to the first cue, and it will track through the rest of your cues until it's told to do otherwise.&lt;br /&gt;
&lt;br /&gt;
'''The Negative:'''&lt;br /&gt;
If you want to add something to a single cue you will need to remove it in the following cue otherwise it will continue tracking throughout the rest of your show.&lt;br /&gt;
&lt;br /&gt;
In general the tracking approach creates simpler shows, with less to manage. Instead of having to look through every channel on a cue to make an adjustment you only need to deal with what has been changed in that particular cue.&lt;br /&gt;
&lt;br /&gt;
===Cue Length===&lt;br /&gt;
The length of a cue is adjusted by clicking and dragging on either the left or right edge of a cue.&lt;br /&gt;
&lt;br /&gt;
===Fade In===&lt;br /&gt;
You can adjust your fade in time by clicking and dragging on the upper left corner of a cue.&lt;br /&gt;
&lt;br /&gt;
===Fade Out===&lt;br /&gt;
You can adjust your fade out time by clicking and dragging on the upper right corner of a cue.&lt;br /&gt;
&lt;br /&gt;
===Moving Cues===&lt;br /&gt;
To rearrange a cue, click on the middle of the cue and drag it to where you would like it to go. When you release the cue all other cues will snap into position around it.&lt;br /&gt;
&lt;br /&gt;
===Nesting===&lt;br /&gt;
You can nest cues inside one another by dragging a cue below another cue.&lt;br /&gt;
&lt;br /&gt;
===Subdivide===&lt;br /&gt;
Subdivide takes an existing cue, and creates two nested cues inside of itself. You can subdivide a cue by right clicking on it and selecting subdivide.&lt;br /&gt;
&lt;br /&gt;
===Collapse===&lt;br /&gt;
Collapse flattens the nested structure of the selected cue. You can collapse a cue by right clicking on it and selecting collapse.&lt;br /&gt;
&lt;br /&gt;
===Load Held Values===&lt;br /&gt;
Double clicking a cue will copy the cue values back onto the rig in the state they were saved in.&lt;br /&gt;
&lt;br /&gt;
==Cue Types==&lt;br /&gt;
===Hold===&lt;br /&gt;
When playback reaches a cue set as a hold cue playback will stop and wait for the user to start the next cue&lt;br /&gt;
===Follow===&lt;br /&gt;
When playback reaches a follow cue it continues playback.&lt;br /&gt;
===Tracking===&lt;br /&gt;
This is the default cue type, it uses the tracking system to combine the changes made in this cue with changes made in previous cues.&lt;br /&gt;
===Non-Tracking===&lt;br /&gt;
Non-Tracking cues take a snapshot of the overall look created by all cues at this point in time. A non-tracking cue will maintain it's values regardless of changes made to cues before it.&lt;br /&gt;
&lt;br /&gt;
==Audio==&lt;br /&gt;
The audio track allows you to load in audio files for synchronizing cues to music. Audio files are manipulated in the same manner as cues with the exception of there being no fade ins or outs on audio tracks. Audio tracks do not rescale on changing of tempo in beats mode.&lt;br /&gt;
&lt;br /&gt;
==Command Markers==&lt;br /&gt;
Command markers allow you to execute commands as playback passes a certain point in time.&lt;br /&gt;
&lt;br /&gt;
===Positioning Modes===&lt;br /&gt;
Command markers have two different positioning modes. These are chosen individually on markers by right clicking the marker and checking or unchecking “Relative”.&lt;br /&gt;
&lt;br /&gt;
====Relative Positioning====&lt;br /&gt;
When set to relative (default), changes in cue timings will automatically shift marker positions with the cues.&lt;br /&gt;
====Absolute Positioning====&lt;br /&gt;
When set to absolute, cue timing will not affect markers.&lt;br /&gt;
&lt;br /&gt;
===Command Marker Types===&lt;br /&gt;
&lt;br /&gt;
====Go To Time====&lt;br /&gt;
Goes to the specified time and continues playback.&lt;br /&gt;
====Pause====&lt;br /&gt;
Pauses at the marker time.&lt;br /&gt;
&lt;br /&gt;
====Midi Show Control====&lt;br /&gt;
Executes a [[Midi Show Control]] command.&lt;br /&gt;
&lt;br /&gt;
==Keyboard And Mouse Shortcuts==&lt;br /&gt;
&lt;br /&gt;
Move Timeline - '''Middle Mouse Drag''' or '''M + Left Mouse Drag'''&lt;br /&gt;
&lt;br /&gt;
Zoom - '''Mouse Wheel''' or '''+''' and '''-'''&lt;br /&gt;
&lt;br /&gt;
Return to Start - '''Home'''&lt;br /&gt;
&lt;br /&gt;
Go To End - '''End'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Play/Pause - '''Space Bar'''&lt;br /&gt;
&lt;br /&gt;
Play Backwards - '''Backspace'''&lt;br /&gt;
&lt;br /&gt;
Skip to Next Cue - '''Right Arrow'''&lt;br /&gt;
&lt;br /&gt;
Go to Previous Cue - '''Left Arrow'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Toggle Follow/Hold - '''F'''&lt;br /&gt;
&lt;br /&gt;
Toggle Tracking/Non-Tracking - '''T'''&lt;br /&gt;
&lt;br /&gt;
Subdivide - '''S'''&lt;br /&gt;
&lt;br /&gt;
Delete Cues/Audio - '''Delete'''&lt;br /&gt;
&lt;br /&gt;
Select All - '''CTRL + A'''&lt;br /&gt;
&lt;br /&gt;
Select None - ''' CTRL + D'''&lt;/div&gt;</summary>
		<author><name>Chris Monson</name></author>	</entry>

	<entry>
		<id>http://www.visualsorcery.com/LightForgeWiki/index.php?title=Profile_Node_System</id>
		<title>Profile Node System</title>
		<link rel="alternate" type="text/html" href="http://www.visualsorcery.com/LightForgeWiki/index.php?title=Profile_Node_System"/>
				<updated>2013-02-24T18:04:32Z</updated>
		
		<summary type="html">&lt;p&gt;Chris Monson: /* Node Types */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Profile Node System is a means of translating Lightforge's input values into values compatible with whatever lighting fixtures you may be using.&lt;br /&gt;
&lt;br /&gt;
==Nodes==&lt;br /&gt;
A node is a container that executes predefined function on the data passing through it's inputs and outputs (called pins). A node system works by allowing you to feed a flow of information from one node to the next in order to make adjustments to the data flowing through the system. &lt;br /&gt;
&lt;br /&gt;
A simple example of this is to calculate 3 + 6. You can calculate this with the following node setup:&lt;br /&gt;
&lt;br /&gt;
      [Value Node @ 3]&lt;br /&gt;
                      \&lt;br /&gt;
                       \&lt;br /&gt;
                        [Add Node]----[Output = 9]&lt;br /&gt;
                       /&lt;br /&gt;
                      /&lt;br /&gt;
      [Value Node @ 6]&lt;br /&gt;
&lt;br /&gt;
The value of 3 flows from the top value node into the add node. The value of 6 flows from the bottom value node into the add node. The add node adds Input 1 + Input 2, and the resulting value of 9 flows out the add node.&lt;br /&gt;
&lt;br /&gt;
==Pins==&lt;br /&gt;
&lt;br /&gt;
==Pin Formats==&lt;br /&gt;
Each pin has a defined format type that it can accept. The formats may change based on what is connected to certain pins in the node. Pin types include the following.&lt;br /&gt;
&lt;br /&gt;
===8 Bit===&lt;br /&gt;
8 Bit pins give you a 0 to 255 range of whole values.&lt;br /&gt;
&lt;br /&gt;
===16 Bit===&lt;br /&gt;
16 Bit pins give you a 0 to 65535 range of whole values&lt;br /&gt;
&lt;br /&gt;
===Decimal===&lt;br /&gt;
Decimal pins are a 64-bit (8-byte) double-precision floating-point numbers ranging in value from -1.79769313486231570E+308 through -4.94065645841246544E-324 for negative values and from 4.94065645841246544E-324 through 1.79769313486231570E+308 for positive values.&lt;br /&gt;
&lt;br /&gt;
===Color===&lt;br /&gt;
Color Pins accept and output a 24bit RGB color structure.&lt;br /&gt;
&lt;br /&gt;
===Auto Detect===&lt;br /&gt;
Auto Detect pins will turn into whatever format type you connect to them.&lt;br /&gt;
&lt;br /&gt;
==Working With Nodes==&lt;br /&gt;
&lt;br /&gt;
===Adding Nodes===&lt;br /&gt;
To add a node right click on an empty area of the canvas and select the type of node you would like to add.&lt;br /&gt;
&lt;br /&gt;
===Moving Nodes===&lt;br /&gt;
To move a node click and drag it to the position you'd like it to be.&lt;br /&gt;
&lt;br /&gt;
===Deleting Nodes===&lt;br /&gt;
To delete a node right click on it and press delete on the context menu.&lt;br /&gt;
&lt;br /&gt;
===Connecting Nodes===&lt;br /&gt;
To connect node inputs and outputs click and drag from the output of the first node to the input of the second. Multiple connections can be made from one output, but only one connection can go to any input.&lt;br /&gt;
&lt;br /&gt;
===Disconnecting Nodes===&lt;br /&gt;
To disconnect a node connection click on the input that the connection is on and drag it off the pin and release it.&lt;br /&gt;
&lt;br /&gt;
==Node Types==&lt;/div&gt;</summary>
		<author><name>Chris Monson</name></author>	</entry>

	<entry>
		<id>http://www.visualsorcery.com/LightForgeWiki/index.php?title=DMX_Channel</id>
		<title>DMX Channel</title>
		<link rel="alternate" type="text/html" href="http://www.visualsorcery.com/LightForgeWiki/index.php?title=DMX_Channel"/>
				<updated>2013-02-24T17:42:41Z</updated>
		
		<summary type="html">&lt;p&gt;Chris Monson: Created page with &amp;quot;A DMX Channel is a value used to control lighting systems via the DMX Lighting Protocol. Each DMX channel has a value range of 0 to 255.&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A DMX Channel is a value used to control lighting systems via the [[DMX]] Lighting Protocol. Each DMX channel has a value range of 0 to 255.&lt;/div&gt;</summary>
		<author><name>Chris Monson</name></author>	</entry>

	<entry>
		<id>http://www.visualsorcery.com/LightForgeWiki/index.php?title=DMX_Universe</id>
		<title>DMX Universe</title>
		<link rel="alternate" type="text/html" href="http://www.visualsorcery.com/LightForgeWiki/index.php?title=DMX_Universe"/>
				<updated>2013-02-24T17:39:12Z</updated>
		
		<summary type="html">&lt;p&gt;Chris Monson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A DMX universe represents 512 discrete [[DMX Channel]]s that lighting fixtures can be addressed to. If you are using traditional DMX, a DMX Universe is equivalent to one DMX output. In Lightforge you can create as many universes as you would like through the [[Settings Menu]].&lt;/div&gt;</summary>
		<author><name>Chris Monson</name></author>	</entry>

	<entry>
		<id>http://www.visualsorcery.com/LightForgeWiki/index.php?title=Fixture_Dialog</id>
		<title>Fixture Dialog</title>
		<link rel="alternate" type="text/html" href="http://www.visualsorcery.com/LightForgeWiki/index.php?title=Fixture_Dialog"/>
				<updated>2013-02-24T17:21:50Z</updated>
		
		<summary type="html">&lt;p&gt;Chris Monson: /* Address */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Fixture Dialog is used to patch lighting fixtures to channels and give you the ability to control them.&lt;br /&gt;
&lt;br /&gt;
==Profiles==&lt;br /&gt;
A profile is a system used to convert the information that you input into Lightforge into something that you lighting fixtures can process. There are two methods of creating profiles in Lightforge, node profiles, and scripted profiles.&lt;br /&gt;
&lt;br /&gt;
===Creating Profiles===&lt;br /&gt;
&lt;br /&gt;
[[Profile Node System]]&lt;br /&gt;
&lt;br /&gt;
[[Profile Python Scripting]]&lt;br /&gt;
&lt;br /&gt;
==Name==&lt;br /&gt;
The name is used to define what your fixture will be labeled throughout Lightforge.&lt;br /&gt;
&lt;br /&gt;
==Universe==&lt;br /&gt;
This is the [[DMX Universe]] that your fixture will be assigned to.&lt;br /&gt;
&lt;br /&gt;
==Address==&lt;br /&gt;
This is the [[DMX Channel]] that your fixture will be assigned to.&lt;br /&gt;
&lt;br /&gt;
==Use Multiple Addresses==&lt;br /&gt;
This allows you to add multiple addresses or ranges or addresses to a single Lightforge fixture. This is useful for situations where you have multiple real fixtures that you would like to be assigned to a single fixture in Lightforge.&lt;br /&gt;
&lt;br /&gt;
==Count==&lt;br /&gt;
The count option gives you the ability to add multiple sequentially addressed lighting fixtures of the same type.&lt;br /&gt;
&lt;br /&gt;
==Offset==&lt;br /&gt;
This gives you the option to leave a specified number of empty channels between the sequential fixtures specified in &amp;quot;Count&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Channel Panel==&lt;br /&gt;
The Channel Panel shows how the addresses the selected [[DMX Universe]] are being used.&lt;br /&gt;
&lt;br /&gt;
'''Color Coding:'''&lt;br /&gt;
&lt;br /&gt;
'''White:''' Addresses that are available.&lt;br /&gt;
&lt;br /&gt;
'''Gray:''' Addresses that are taken by other fixtures.&lt;br /&gt;
&lt;br /&gt;
'''Cyan:''' The addresses that your current selection is occupying.&lt;br /&gt;
&lt;br /&gt;
'''Red:''' Addresses that can't be patched because of overlapping channels.&lt;/div&gt;</summary>
		<author><name>Chris Monson</name></author>	</entry>

	</feed>