1--------------------------------------------------------------------------------
2--------------------------------------------------------------------------------
3--
4--  file:    specialCallinHandlers.lua
5--  brief:
6--  author:  jK
7--
8--  Copyright (C) 2007-2013.
9--  Licensed under the terms of the GNU GPL, v2 or later.
10--
11--------------------------------------------------------------------------------
12--------------------------------------------------------------------------------
13
14
15--------------------------------------------------------------------------------
16--------------------------------------------------------------------------------
17--  Some CallIns need custom handlers
18
19local hCallInLists = handler.callInLists
20local hHookFuncs   = handler.callInHookFuncs
21
22function hHookFuncs.Shutdown()
23	handler:SaveOrderList()
24	handler:SaveConfigData()
25	for _,f in hCallInLists.Shutdown:iter() do
26		f()
27	end
28end
29
30
31function hHookFuncs.ConfigureLayout(command)
32	if (command == 'reconf') then
33		handler:SendConfigData()
34		return true
35	elseif (command:find('togglewidget') == 1) then
36		handler:Toggle(string.sub(command, 14))
37		return true
38	elseif (command:find('enablewidget') == 1) then
39		handler:Enable(string.sub(command, 14))
40		return true
41	elseif (command:find('disablewidget') == 1) then
42		handler:Disable(string.sub(command, 15))
43		return true
44	elseif (command:find('callins') == 1) then
45		Spring.Log(LUA_NAME, "info", "known callins are:")
46		Spring.Log(LUA_NAME, "info", "  (NOTE: This list contains a few (e.g. cause of LOS checking) unhandled CallIns, too.)")
47		local o = {}
48		for i,v in pairs(handler.knownCallIns) do
49			local t = {}
50			for j,w in pairs(v) do
51				t[#t+1] = j .. "=" .. tostring(w)
52			end
53			o[#o+1] = ("  %-25s "):format(i .. ":") .. table.concat(t, ", ")
54		end
55		table.sort(o)
56		for i=1,#o do
57			Spring.Log(LUA_NAME, "info", o[i])
58		end
59		return true
60	end
61
62	if (actionHandler.TextAction(command)) then
63		return true
64	end
65
66	for _,f in hCallInLists.TextCommand:iter() do
67		if (f(command)) then
68			return true
69		end
70	end
71
72	return false
73end
74
75
76function hHookFuncs.Update()
77	local deltaTime = (LUA_NAME == "LuaUI") and Spring.GetLastUpdateSeconds() or nil
78
79	for _,f in hCallInLists.Update:iter() do
80		f(deltaTime)
81	end
82end
83
84
85function hHookFuncs.CommandNotify(id, params, options)
86	for _,f in hCallInLists.CommandNotify:iter() do
87		if (f(id, params, options)) then
88			return true
89		end
90	end
91
92	return false
93end
94
95
96function hHookFuncs.CommandsChanged()
97	handler:UpdateSelection() --// for selectionchanged
98	handler.inCommandsChanged = true
99	handler.customCommands = {}
100
101	for _,f in hCallInLists.CommandsChanged:iter() do
102		f()
103	end
104
105	handler.inCommandsChanged = false
106end
107
108
109--------------------------------------------------------------------------------
110--------------------------------------------------------------------------------
111--  Drawing call-ins
112
113function hHookFuncs.ViewResize(viewGeometry)
114	local vsx = viewGeometry.viewSizeX
115	local vsy = viewGeometry.viewSizeY
116	for _,f in hCallInLists.ViewResize:iter() do
117		f(vsx, vsy, viewGeometry)
118	end
119end
120
121
122--------------------------------------------------------------------------------
123--------------------------------------------------------------------------------
124--  Keyboard call-ins
125
126function hHookFuncs.KeyPress(key, mods, isRepeat, label, unicode)
127	if (actionHandler.KeyAction(true, key, mods, isRepeat)) then
128		return true
129	end
130
131	for _,f in hCallInLists.KeyPress:iter() do
132		if f(key, mods, isRepeat, label, unicode) then
133			return true
134		end
135	end
136
137	return false
138end
139
140
141function hHookFuncs.KeyRelease(key, mods, label, unicode)
142	if (actionHandler.KeyAction(false, key, mods, false)) then
143		return true
144	end
145
146	for _,f in hCallInLists.KeyRelease:iter() do
147		if f(key, mods, label, unicode) then
148			return true
149		end
150	end
151
152	return false
153end
154
155
156--------------------------------------------------------------------------------
157--------------------------------------------------------------------------------
158--  Mouse call-ins
159
160do
161	local lastDrawFrame = 0
162	local lastx,lasty = 0,0
163	local lastWidget
164
165	local spGetDrawFrame = Spring.GetDrawFrame
166
167	--// local helper
168	function handler:WidgetAt(x, y)
169		local drawframe = spGetDrawFrame()
170		if (lastDrawFrame == drawframe)and(lastx == x)and(lasty == y) then
171			return lastWidget
172		end
173
174		lastDrawFrame = drawframe
175		lastx = x
176		lasty = y
177
178		for it,f in hCallInLists.IsAbove:iter() do
179			if f(x, y) then
180				lastWidget = it.owner
181				return lastWidget
182			end
183		end
184
185		lastWidget = nil
186		return nil
187	end
188end
189
190
191function hHookFuncs.MousePress(x, y, button)
192	local mo = handler.mouseOwner
193	if (mo and mo.MousePress__) then
194		SafeCallAddon(mo, "MousePress__", x, y, button)
195		return true  --// already have an active press
196	end
197
198	for it,f in hCallInLists.MousePress:iter() do
199		if f(x, y, button) then
200			handler.mouseOwner = it.owner
201			return true
202		end
203	end
204	return false
205end
206
207
208function hHookFuncs.MouseMove(x, y, dx, dy, button)
209	--FIXME send this event to all widgets (perhaps via a new callin PassiveMouseMove?)
210
211	local mo = handler.mouseOwner
212	if (mo) then
213		return SafeCallAddon(mo, "MouseMove__", x, y, dx, dy, button)
214	end
215end
216
217
218function hHookFuncs.MouseRelease(x, y, button)
219	local mo = handler.mouseOwner
220	local mx, my, lmb, mmb, rmb = Spring.GetMouseState()
221	if (not (lmb or mmb or rmb)) then
222		handler.mouseOwner = nil
223	end
224
225	if (not mo) then
226		return -1
227	end
228
229	return SafeCallAddon(mo, "MouseRelease__", x, y, button) or -1
230end
231
232
233function hHookFuncs.MouseWheel(up, value)
234	for _,f in hCallInLists.MouseWheel:iter() do
235		if (f(up, value)) then
236			return true
237		end
238	end
239	return false
240end
241
242
243function hHookFuncs.IsAbove(x, y)
244	return (handler:WidgetAt(x, y) ~= nil)
245end
246
247
248function hHookFuncs.GetTooltip(x, y)
249	for it,f in hCallInLists.GetTooltip:iter() do
250		if (SafeCallAddon(it.owner, "IsAbove__", x, y)) then
251			local tip = f(x, y)
252			if ((type(tip) == 'string') and (#tip > 0)) then
253				return tip
254			end
255		end
256	end
257	return ""
258end
259
260
261
262--------------------------------------------------------------------------------
263--------------------------------------------------------------------------------
264--  Game call-ins
265
266function hHookFuncs.WorldTooltip(ttType, ...)
267	for _,f in hCallInLists.WorldTooltip:iter() do
268		local tt = f(ttType, ...)
269		if ((type(tt) == 'string') and (#tt > 0)) then
270			return tt
271		end
272	end
273end
274
275
276function hHookFuncs.MapDrawCmd(playerID, cmdType, px, py, pz, ...)
277	local retval = false
278	for _,f in hCallInLists.MapDrawCmd:iter() do
279		local takeEvent = f(playerID, cmdType, px, py, pz, ...)
280		if (takeEvent) then
281			retval = true
282		end
283	end
284	return retval
285end
286
287
288function hHookFuncs.GameSetup(state, ready, playerStates)
289	for _,f in hCallInLists.GameSetup:iter() do
290		local success, newReady = f(state, ready, playerStates)
291		if (success) then
292			return true, newReady
293		end
294	end
295	return false
296end
297
298
299function hHookFuncs.DefaultCommand(...)
300	for _,f in hCallInLists.DefaultCommand:iter() do
301		local result = f(...)
302		if (type(result) == 'number') then
303			return result
304		end
305	end
306	return nil  --// not a number, use the default engine command
307end
308
309
310--------------------------------------------------------------------------------
311--------------------------------------------------------------------------------
312--  RecvLuaMsg
313
314function hHookFuncs.RecvLuaMsg(msg, playerID)
315	local retval = false
316	--FIXME: another actionHandler type?
317	--if (actionHandler.RecvLuaMsg(msg, playerID)) then
318	--	retval = true
319	--end
320
321	for _,f in hCallInLists.RecvLuaMsg:iter() do
322		if f(msg, playerID) then
323			retval = true
324		end
325	end
326	return retval
327end
328
329
330--------------------------------------------------------------------------------
331--------------------------------------------------------------------------------
332--  BlockAddon
333
334function hHookFuncs.BlockAddon(addonName, knownInfo)
335	local retval = false
336	for _,f in hCallInLists.BlockAddon:iter() do
337		if f(addonName, knownInfo) then
338			retval = true
339		end
340	end
341	return retval
342end
343
344
345--------------------------------------------------------------------------------
346--------------------------------------------------------------------------------
347-- Custom SelectionChanged callin
348
349--// local helper
350local oldSelection = {}
351function handler:UpdateSelection()
352	local changed = false
353	local newSelection = Spring.GetSelectedUnits()
354	if (#newSelection == #oldSelection) then
355		for i=1, #newSelection do
356			if (newSelection[i] ~= oldSelection[i]) then --// it seems the order stays
357				changed = true
358				break
359			end
360		end
361	else
362		changed = true
363	end
364	if (changed) then
365		handler:SelectionChanged(newSelection)
366	end
367	oldSelection = newSelection
368end
369
370
371function hHookFuncs.SelectionChanged(selectedUnits)
372	for _,f in hCallInLists.SelectionChanged:iter() do
373		local unitArray = f(selectedUnits)
374		if (unitArray) then
375			Spring.SelectUnitArray(unitArray)
376			selectedUnits = unitArray
377		end
378	end
379end
380