Chili:Tutorial Command and Build Commands: Difference between revisions

From Spring
Jump to navigationJump to search
Sunspot (talk | contribs)
No edit summary
Sunspot (talk | contribs)
Line 153: Line 153:


=== On unit selection ... load the commands ===
=== On unit selection ... load the commands ===
Each unit in the game can have different commands.  It even gets more complicated when you select more then one unit.  Some commands are double, some new etc...  It all gets a bit messy.  So we have to take all those things in consideration.  Due to the complexity I'm goint to cut things in several parts.
<code><pre>
function widget:CommandsChanged()
if DEBUG then Spring.Echo("commandChanged called") end
updateRequired = true
end
function widget:DrawScreen()
    if updateRequired then
        updateRequired = false
local selection = spGetSelectedUnits()
drawPanel(selection)
    end
end
</pre></code>
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 windows in our case) needs to be redrawn.  I'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'll find in most chili scripts.
<code><pre>
function findUniqueCommandsFromSelection(unitSelection)
local uniqueList = {}
if DEBUG then Spring.Echo("Unit selection ", #unitSelection) end
if not(#unitSelection == 0)then
local j = 1
for i, unit in ipairs(unitSelection) do
local unitcommands = Spring.GetUnitCmdDescs(unit)
for _, cmd in ipairs(unitcommands) do
local contained = false
for k=1, #uniqueList do
if(uniqueList[k].id == cmd.id)then
contained = true
end
end
if not contained then
if DEBUG then Spring.Echo("Adding command ", cmd.name) end
if not table.contains(COMMANDSTOEXCLUDE,cmd.name) then
uniqueList[j] = cmd
j = j + 1
end
end
end
end
end
return uniqueList
end
function resetWindow(container)
RemoveChildren(container)
container.xstep = 1
container.ystep = 1
end
function drawPanel(unitSelection)
resetWindow(commandWindow)
resetWindow(stateCommandWindow)
resetWindow(buildCommandWindow)
if (#unitSelection ~= 0)then
local commands = findUniqueCommandsFromSelection(unitSelection)
table.sort(commands,function(x,y) return x.action < y.action end)
for cmdid, cmd in pairs(commands) do
rowcount = createMyButton(commands[cmdid])
end
end
end
</pre></code>

Revision as of 19:26, 26 June 2011

Commands and Build bar

Preparation

We are stepping it up a notch. We can all agree that the stock GUI for commands and building isn't really all that great. Good thing is we can improve on this. Following is not a perfect sollution since it doesn'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.

 
- LuaUI\widgets\gui_chili_commandwindow.lua

File header

You open up with the regular info and imports that you are going to use thru the script.

function widget:GetInfo()
	return {
		name		= "command list window",
		desc		= "ChiliUi window that contains all the commands a unit has",
		author		= "Sunspot",
		date		= "2011-06-15",
		license     = "GNU GPL v2",
		layer		= math.huge,
		enabled   	= true,
		handler		= true,
	}
end
-- INCLUDES
VFS.Include("LuaRules/Gadgets/Includes/utilities.lua")

-- CONSTANTS
local MAXBUTTONSONROW = 4
local COMMANDSTOEXCLUDE = {"TimeWait","DeathWait","SquadWait","GatherWait","Load units"}
local Chili
local Button
local Window
local Image
local Control

-- MEMBERS
local x
local y
local commandWindow
local stateCommandWindow
local buildCommandWindow
local updateRequired = true

-- CONTROLS
local spGetActiveCommand 	= Spring.GetActiveCommand
local spGetActiveCmdDesc 	= Spring.GetActiveCmdDesc
local spGetSelectedUnits    = Spring.GetSelectedUnits
local spSendCommands        = Spring.SendCommands

You'll notice a lot of variables and controls. They will all get a place during the further script design and explained in detail.

initializing the widget

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 windows to seperate the command, status command and build commands in. To keep those windows nicely together we merge them in one window. Following code will do this. I'll explain it more in detail since it has a few important parts.

function widget:Initialize()
	widgetHandler:ConfigLayoutHandler(LayoutHandler)
	Spring.ForceLayoutUpdate()
	spSendCommands({"tooltip 0"})
	
	if (not WG.Chili) then
		widgetHandler:RemoveWidget()
		return
	end

	Chili = WG.Chili
	Button = Chili.Button
	Window = Chili.Window
	Image = Chili.Image
	local screen0 = Chili.Screen0
		
	commandWindow = Window:New{
		x = 0,
		y = 0,
		width = "100%",
		height = "40%",
		xstep = 1,
		ystep = 1,
		draggable = false,
		resizable = false,
		dragUseGrip = false,		
		anchors = {left=true,bottom=true,right=true,top=true},
		children = {},
	}

	stateCommandWindow = Window:New{
		x = 0,
		y = "40%",
		width = "100%",
		height = "20%",
		xstep = 1,
		ystep = 1,
		draggable = false,
		resizable = false,
		dragUseGrip = false,		
		anchors = {left=true,bottom=false,right=true,top=false},
		children = {},
	}	

	buildCommandWindow = Window:New{
		x = 0,
		y = "60%",
		width = "100%",
		height = "40%",
		xstep = 1,
		ystep = 1,
		draggable = false,
		resizable = false,
		dragUseGrip = false,		
		anchors = {left=true,bottom=true,right=true,top=false},
		children = {},
	}		
	
	window0 = Window:New{
		x = '50%',
		y = '15%',	
		dockable = true,
		parent = screen0,
		caption = "",
		draggable = true,
		resizable = true,
		dragUseGrip = true,
		clientWidth = 400,
		clientHeight = 200,
		backgroundColor = {0,0,0,1},
		skinName  = "DarkGlass",		
		children = {commandWindow,stateCommandWindow,buildCommandWindow},
	}	
end

function LayoutHandler(xIcons, yIcons, cmdCount, commands)
	widgetHandler.commands   = commands
	widgetHandler.commands.n = cmdCount
	widgetHandler:CommandsChanged()
	local reParamsCmds = {}
	local customCmds = {}

	return "", xIcons, yIcons, {}, customCmds, {}, {}, {}, {}, reParamsCmds, {[1337]=9001}
end

function widget:Shutdown()
  widgetHandler:ConfigLayoutHandler(nil)
  Spring.ForceLayoutUpdate()
  spSendCommands({"tooltip 1"})
end

The first 3 lines remove the stock command stuff, by ways of creating a custom LayoutHandler. There isn't much to say about that method other then it's best to copy paste the one you see here. I've went thru a couple of scripts who use custom chili command windows and most of them have the same method. The spSendCommands({"tooltip 0"}) line removes the bottom left tooltip

Next we instantiate all our chili controls and objects, we create 3 windows and group them in one seperate window. We also make sure the 3 windows resize together with the group window by anchoring them in the right positions and 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.

On unit selection ... load the commands

Each unit in the game can have different commands. It even gets more complicated when you select more then one unit. Some commands are double, some new etc... It all gets a bit messy. So we have to take all those things in consideration. Due to the complexity I'm goint to cut things in several parts.

function widget:CommandsChanged()
	if DEBUG then Spring.Echo("commandChanged called") end
	updateRequired = true
end

function widget:DrawScreen()
    if updateRequired then
        updateRequired = false
		local selection = spGetSelectedUnits()
		drawPanel(selection)
    end
end

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 windows in our case) needs to be redrawn. I'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'll find in most chili scripts.

function findUniqueCommandsFromSelection(unitSelection)
	local uniqueList = {}
	if DEBUG then Spring.Echo("Unit selection ", #unitSelection) end
	if not(#unitSelection == 0)then
		local j = 1
		for i, unit in ipairs(unitSelection) do
			local unitcommands = Spring.GetUnitCmdDescs(unit)
			for _, cmd in ipairs(unitcommands) do
				local contained = false
				for k=1, #uniqueList do
					if(uniqueList[k].id == cmd.id)then
						contained = true
					end
				end
				if not contained then
					if DEBUG then Spring.Echo("Adding command ", cmd.name) end
					if not table.contains(COMMANDSTOEXCLUDE,cmd.name) then
						uniqueList[j] = cmd
						j = j + 1
					end
				end
			end			
		end
	end
	return uniqueList
end

function resetWindow(container)
	RemoveChildren(container)
	container.xstep = 1
	container.ystep = 1
end

function drawPanel(unitSelection)
	resetWindow(commandWindow)
	resetWindow(stateCommandWindow)
	resetWindow(buildCommandWindow)
	if (#unitSelection ~= 0)then
		local commands = findUniqueCommandsFromSelection(unitSelection)
		table.sort(commands,function(x,y) return x.action < y.action end)
		for cmdid, cmd in pairs(commands) do
			rowcount = createMyButton(commands[cmdid]) 
		end
	end
end