<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.fightorder.net/wiki/index.php?action=history&amp;feed=atom&amp;title=Chili%3ATutorial_Command_and_Build_Commands</id>
	<title>Chili:Tutorial Command and Build Commands - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://www.fightorder.net/wiki/index.php?action=history&amp;feed=atom&amp;title=Chili%3ATutorial_Command_and_Build_Commands"/>
	<link rel="alternate" type="text/html" href="https://www.fightorder.net/wiki/index.php?title=Chili:Tutorial_Command_and_Build_Commands&amp;action=history"/>
	<updated>2026-04-21T04:02:42Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.44.2</generator>
	<entry>
		<id>https://www.fightorder.net/wiki/index.php?title=Chili:Tutorial_Command_and_Build_Commands&amp;diff=684&amp;oldid=prev</id>
		<title>Qrow: 1 revision imported</title>
		<link rel="alternate" type="text/html" href="https://www.fightorder.net/wiki/index.php?title=Chili:Tutorial_Command_and_Build_Commands&amp;diff=684&amp;oldid=prev"/>
		<updated>2025-11-14T05:22:17Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 22:22, 13 November 2025&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Qrow</name></author>
	</entry>
	<entry>
		<id>https://www.fightorder.net/wiki/index.php?title=Chili:Tutorial_Command_and_Build_Commands&amp;diff=683&amp;oldid=prev</id>
		<title>Interwiki&gt;Sunspot: /* initializing the widget */</title>
		<link rel="alternate" type="text/html" href="https://www.fightorder.net/wiki/index.php?title=Chili:Tutorial_Command_and_Build_Commands&amp;diff=683&amp;oldid=prev"/>
		<updated>2013-07-14T16:01:50Z</updated>

		<summary type="html">&lt;p&gt;&lt;span class=&quot;autocomment&quot;&gt;initializing the widget&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== Commands and Build bar ==&lt;br /&gt;
=== Preparation ===&lt;br /&gt;
We are stepping it up a notch.  We can all agree that the stock GUI for commands and building isn&amp;#039;t really all that great.  Good thing is we can improve on this.  Following is not a perfect sollution since it doesn&amp;#039;t handle pagination, but it will get you a long way getting you started for advanced stuff.  For this tutorial you will only need one lua script but it will have quite a bit of content.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt; &lt;br /&gt;
- LuaUI\widgets\gui_chili_commandwindow.lua&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== File header ===&lt;br /&gt;
You open up with the regular info and imports that you are going to use thru the script.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
function widget:GetInfo()&lt;br /&gt;
	return {&lt;br /&gt;
		name		= &amp;quot;command list window&amp;quot;,&lt;br /&gt;
		desc		= &amp;quot;ChiliUi window that contains all the commands a unit has&amp;quot;,&lt;br /&gt;
		author		= &amp;quot;Sunspot&amp;quot;,&lt;br /&gt;
		date		= &amp;quot;2011-06-15&amp;quot;,&lt;br /&gt;
		license     = &amp;quot;GNU GPL v2&amp;quot;,&lt;br /&gt;
		layer		= math.huge,&lt;br /&gt;
		enabled   	= true,&lt;br /&gt;
		handler		= true,&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
-- INCLUDES&lt;br /&gt;
VFS.Include(&amp;quot;LuaRules/Gadgets/Includes/utilities.lua&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
-- CONSTANTS&lt;br /&gt;
local MAXBUTTONSONROW = 4&lt;br /&gt;
local COMMANDSTOEXCLUDE = {&amp;quot;TimeWait&amp;quot;,&amp;quot;DeathWait&amp;quot;,&amp;quot;SquadWait&amp;quot;,&amp;quot;GatherWait&amp;quot;,&amp;quot;Load units&amp;quot;}&lt;br /&gt;
local Chili&lt;br /&gt;
&lt;br /&gt;
-- MEMBERS&lt;br /&gt;
local x&lt;br /&gt;
local y&lt;br /&gt;
local commandWindow&lt;br /&gt;
local stateCommandWindow&lt;br /&gt;
local buildCommandWindow&lt;br /&gt;
local updateRequired = true&lt;br /&gt;
&lt;br /&gt;
-- CONTROLS&lt;br /&gt;
local spGetActiveCommand 	= Spring.GetActiveCommand&lt;br /&gt;
local spGetActiveCmdDesc 	= Spring.GetActiveCmdDesc&lt;br /&gt;
local spGetSelectedUnits    = Spring.GetSelectedUnits&lt;br /&gt;
local spSendCommands        = Spring.SendCommands&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You&amp;#039;ll notice a lot of variables and controls.  They will all get a place during the further script design and explained in detail.  Notice as well that this widgets GetInfo has an extra option (handler = true).  This is needed so Spring.SendCommands can execute.  It&amp;#039;s a common mistake to omit that option with all consequences and frustrations that follow.&lt;br /&gt;
&lt;br /&gt;
=== initializing the widget ===&lt;br /&gt;
What we are going to do, is remove the stock command bar and build bar ui together with the left bottom tooltip.  Next we are going to define 3 simple Chili Controls to seperate the command, status command and build commands in.  To keep those controls nicely together we merge them in one window.  Following code will do this.  I&amp;#039;ll explain it more in detail since it has a few important parts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
local function CleanStockUi()&lt;br /&gt;
	widgetHandler:ConfigLayoutHandler(DummyHandler)&lt;br /&gt;
	Spring.ForceLayoutUpdate()&lt;br /&gt;
	spSendCommands({&amp;quot;tooltip 0&amp;quot;})&lt;br /&gt;
	spSendCommands(&amp;quot;resbar 0&amp;quot;)&lt;br /&gt;
	spSendCommands({&amp;quot;console 0&amp;quot;})&lt;br /&gt;
	spSendCommands({&amp;quot;clock 0&amp;quot;})&lt;br /&gt;
	spSendCommands({&amp;quot;fps 0&amp;quot;})&lt;br /&gt;
	spSendCommands({&amp;quot;info 0&amp;quot;})&lt;br /&gt;
	spSendCommands({&amp;quot;speed 0&amp;quot;})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function widget:Initialize()&lt;br /&gt;
	CleanStockUi()&lt;br /&gt;
	&lt;br /&gt;
	if (not WG.Chili) then&lt;br /&gt;
		widgetHandler:RemoveWidget()&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	Chili = WG.Chili&lt;br /&gt;
	local screen0 = Chili.Screen0&lt;br /&gt;
		&lt;br /&gt;
	commandWindow = Chili.Control:New{&lt;br /&gt;
		x = 0,&lt;br /&gt;
		y = 0,&lt;br /&gt;
		width = &amp;quot;100%&amp;quot;,&lt;br /&gt;
		height = &amp;quot;40%&amp;quot;,&lt;br /&gt;
		xstep = 1,&lt;br /&gt;
		ystep = 1,&lt;br /&gt;
		draggable = false,&lt;br /&gt;
		resizable = false,&lt;br /&gt;
		dragUseGrip = false,		&lt;br /&gt;
		children = {},&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	stateCommandWindow = Chili.Control:New{&lt;br /&gt;
		x = 0,&lt;br /&gt;
		y = &amp;quot;40%&amp;quot;,&lt;br /&gt;
		width = &amp;quot;100%&amp;quot;,&lt;br /&gt;
		height = &amp;quot;20%&amp;quot;,&lt;br /&gt;
		xstep = 1,&lt;br /&gt;
		ystep = 1,&lt;br /&gt;
		draggable = false,&lt;br /&gt;
		resizable = false,&lt;br /&gt;
		dragUseGrip = false,		&lt;br /&gt;
		children = {},&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	buildCommandWindow = Chili.Control:New{&lt;br /&gt;
		x = 0,&lt;br /&gt;
		y = &amp;quot;60%&amp;quot;,&lt;br /&gt;
		width = &amp;quot;100%&amp;quot;,&lt;br /&gt;
		height = &amp;quot;40%&amp;quot;,&lt;br /&gt;
		xstep = 1,&lt;br /&gt;
		ystep = 1,&lt;br /&gt;
		draggable = false,&lt;br /&gt;
		resizable = false,&lt;br /&gt;
		dragUseGrip = false,		&lt;br /&gt;
		children = {},&lt;br /&gt;
	}		&lt;br /&gt;
	&lt;br /&gt;
	window0 = Chili.Window:New{&lt;br /&gt;
		x = &amp;#039;50%&amp;#039;,&lt;br /&gt;
		y = &amp;#039;15%&amp;#039;,	&lt;br /&gt;
		dockable = true,&lt;br /&gt;
		parent = screen0,&lt;br /&gt;
		caption = &amp;quot;&amp;quot;,&lt;br /&gt;
		draggable = true,&lt;br /&gt;
		resizable = true,&lt;br /&gt;
		dragUseGrip = true,&lt;br /&gt;
		clientWidth = 400,&lt;br /&gt;
		clientHeight = 200,&lt;br /&gt;
		backgroundColor = {0,0,0,1},&lt;br /&gt;
		skinName  = &amp;quot;DarkGlass&amp;quot;,		&lt;br /&gt;
		children = {commandWindow,stateCommandWindow,buildCommandWindow},&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function widget:Shutdown()&lt;br /&gt;
  widgetHandler:ConfigLayoutHandler(nil)&lt;br /&gt;
  Spring.ForceLayoutUpdate()&lt;br /&gt;
  spSendCommands({&amp;quot;tooltip 1&amp;quot;})&lt;br /&gt;
  spSendCommands(&amp;quot;resbar 1&amp;quot;)&lt;br /&gt;
  spSendCommands({&amp;quot;console 1&amp;quot;})&lt;br /&gt;
  spSendCommands({&amp;quot;clock 1&amp;quot;})&lt;br /&gt;
  spSendCommands({&amp;quot;fps 1&amp;quot;})&lt;br /&gt;
  spSendCommands({&amp;quot;info 1&amp;quot;})&lt;br /&gt;
  spSendCommands({&amp;quot;speed 1&amp;quot;})&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You&amp;#039;ll find on top here the CleanStockUi() local function.  This is a helper function I made to clean up nearly all of the stock ui delivered with spring.  The DummyLayout is a handler that can be found in layouts.lua delivered with spring.  You&amp;#039;ll notice in a lot of mods that people write their own LayoutHandler, I did so to at first.  But after some discover work I found the DummyLayout written by the spring devs and it&amp;#039;s clearly better to use theirs.  I got rid of most stock stuff, except the minimap, that seems to serve a special function or the command is unknown to me to get rid of.&lt;br /&gt;
&lt;br /&gt;
Now with the stock ui gone we create 3 chili controls and group them in one seperate window.  We also make sure the 3 controls resize together with the group window by using relative Y coordinates.  Put resize on false except the group window.  Last we put the shutdown method to clean up everything we have done incase something goes wrong.&lt;br /&gt;
&lt;br /&gt;
=== On unit selection ... load the commands ===&lt;br /&gt;
Once you select one or more units the commands in the controls need to be refreshed, following code will do this for you.&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
function widget:CommandsChanged()&lt;br /&gt;
	if DEBUG then Spring.Echo(&amp;quot;commandChanged called&amp;quot;) end&lt;br /&gt;
	updateRequired = true&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function widget:DrawScreen()&lt;br /&gt;
    if updateRequired then&lt;br /&gt;
        updateRequired = false&lt;br /&gt;
		loadPanel()&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These widget commands serve to detect if commands are changed and if they are they will flag that on the next redraw the panel (being the 3 controls in our case) needs to be redrawn.  I&amp;#039;m told this is the standard way of doing things and quite frankly it works , so this is once again just copy paste code you&amp;#039;ll find in most chili scripts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
function loadPanel()&lt;br /&gt;
	resetWindow(commandWindow)&lt;br /&gt;
	resetWindow(stateCommandWindow)&lt;br /&gt;
	resetWindow(buildCommandWindow)&lt;br /&gt;
	local commands = Spring.GetActiveCmdDescs()&lt;br /&gt;
	commands = filterUnwanted(commands)&lt;br /&gt;
	table.sort(commands,function(x,y) return x.action &amp;lt; y.action end)&lt;br /&gt;
	for cmdid, cmd in pairs(commands) do&lt;br /&gt;
		rowcount = createMyButton(commands[cmdid]) &lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function resetWindow(container)&lt;br /&gt;
	container:ClearChildren()&lt;br /&gt;
	container.xstep = 1&lt;br /&gt;
	container.ystep = 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function filterUnwanted(commands)&lt;br /&gt;
	local uniqueList = {}&lt;br /&gt;
	if DEBUG then Spring.Echo(&amp;quot;Total commands &amp;quot;, #commands) end&lt;br /&gt;
	if not(#commands == 0)then&lt;br /&gt;
		j = 1&lt;br /&gt;
		for _, cmd in ipairs(commands) do&lt;br /&gt;
			if DEBUG then Spring.Echo(&amp;quot;Adding command &amp;quot;, cmd.action) end&lt;br /&gt;
			if not table.contains(COMMANDSTOEXCLUDE,cmd.action) then&lt;br /&gt;
				uniqueList[j] = cmd&lt;br /&gt;
				j = j + 1&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return uniqueList&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We start of by resetting the old contents of the controls.  Each control has also an x and y variable to keep track where the next object will come, since we removed everything well we reset these as well.&lt;br /&gt;
&lt;br /&gt;
you&amp;#039;ll notice an array COMMANDSTOEXCLUDE that we initialised at the start of the script.  We use this to remove commands , that are not appropriate for the mod you are making. You will also see a method table.contains, this is a method I created myself and is contained in utilities.lua.  It has following code, I&amp;#039;m not sure if it&amp;#039;s really performant or if there is a better way but it works.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
function table.contains(table, element)   &lt;br /&gt;
	for i=1, #table do     &lt;br /&gt;
		if table[i] == element then       &lt;br /&gt;
			return true     &lt;br /&gt;
		end   &lt;br /&gt;
	end   &lt;br /&gt;
	return false &lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With Spring.GetActiveCmdDescs()&lt;br /&gt;
 we grab all the commands that are currently active in the selection.  Then we filter the unwanted commands out of that list and we sort them by actionname.  This to keep most of the commands on the same place when we select multiple units with different commands.  This not to confuse the players who are going to use your gui.  It&amp;#039;s just sane design.  Following we loop over the commands and create buttons for them in all the windows.  The real juicy part of the script&lt;br /&gt;
&lt;br /&gt;
=== Forging the buttons ===&lt;br /&gt;
You could do several things with buttons, put images on them, let them cycle images for state commands or just plain old text.  For this tutorial I&amp;#039;ll show you how to put text buttons for state and regular commands.  And put images on build commands.  We can put most of this code in one method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
function createMyButton(cmd)&lt;br /&gt;
	if(type(cmd) == &amp;#039;table&amp;#039;)then&lt;br /&gt;
		buttontext, container, isState, isBuild, texture = findButtonData(cmd)&lt;br /&gt;
&lt;br /&gt;
		local result = container.xstep % MAXBUTTONSONROW&lt;br /&gt;
		container.xstep = container.xstep + 1&lt;br /&gt;
		local increaseRow = false&lt;br /&gt;
		if(result==0)then&lt;br /&gt;
			result = MAXBUTTONSONROW&lt;br /&gt;
			increaseRow = true&lt;br /&gt;
		end	&lt;br /&gt;
&lt;br /&gt;
		&lt;br /&gt;
		local color = {0,0,0,1}&lt;br /&gt;
		local button = Chili.Button:New {&lt;br /&gt;
			parent = container,&lt;br /&gt;
			x = 80 * (result-1),&lt;br /&gt;
			y = 38 * (container.ystep-1),&lt;br /&gt;
			padding = {5, 5, 5, 5},&lt;br /&gt;
			margin = {0, 0, 0, 0},&lt;br /&gt;
			minWidth = 40,&lt;br /&gt;
			minHeight = 40,&lt;br /&gt;
			caption = buttontext,&lt;br /&gt;
			isDisabled = false,&lt;br /&gt;
			cmdid = cmd.id,&lt;br /&gt;
			OnMouseDown = {ClickFunc},&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		if texture then&lt;br /&gt;
			if DEBUG then Spring.Echo(&amp;quot;texture&amp;quot;,texture) end&lt;br /&gt;
			button:Resize(80,80)&lt;br /&gt;
			image= Chili.Image:New {&lt;br /&gt;
				width=&amp;quot;100%&amp;quot;;&lt;br /&gt;
				height=&amp;quot;90%&amp;quot;;&lt;br /&gt;
				y=&amp;quot;6%&amp;quot;;&lt;br /&gt;
				keepAspect = true,	--isState;&lt;br /&gt;
				file = texture;&lt;br /&gt;
				parent = button;&lt;br /&gt;
			}		&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		if(increaseRow)then&lt;br /&gt;
			container.ystep = container.ystep+1&lt;br /&gt;
		end		&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The button creation method , recieves a cmd from the cmd array we filtered earlier.  Now for some reason the last command isn&amp;#039;t an array but just a number so we&amp;#039;ll have to write a check for that, not to crash our script.  next we will need information from the given command.  We have to determine if it&amp;#039;s a regular command, state command or build command.  It is also important to know what the content of the button will be, for state commands we want to know the text of the state we are in, for build icons we want buildpics.  The buildpic to use is basicly the name of the unit file with a #- in front.  You can see in the findButtonData we concatanate this and put it in the texture var.  We return all that info back to the createbutton method.&lt;br /&gt;
&lt;br /&gt;
After we have all the info we use a bit of XY math to determine where the button will be put.  I&amp;#039;m not going to deep into this cause I suck at math explainations.  But you&amp;#039;ll figure it out do take notice of the constant MAXBUTTONSONROW, we intitialised this at the start of the script.  The following part is where we create the button.  The captiontext is the text you will see on the button.  There is also one more important part.  OnMouseDown = {ClickFunc} , this tells what method has to be performed once you go onMouseDown on the button.  Think of it as a onActionPerformed of a JAVA button.  Here is the code that gets executed once you press it&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
function ClickFunc(chiliButton, x, y, button, mods) &lt;br /&gt;
	local index = Spring.GetCmdDescIndex(chiliButton.cmdid)&lt;br /&gt;
	if (index) then&lt;br /&gt;
		local left, right = (button == 1), (button == 3)&lt;br /&gt;
		local alt, ctrl, meta, shift = mods.alt, mods.ctrl, mods.meta, mods.shift&lt;br /&gt;
&lt;br /&gt;
		if DEBUG then Spring.Echo(&amp;quot;active command set to &amp;quot;, chiliButton.cmdid) end&lt;br /&gt;
		Spring.SetActiveCommand(index, button, left, right, alt, ctrl, meta, shift)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Basicly we get the current mouseState and then decide if an alt, shift or ctrl button is pressed as well, then we decide if the left or right button is pressed and set the next active command that should occure.  The command to be exectued is set on the button when we created it in cmdid.  Carrying on from the createbutton method, you&amp;#039;ll see that we check if a texture was returned from the cmd info method earlier.  This would mean we have a build command, and if so you&amp;#039;ll see we attach an image to the button.  The last line is still a bit of XY math to determine if next time we&amp;#039;ll have to switch to another row by increasing the Y on the current container, who was given to the createbutton method when we called it.&lt;br /&gt;
&lt;br /&gt;
=== Final script ===&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
function widget:GetInfo()&lt;br /&gt;
	return {&lt;br /&gt;
		name		= &amp;quot;command list window&amp;quot;,&lt;br /&gt;
		desc		= &amp;quot;ChiliUi window that contains all the commands a unit has&amp;quot;,&lt;br /&gt;
		author		= &amp;quot;Sunspot&amp;quot;,&lt;br /&gt;
		date		= &amp;quot;2011-06-15&amp;quot;,&lt;br /&gt;
		license     = &amp;quot;GNU GPL v2&amp;quot;,&lt;br /&gt;
		layer		= math.huge,&lt;br /&gt;
		enabled   	= true,&lt;br /&gt;
		handler		= true,&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
-- INCLUDES&lt;br /&gt;
VFS.Include(&amp;quot;LuaRules/Gadgets/Includes/utilities.lua&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
-- CONSTANTS&lt;br /&gt;
local MAXBUTTONSONROW = 3&lt;br /&gt;
local COMMANDSTOEXCLUDE = {&amp;quot;timewait&amp;quot;,&amp;quot;deathwait&amp;quot;,&amp;quot;squadwait&amp;quot;,&amp;quot;gatherwait&amp;quot;,&amp;quot;loadonto&amp;quot;,&amp;quot;nextmenu&amp;quot;,&amp;quot;prevmenu&amp;quot;}&lt;br /&gt;
local Chili&lt;br /&gt;
&lt;br /&gt;
-- MEMBERS&lt;br /&gt;
local x&lt;br /&gt;
local y&lt;br /&gt;
local imageDir = &amp;#039;LuaUI/Images/commands/&amp;#039;&lt;br /&gt;
local commandWindow&lt;br /&gt;
local stateCommandWindow&lt;br /&gt;
local buildCommandWindow&lt;br /&gt;
local updateRequired = true&lt;br /&gt;
&lt;br /&gt;
-- CONTROLS&lt;br /&gt;
local spGetActiveCommand 	= Spring.GetActiveCommand&lt;br /&gt;
local spGetActiveCmdDesc 	= Spring.GetActiveCmdDesc&lt;br /&gt;
local spGetSelectedUnits    = Spring.GetSelectedUnits&lt;br /&gt;
local spSendCommands        = Spring.SendCommands&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-- SCRIPT FUNCTIONS&lt;br /&gt;
function LayoutHandler(xIcons, yIcons, cmdCount, commands)&lt;br /&gt;
	widgetHandler.commands   = commands&lt;br /&gt;
	widgetHandler.commands.n = cmdCount&lt;br /&gt;
	widgetHandler:CommandsChanged()&lt;br /&gt;
	local reParamsCmds = {}&lt;br /&gt;
	local customCmds = {}&lt;br /&gt;
&lt;br /&gt;
	return &amp;quot;&amp;quot;, xIcons, yIcons, {}, customCmds, {}, {}, {}, {}, reParamsCmds, {[1337]=9001}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function ClickFunc(chiliButton, x, y, button, mods) &lt;br /&gt;
	local index = Spring.GetCmdDescIndex(chiliButton.cmdid)&lt;br /&gt;
	if (index) then&lt;br /&gt;
		local left, right = (button == 1), (button == 3)&lt;br /&gt;
		local alt, ctrl, meta, shift = mods.alt, mods.ctrl, mods.meta, mods.shift&lt;br /&gt;
&lt;br /&gt;
		if DEBUG then Spring.Echo(&amp;quot;active command set to &amp;quot;, chiliButton.cmdid) end&lt;br /&gt;
		Spring.SetActiveCommand(index, button, left, right, alt, ctrl, meta, shift)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Returns the caption, parent container and commandtype of the button	&lt;br /&gt;
function findButtonData(cmd)&lt;br /&gt;
	local isState = (cmd.type == CMDTYPE.ICON_MODE and #cmd.params &amp;gt; 1)&lt;br /&gt;
	local isBuild = (cmd.id &amp;lt; 0)	&lt;br /&gt;
	local buttontext = &amp;quot;&amp;quot;&lt;br /&gt;
	local container&lt;br /&gt;
	local texture = nil&lt;br /&gt;
	if not isState and not isBuild then&lt;br /&gt;
		buttontext = cmd.name&lt;br /&gt;
		container = commandWindow&lt;br /&gt;
	elseif isState then&lt;br /&gt;
		local indexChoice = cmd.params[1] + 2&lt;br /&gt;
		buttontext = cmd.params[indexChoice]&lt;br /&gt;
		container = stateCommandWindow&lt;br /&gt;
	else&lt;br /&gt;
		container = buildCommandWindow&lt;br /&gt;
		texture = &amp;#039;#&amp;#039;..-cmd.id&lt;br /&gt;
	end&lt;br /&gt;
	return buttontext, container, isState, isBuild, texture	&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function createMyButton(cmd)&lt;br /&gt;
	if(type(cmd) == &amp;#039;table&amp;#039;)then&lt;br /&gt;
		buttontext, container, isState, isBuild, texture = findButtonData(cmd)&lt;br /&gt;
&lt;br /&gt;
		local result = container.xstep % MAXBUTTONSONROW&lt;br /&gt;
		container.xstep = container.xstep + 1&lt;br /&gt;
		local increaseRow = false&lt;br /&gt;
		if(result==0)then&lt;br /&gt;
			result = MAXBUTTONSONROW&lt;br /&gt;
			increaseRow = true&lt;br /&gt;
		end	&lt;br /&gt;
&lt;br /&gt;
		&lt;br /&gt;
		local color = {0,0,0,1}&lt;br /&gt;
		local button = Chili.Button:New {&lt;br /&gt;
			parent = container,&lt;br /&gt;
			x = 80 * (result-1),&lt;br /&gt;
			y = 38 * (container.ystep-1),&lt;br /&gt;
			padding = {5, 5, 5, 5},&lt;br /&gt;
			margin = {0, 0, 0, 0},&lt;br /&gt;
			minWidth = 40,&lt;br /&gt;
			minHeight = 40,&lt;br /&gt;
			caption = buttontext,&lt;br /&gt;
			isDisabled = false,&lt;br /&gt;
			cmdid = cmd.id,&lt;br /&gt;
			OnMouseDown = {ClickFunc},&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		if texture then&lt;br /&gt;
			if DEBUG then Spring.Echo(&amp;quot;texture&amp;quot;,texture) end&lt;br /&gt;
			button:Resize(80,80)&lt;br /&gt;
			image= Chili.Image:New {&lt;br /&gt;
				width=&amp;quot;100%&amp;quot;;&lt;br /&gt;
				height=&amp;quot;90%&amp;quot;;&lt;br /&gt;
				y=&amp;quot;6%&amp;quot;;&lt;br /&gt;
				keepAspect = true,	--isState;&lt;br /&gt;
				file = texture;&lt;br /&gt;
				parent = button;&lt;br /&gt;
			}		&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		if(increaseRow)then&lt;br /&gt;
			container.ystep = container.ystep+1&lt;br /&gt;
		end		&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function filterUnwanted(commands)&lt;br /&gt;
	local uniqueList = {}&lt;br /&gt;
	if DEBUG then Spring.Echo(&amp;quot;Total commands &amp;quot;, #commands) end&lt;br /&gt;
	if not(#commands == 0)then&lt;br /&gt;
		j = 1&lt;br /&gt;
		for _, cmd in ipairs(commands) do&lt;br /&gt;
			if DEBUG then Spring.Echo(&amp;quot;Adding command &amp;quot;, cmd.action) end&lt;br /&gt;
			if not table.contains(COMMANDSTOEXCLUDE,cmd.action) then&lt;br /&gt;
				uniqueList[j] = cmd&lt;br /&gt;
				j = j + 1&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return uniqueList&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function resetWindow(container)&lt;br /&gt;
	container:ClearChildren()&lt;br /&gt;
	container.xstep = 1&lt;br /&gt;
	container.ystep = 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function loadPanel()&lt;br /&gt;
	resetWindow(commandWindow)&lt;br /&gt;
	resetWindow(stateCommandWindow)&lt;br /&gt;
	resetWindow(buildCommandWindow)&lt;br /&gt;
	local commands = Spring.GetActiveCmdDescs()&lt;br /&gt;
	commands = filterUnwanted(commands)&lt;br /&gt;
	table.sort(commands,function(x,y) return x.action &amp;lt; y.action end)&lt;br /&gt;
	for cmdid, cmd in pairs(commands) do&lt;br /&gt;
		rowcount = createMyButton(commands[cmdid]) &lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- WIDGET CODE&lt;br /&gt;
function widget:Initialize()&lt;br /&gt;
	widgetHandler:ConfigLayoutHandler(LayoutHandler)&lt;br /&gt;
	Spring.ForceLayoutUpdate()&lt;br /&gt;
	spSendCommands({&amp;quot;tooltip 0&amp;quot;})&lt;br /&gt;
	&lt;br /&gt;
	if (not WG.Chili) then&lt;br /&gt;
		widgetHandler:RemoveWidget()&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	Chili = WG.Chili&lt;br /&gt;
	local screen0 = Chili.Screen0&lt;br /&gt;
		&lt;br /&gt;
	commandWindow = Chili.Control:New{&lt;br /&gt;
		x = 0,&lt;br /&gt;
		y = 0,&lt;br /&gt;
		width = &amp;quot;100%&amp;quot;,&lt;br /&gt;
		height = &amp;quot;40%&amp;quot;,&lt;br /&gt;
		xstep = 1,&lt;br /&gt;
		ystep = 1,&lt;br /&gt;
		draggable = false,&lt;br /&gt;
		resizable = false,&lt;br /&gt;
		dragUseGrip = false,		&lt;br /&gt;
		children = {},&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	stateCommandWindow = Chili.Control:New{&lt;br /&gt;
		x = 0,&lt;br /&gt;
		y = &amp;quot;40%&amp;quot;,&lt;br /&gt;
		width = &amp;quot;100%&amp;quot;,&lt;br /&gt;
		height = &amp;quot;20%&amp;quot;,&lt;br /&gt;
		xstep = 1,&lt;br /&gt;
		ystep = 1,&lt;br /&gt;
		draggable = false,&lt;br /&gt;
		resizable = false,&lt;br /&gt;
		dragUseGrip = false,		&lt;br /&gt;
		children = {},&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	buildCommandWindow = Chili.Control:New{&lt;br /&gt;
		x = 0,&lt;br /&gt;
		y = &amp;quot;60%&amp;quot;,&lt;br /&gt;
		width = &amp;quot;100%&amp;quot;,&lt;br /&gt;
		height = &amp;quot;40%&amp;quot;,&lt;br /&gt;
		xstep = 1,&lt;br /&gt;
		ystep = 1,&lt;br /&gt;
		draggable = false,&lt;br /&gt;
		resizable = false,&lt;br /&gt;
		dragUseGrip = false,		&lt;br /&gt;
		children = {},&lt;br /&gt;
	}		&lt;br /&gt;
	&lt;br /&gt;
	window0 = Chili.Window:New{&lt;br /&gt;
		x = &amp;#039;50%&amp;#039;,&lt;br /&gt;
		y = &amp;#039;15%&amp;#039;,	&lt;br /&gt;
		dockable = true,&lt;br /&gt;
		parent = screen0,&lt;br /&gt;
		caption = &amp;quot;&amp;quot;,&lt;br /&gt;
		draggable = true,&lt;br /&gt;
		resizable = true,&lt;br /&gt;
		dragUseGrip = true,&lt;br /&gt;
		clientWidth = 400,&lt;br /&gt;
		clientHeight = 200,&lt;br /&gt;
		backgroundColor = {0,0,0,1},&lt;br /&gt;
		skinName  = &amp;quot;DarkGlass&amp;quot;,		&lt;br /&gt;
		children = {commandWindow,stateCommandWindow,buildCommandWindow},&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function widget:CommandsChanged()&lt;br /&gt;
	if DEBUG then Spring.Echo(&amp;quot;commandChanged called&amp;quot;) end&lt;br /&gt;
	updateRequired = true&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function widget:DrawScreen()&lt;br /&gt;
    if updateRequired then&lt;br /&gt;
        updateRequired = false&lt;br /&gt;
		loadPanel()&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function widget:Shutdown()&lt;br /&gt;
  widgetHandler:ConfigLayoutHandler(nil)&lt;br /&gt;
  Spring.ForceLayoutUpdate()&lt;br /&gt;
  spSendCommands({&amp;quot;tooltip 1&amp;quot;})&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There we have it, maybe a bit complicated but it&amp;#039;s completly possible to remove the nasty stock ui and build your own fancy chili UI.  I hope these last 3 tutorials where usefull and you will build some very fine chili gui&amp;#039;s&lt;br /&gt;
&lt;br /&gt;
[[Category:Libraries]]&lt;/div&gt;</summary>
		<author><name>Interwiki&gt;Sunspot</name></author>
	</entry>
</feed>