1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2
3 #include "System/EventHandler.h"
4 #include "System/EventBatchHandler.h"
5
6 #include "Lua/LuaCallInCheck.h"
7 #include "Lua/LuaOpenGL.h" // FIXME -- should be moved
8
9 #include "System/Config/ConfigHandler.h"
10 #include "System/Platform/Threading.h"
11 #include "System/GlobalConfig.h"
12
13 using std::string;
14 using std::vector;
15 using std::map;
16
17
18 CEventHandler eventHandler;
19
20
21 /******************************************************************************/
22 /******************************************************************************/
23
SetupEvent(const string & eName,EventClientList * list,int props)24 void CEventHandler::SetupEvent(const string& eName,
25 EventClientList* list, int props)
26 {
27 eventMap[eName] = EventInfo(eName, list, props);
28 }
29
30 /******************************************************************************/
31 /******************************************************************************/
32
CEventHandler()33 CEventHandler::CEventHandler()
34 {
35 mouseOwner = NULL;
36
37 // Setup all events
38 #define SETUP_EVENT(name, props) SetupEvent(#name, &list ## name, props);
39 #define SETUP_UNMANAGED_EVENT(name, props) SetupEvent(#name, NULL, props);
40 #include "Events.def"
41 #undef SETUP_EVENT
42 #undef SETUP_UNMANAGED_EVENT
43
44 // helper event client (alwayss create)
45 EventBatchHandler::CreateInstance();
46 }
47
48
~CEventHandler()49 CEventHandler::~CEventHandler()
50 {
51 EventBatchHandler::DeleteInstance();
52 }
53
54
55 /******************************************************************************/
56 /******************************************************************************/
57
AddClient(CEventClient * ec)58 void CEventHandler::AddClient(CEventClient* ec)
59 {
60 ListInsert(handles, ec);
61
62 EventMap::const_iterator it;
63 for (it = eventMap.begin(); it != eventMap.end(); ++it) {
64 const EventInfo& ei = it->second;
65 if (ei.HasPropBit(MANAGED_BIT)) {
66 if (ec->WantsEvent(it->first)) {
67 InsertEvent(ec, it->first);
68 }
69 }
70 }
71 }
72
73
RemoveClient(CEventClient * ec)74 void CEventHandler::RemoveClient(CEventClient* ec)
75 {
76 if (mouseOwner == ec) {
77 mouseOwner = NULL;
78 }
79
80 ListRemove(handles, ec);
81
82 EventMap::const_iterator it;
83 for (it = eventMap.begin(); it != eventMap.end(); ++it) {
84 const EventInfo& ei = it->second;
85 if (ei.HasPropBit(MANAGED_BIT)) {
86 RemoveEvent(ec, it->first);
87 }
88 }
89 }
90
91
92 /******************************************************************************/
93 /******************************************************************************/
94
GetEventList(vector<string> & list) const95 void CEventHandler::GetEventList(vector<string>& list) const
96 {
97 list.clear();
98 EventMap::const_iterator it;
99 for (it = eventMap.begin(); it != eventMap.end(); ++it) {
100 list.push_back(it->first);
101 }
102 }
103
104
IsKnown(const string & eName) const105 bool CEventHandler::IsKnown(const string& eName) const
106 {
107 return (eventMap.find(eName) != eventMap.end());
108 }
109
110
IsManaged(const string & eName) const111 bool CEventHandler::IsManaged(const string& eName) const
112 {
113 EventMap::const_iterator it = eventMap.find(eName);
114 return ((it != eventMap.end()) && (it->second.HasPropBit(MANAGED_BIT)));
115 }
116
117
IsUnsynced(const string & eName) const118 bool CEventHandler::IsUnsynced(const string& eName) const
119 {
120 EventMap::const_iterator it = eventMap.find(eName);
121 return ((it != eventMap.end()) && (it->second.HasPropBit(UNSYNCED_BIT)));
122 }
123
124
IsController(const string & eName) const125 bool CEventHandler::IsController(const string& eName) const
126 {
127 EventMap::const_iterator it = eventMap.find(eName);
128 return ((it != eventMap.end()) && (it->second.HasPropBit(CONTROL_BIT)));
129 }
130
131
132 /******************************************************************************/
133
InsertEvent(CEventClient * ec,const string & ciName)134 bool CEventHandler::InsertEvent(CEventClient* ec, const string& ciName)
135 {
136 EventMap::iterator it = eventMap.find(ciName);
137 if ((it == eventMap.end()) || (it->second.GetList() == NULL)) {
138 return false;
139 }
140 if (ec->GetSynced() && it->second.HasPropBit(UNSYNCED_BIT)) {
141 return false;
142 }
143 ListInsert(*it->second.GetList(), ec);
144 return true;
145 }
146
147
RemoveEvent(CEventClient * ec,const string & ciName)148 bool CEventHandler::RemoveEvent(CEventClient* ec, const string& ciName)
149 {
150 EventMap::iterator it = eventMap.find(ciName);
151 if ((it == eventMap.end()) || (it->second.GetList() == NULL)) {
152 return false;
153 }
154 ListRemove(*it->second.GetList(), ec);
155 return true;
156 }
157
158
159 /******************************************************************************/
160
ListInsert(EventClientList & ecList,CEventClient * ec)161 void CEventHandler::ListInsert(EventClientList& ecList, CEventClient* ec)
162 {
163 EventClientList::iterator it;
164 for (it = ecList.begin(); it != ecList.end(); ++it) {
165 const CEventClient* ecIt = *it;
166 if (ec == ecIt) {
167 return; // already in the list
168 }
169 else if ((ec->GetOrder() < ecIt->GetOrder()) ||
170 ((ec->GetOrder() == ecIt->GetOrder()) &&
171 (ec->GetName() < ecIt->GetName()))) { // should not happen
172 ecList.insert(it, ec);
173 return;
174 }
175 }
176 ecList.push_back(ec);
177 }
178
179
ListRemove(EventClientList & ecList,CEventClient * ec)180 void CEventHandler::ListRemove(EventClientList& ecList, CEventClient* ec)
181 {
182 // FIXME: efficient, hardly
183 EventClientList newList;
184 newList.reserve(ecList.size());
185 for (size_t i = 0; i < ecList.size(); i++) {
186 if (ec != ecList[i]) {
187 newList.push_back(ecList[i]);
188 }
189 }
190 ecList.swap(newList);
191 }
192
193
194 /******************************************************************************/
195 /******************************************************************************/
196
197 #define CONTROL_ITERATE_DEF_TRUE(name, ...) \
198 bool result = true; \
199 for (int i = 0; i < list##name.size(); ) { \
200 CEventClient* ec = list##name[i]; \
201 result &= ec->name(__VA_ARGS__); \
202 if (i < list##name.size() && ec == list##name[i]) \
203 ++i; /* the call-in may remove itself from the list */ \
204 } \
205 return result;
206
207 #define CONTROL_ITERATE_DEF_FALSE(name, ...) \
208 bool result = false; \
209 for (int i = 0; i < list##name.size(); ) { \
210 CEventClient* ec = list##name[i]; \
211 result |= ec->name(__VA_ARGS__); \
212 if (i < list##name.size() && ec == list##name[i]) \
213 ++i; /* the call-in may remove itself from the list */ \
214 } \
215 return result;
216
217
CommandFallback(const CUnit * unit,const Command & cmd)218 bool CEventHandler::CommandFallback(const CUnit* unit, const Command& cmd)
219 {
220 CONTROL_ITERATE_DEF_TRUE(CommandFallback, unit, cmd)
221 }
222
223
AllowCommand(const CUnit * unit,const Command & cmd,bool fromSynced)224 bool CEventHandler::AllowCommand(const CUnit* unit, const Command& cmd, bool fromSynced)
225 {
226 CONTROL_ITERATE_DEF_TRUE(AllowCommand, unit, cmd, fromSynced)
227 }
228
229
AllowUnitCreation(const UnitDef * unitDef,const CUnit * builder,const BuildInfo * buildInfo)230 bool CEventHandler::AllowUnitCreation(const UnitDef* unitDef, const CUnit* builder, const BuildInfo* buildInfo)
231 {
232 CONTROL_ITERATE_DEF_TRUE(AllowUnitCreation, unitDef, builder, buildInfo)
233 }
234
235
AllowUnitTransfer(const CUnit * unit,int newTeam,bool capture)236 bool CEventHandler::AllowUnitTransfer(const CUnit* unit, int newTeam, bool capture)
237 {
238 CONTROL_ITERATE_DEF_TRUE(AllowUnitTransfer, unit, newTeam, capture)
239 }
240
241
AllowUnitBuildStep(const CUnit * builder,const CUnit * unit,float part)242 bool CEventHandler::AllowUnitBuildStep(const CUnit* builder, const CUnit* unit, float part)
243 {
244 CONTROL_ITERATE_DEF_TRUE(AllowUnitBuildStep, builder, unit, part)
245 }
246
247
AllowFeatureCreation(const FeatureDef * featureDef,int allyTeamID,const float3 & pos)248 bool CEventHandler::AllowFeatureCreation(const FeatureDef* featureDef, int allyTeamID, const float3& pos)
249 {
250 CONTROL_ITERATE_DEF_TRUE(AllowFeatureCreation, featureDef, allyTeamID, pos)
251 }
252
253
AllowFeatureBuildStep(const CUnit * builder,const CFeature * feature,float part)254 bool CEventHandler::AllowFeatureBuildStep(const CUnit* builder, const CFeature* feature, float part)
255 {
256 CONTROL_ITERATE_DEF_TRUE(AllowFeatureBuildStep, builder, feature, part)
257 }
258
259
AllowResourceLevel(int teamID,const string & type,float level)260 bool CEventHandler::AllowResourceLevel(int teamID, const string& type, float level)
261 {
262 CONTROL_ITERATE_DEF_TRUE(AllowResourceLevel, teamID, type, level)
263 }
264
265
AllowResourceTransfer(int oldTeam,int newTeam,const string & type,float amount)266 bool CEventHandler::AllowResourceTransfer(int oldTeam, int newTeam, const string& type, float amount)
267 {
268 CONTROL_ITERATE_DEF_TRUE(AllowResourceTransfer, oldTeam, newTeam, type, amount)
269 }
270
271
AllowDirectUnitControl(int playerID,const CUnit * unit)272 bool CEventHandler::AllowDirectUnitControl(int playerID, const CUnit* unit)
273 {
274 CONTROL_ITERATE_DEF_TRUE(AllowDirectUnitControl, playerID, unit)
275 }
276
277
AllowBuilderHoldFire(const CUnit * unit,int action)278 bool CEventHandler::AllowBuilderHoldFire(const CUnit* unit, int action)
279 {
280 CONTROL_ITERATE_DEF_TRUE(AllowBuilderHoldFire, unit, action)
281 }
282
283
AllowStartPosition(int playerID,unsigned char readyState,const float3 & clampedPos,const float3 & rawPickPos)284 bool CEventHandler::AllowStartPosition(int playerID, unsigned char readyState, const float3& clampedPos, const float3& rawPickPos)
285 {
286 CONTROL_ITERATE_DEF_TRUE(AllowStartPosition, playerID, readyState, clampedPos, rawPickPos)
287 }
288
289
290
TerraformComplete(const CUnit * unit,const CUnit * build)291 bool CEventHandler::TerraformComplete(const CUnit* unit, const CUnit* build)
292 {
293 CONTROL_ITERATE_DEF_FALSE(TerraformComplete, unit, build)
294 }
295
296
MoveCtrlNotify(const CUnit * unit,int data)297 bool CEventHandler::MoveCtrlNotify(const CUnit* unit, int data)
298 {
299 CONTROL_ITERATE_DEF_FALSE(MoveCtrlNotify, unit, data)
300 }
301
302
AllowWeaponTargetCheck(unsigned int attackerID,unsigned int attackerWeaponNum,unsigned int attackerWeaponDefID)303 int CEventHandler::AllowWeaponTargetCheck(unsigned int attackerID, unsigned int attackerWeaponNum, unsigned int attackerWeaponDefID)
304 {
305 int result = -1;
306 for (int i = 0; i < listAllowWeaponTargetCheck.size(); ) {
307 CEventClient* ec = listAllowWeaponTargetCheck[i];
308 int result2 = ec->AllowWeaponTargetCheck(attackerID, attackerWeaponNum, attackerWeaponDefID);
309 if (result2 > result) result = result2;
310 if (i < listAllowWeaponTargetCheck.size() && ec == listAllowWeaponTargetCheck[i])
311 ++i; /* the call-in may remove itself from the list */
312 }
313 return result;
314 }
315
316
AllowWeaponTarget(unsigned int attackerID,unsigned int targetID,unsigned int attackerWeaponNum,unsigned int attackerWeaponDefID,float * targetPriority)317 bool CEventHandler::AllowWeaponTarget(
318 unsigned int attackerID,
319 unsigned int targetID,
320 unsigned int attackerWeaponNum,
321 unsigned int attackerWeaponDefID,
322 float* targetPriority
323 ) {
324 CONTROL_ITERATE_DEF_TRUE(AllowWeaponTarget, attackerID, targetID, attackerWeaponNum, attackerWeaponDefID, targetPriority)
325 }
326
327
AllowWeaponInterceptTarget(const CUnit * interceptorUnit,const CWeapon * interceptorWeapon,const CProjectile * interceptorTarget)328 bool CEventHandler::AllowWeaponInterceptTarget(const CUnit* interceptorUnit, const CWeapon* interceptorWeapon, const CProjectile* interceptorTarget)
329 {
330 CONTROL_ITERATE_DEF_TRUE(AllowWeaponInterceptTarget, interceptorUnit, interceptorWeapon, interceptorTarget)
331 }
332
333
UnitPreDamaged(const CUnit * unit,const CUnit * attacker,float damage,int weaponDefID,int projectileID,bool paralyzer,float * newDamage,float * impulseMult)334 bool CEventHandler::UnitPreDamaged(
335 const CUnit* unit,
336 const CUnit* attacker,
337 float damage,
338 int weaponDefID,
339 int projectileID,
340 bool paralyzer,
341 float* newDamage,
342 float* impulseMult
343 ) {
344 CONTROL_ITERATE_DEF_FALSE(UnitPreDamaged, unit, attacker, damage, weaponDefID, projectileID, paralyzer, newDamage, impulseMult)
345 }
346
347
FeaturePreDamaged(const CFeature * feature,const CUnit * attacker,float damage,int weaponDefID,int projectileID,float * newDamage,float * impulseMult)348 bool CEventHandler::FeaturePreDamaged(
349 const CFeature* feature,
350 const CUnit* attacker,
351 float damage,
352 int weaponDefID,
353 int projectileID,
354 float* newDamage,
355 float* impulseMult
356 ) {
357 CONTROL_ITERATE_DEF_FALSE(FeaturePreDamaged, feature, attacker, damage, weaponDefID, projectileID, newDamage, impulseMult)
358 }
359
360
ShieldPreDamaged(const CProjectile * proj,const CWeapon * w,const CUnit * u,bool repulsor)361 bool CEventHandler::ShieldPreDamaged(const CProjectile* proj, const CWeapon* w, const CUnit* u, bool repulsor)
362 {
363 CONTROL_ITERATE_DEF_FALSE(ShieldPreDamaged, proj, w, u, repulsor)
364 }
365
366
SyncedActionFallback(const string & line,int playerID)367 bool CEventHandler::SyncedActionFallback(const string& line, int playerID)
368 {
369 for (int i = 0; i < listSyncedActionFallback.size(); ) {
370 CEventClient* ec = listSyncedActionFallback[i];
371 if (ec->SyncedActionFallback(line, playerID))
372 return true;
373 if (i < listSyncedActionFallback.size() && ec == listSyncedActionFallback[i])
374 ++i; /* the call-in may remove itself from the list */
375 }
376 return false;
377 }
378
379
380 /******************************************************************************/
381 /******************************************************************************/
382
383 #define ITERATE_EVENTCLIENTLIST(name, ...) \
384 for (int i = 0; i < list##name.size(); ) { \
385 CEventClient* ec = list##name[i]; \
386 ec->name(__VA_ARGS__); \
387 if (i < list##name.size() && ec == list##name[i]) \
388 ++i; /* the call-in may remove itself from the list */ \
389 }
390
391
Save(zipFile archive)392 void CEventHandler::Save(zipFile archive)
393 {
394 ITERATE_EVENTCLIENTLIST(Save, archive);
395 }
396
397
GamePreload()398 void CEventHandler::GamePreload()
399 {
400 ITERATE_EVENTCLIENTLIST(GamePreload);
401 }
402
403
GameStart()404 void CEventHandler::GameStart()
405 {
406 ITERATE_EVENTCLIENTLIST(GameStart);
407 }
408
409
GameOver(const std::vector<unsigned char> & winningAllyTeams)410 void CEventHandler::GameOver(const std::vector<unsigned char>& winningAllyTeams)
411 {
412 ITERATE_EVENTCLIENTLIST(GameOver, winningAllyTeams);
413 }
414
415
GamePaused(int playerID,bool paused)416 void CEventHandler::GamePaused(int playerID, bool paused)
417 {
418 ITERATE_EVENTCLIENTLIST(GamePaused, playerID, paused);
419 }
420
421
GameFrame(int gameFrame)422 void CEventHandler::GameFrame(int gameFrame)
423 {
424 ITERATE_EVENTCLIENTLIST(GameFrame, gameFrame);
425 }
426
427
GameID(const unsigned char * gameID,unsigned int numBytes)428 void CEventHandler::GameID(const unsigned char* gameID, unsigned int numBytes)
429 {
430 ITERATE_EVENTCLIENTLIST(GameID, gameID, numBytes);
431 }
432
433
TeamDied(int teamID)434 void CEventHandler::TeamDied(int teamID)
435 {
436 ITERATE_EVENTCLIENTLIST(TeamDied, teamID);
437 }
438
439
TeamChanged(int teamID)440 void CEventHandler::TeamChanged(int teamID)
441 {
442 ITERATE_EVENTCLIENTLIST(TeamChanged, teamID);
443 }
444
445
PlayerChanged(int playerID)446 void CEventHandler::PlayerChanged(int playerID)
447 {
448 ITERATE_EVENTCLIENTLIST(PlayerChanged, playerID);
449 }
450
451
PlayerAdded(int playerID)452 void CEventHandler::PlayerAdded(int playerID)
453 {
454 ITERATE_EVENTCLIENTLIST(PlayerAdded, playerID);
455 }
456
457
PlayerRemoved(int playerID,int reason)458 void CEventHandler::PlayerRemoved(int playerID, int reason)
459 {
460 ITERATE_EVENTCLIENTLIST(PlayerRemoved, playerID, reason);
461 }
462
463
464 /******************************************************************************/
465 /******************************************************************************/
466
UnitHarvestStorageFull(const CUnit * unit)467 void CEventHandler::UnitHarvestStorageFull(const CUnit* unit)
468 {
469 const int unitAllyTeam = unit->allyteam;
470 const int count = listUnitHarvestStorageFull.size();
471 for (int i = 0; i < count; i++) {
472 CEventClient* ec = listUnitHarvestStorageFull[i];
473 if (ec->CanReadAllyTeam(unitAllyTeam)) {
474 ec->UnitHarvestStorageFull(unit);
475 }
476 }
477 }
478
479 /******************************************************************************/
480 /******************************************************************************/
481
CollectGarbage()482 void CEventHandler::CollectGarbage()
483 {
484 ITERATE_EVENTCLIENTLIST(CollectGarbage);
485 }
486
487
DbgTimingInfo(DbgTimingInfoType type,const spring_time start,const spring_time end)488 void CEventHandler::DbgTimingInfo(DbgTimingInfoType type, const spring_time start, const spring_time end)
489 {
490 ITERATE_EVENTCLIENTLIST(DbgTimingInfo, type, start, end);
491 }
492
493
Load(IArchive * archive)494 void CEventHandler::Load(IArchive* archive)
495 {
496 ITERATE_EVENTCLIENTLIST(Load, archive);
497 }
498
499
Update()500 void CEventHandler::Update()
501 {
502 ITERATE_EVENTCLIENTLIST(Update);
503 }
504
505
506
UpdateUnits()507 void CEventHandler::UpdateUnits() { eventBatchHandler->UpdateUnits(); }
UpdateDrawUnits()508 void CEventHandler::UpdateDrawUnits() { eventBatchHandler->UpdateDrawUnits(); }
DeleteSyncedUnits()509 void CEventHandler::DeleteSyncedUnits() { eventBatchHandler->DeleteSyncedUnits(); }
510
UpdateFeatures()511 void CEventHandler::UpdateFeatures() { eventBatchHandler->UpdateFeatures(); }
UpdateDrawFeatures()512 void CEventHandler::UpdateDrawFeatures() { eventBatchHandler->UpdateDrawFeatures(); }
DeleteSyncedFeatures()513 void CEventHandler::DeleteSyncedFeatures() { eventBatchHandler->DeleteSyncedFeatures(); }
514
UpdateProjectiles()515 void CEventHandler::UpdateProjectiles() { eventBatchHandler->UpdateProjectiles(); }
UpdateDrawProjectiles()516 void CEventHandler::UpdateDrawProjectiles() { eventBatchHandler->UpdateDrawProjectiles(); }
517
ExecuteAllCallsFromSynced()518 inline void ExecuteAllCallsFromSynced() { } //FIXME delete
519
DeleteSyncedProjectiles()520 void CEventHandler::DeleteSyncedProjectiles() {
521 ExecuteAllCallsFromSynced();
522 eventBatchHandler->DeleteSyncedProjectiles();
523 }
524
UpdateObjects()525 void CEventHandler::UpdateObjects() {
526 eventBatchHandler->UpdateObjects();
527 }
DeleteSyncedObjects()528 void CEventHandler::DeleteSyncedObjects() {
529 ExecuteAllCallsFromSynced();
530 }
531
532
533
SunChanged(const float3 & sunDir)534 void CEventHandler::SunChanged(const float3& sunDir)
535 {
536 ITERATE_EVENTCLIENTLIST(SunChanged, sunDir);
537 }
538
ViewResize()539 void CEventHandler::ViewResize()
540 {
541 ITERATE_EVENTCLIENTLIST(ViewResize);
542 }
543
544
GameProgress(int gameFrame)545 void CEventHandler::GameProgress(int gameFrame)
546 {
547 ITERATE_EVENTCLIENTLIST(GameProgress, gameFrame);
548 }
549
550
551 #define DRAW_CALLIN(name) \
552 void CEventHandler:: Draw ## name () \
553 { \
554 if (listDraw ## name.empty()) \
555 return; \
556 LuaOpenGL::EnableDraw ## name (); \
557 listDraw ## name [0]->Draw ## name (); \
558 \
559 for (int i = 1; i < listDraw ## name.size(); ) { \
560 LuaOpenGL::ResetDraw ## name (); \
561 CEventClient* ec = listDraw ## name [i]; \
562 ec-> Draw ## name (); \
563 if (i < listDraw ## name.size() && ec == listDraw ## name [i]) \
564 ++i; \
565 } \
566 \
567 LuaOpenGL::DisableDraw ## name (); \
568 }
569
570 DRAW_CALLIN(Genesis)
DRAW_CALLIN(World)571 DRAW_CALLIN(World)
572 DRAW_CALLIN(WorldPreUnit)
573 DRAW_CALLIN(WorldShadow)
574 DRAW_CALLIN(WorldReflection)
575 DRAW_CALLIN(WorldRefraction)
576 DRAW_CALLIN(ScreenEffects)
577 DRAW_CALLIN(Screen)
578 DRAW_CALLIN(InMiniMap)
579 DRAW_CALLIN(InMiniMapBackground)
580
581
582 #define DRAW_ENTITY_CALLIN(name, args, args2) \
583 bool CEventHandler:: Draw ## name args \
584 { \
585 bool skipEngineDrawing = false; \
586 for (int i = 0; i < listDraw ## name.size(); ) { \
587 CEventClient* ec = listDraw ## name [i]; \
588 skipEngineDrawing |= ec-> Draw ## name args2 ; \
589 if (i < listDraw ## name.size() && ec == listDraw ## name [i]) \
590 ++i; \
591 } \
592 return skipEngineDrawing; \
593 }
594
595 DRAW_ENTITY_CALLIN(Unit, (const CUnit* unit), (unit))
596 DRAW_ENTITY_CALLIN(Feature, (const CFeature* feature), (feature))
597 DRAW_ENTITY_CALLIN(Shield, (const CUnit* unit, const CWeapon* weapon), (unit, weapon))
598 DRAW_ENTITY_CALLIN(Projectile, (const CProjectile* projectile), (projectile))
599
600 /******************************************************************************/
601 /******************************************************************************/
602
603 #define CONTROL_REVERSE_ITERATE_DEF_TRUE(name, ...) \
604 for (int i = list##name.size() - 1; i >= 0; --i) { \
605 CEventClient* ec = list##name[i]; \
606 if (ec->name(__VA_ARGS__)) \
607 return true; \
608 }
609
610 #define CONTROL_REVERSE_ITERATE_STRING(name, ...) \
611 for (int i = list##name.size() - 1; i >= 0; --i) { \
612 CEventClient* ec = list##name[i]; \
613 const std::string& str = ec->name(__VA_ARGS__); \
614 if (!str.empty()) \
615 return str; \
616 }
617
618 bool CEventHandler::CommandNotify(const Command& cmd)
619 {
620 CONTROL_REVERSE_ITERATE_DEF_TRUE(CommandNotify, cmd)
621 return false;
622 }
623
624
KeyPress(int key,bool isRepeat)625 bool CEventHandler::KeyPress(int key, bool isRepeat)
626 {
627 CONTROL_REVERSE_ITERATE_DEF_TRUE(KeyPress, key, isRepeat)
628 return false;
629 }
630
631
KeyRelease(int key)632 bool CEventHandler::KeyRelease(int key)
633 {
634 CONTROL_REVERSE_ITERATE_DEF_TRUE(KeyRelease, key)
635 return false;
636 }
637
638
TextInput(const std::string & utf8)639 bool CEventHandler::TextInput(const std::string& utf8)
640 {
641 CONTROL_REVERSE_ITERATE_DEF_TRUE(TextInput, utf8)
642 return false;
643 }
644
645
MousePress(int x,int y,int button)646 bool CEventHandler::MousePress(int x, int y, int button)
647 {
648 for (int i = listMousePress.size() - 1; i >= 0; --i) {
649 CEventClient* ec = listMousePress[i];
650 if (ec->MousePress(x,y,button)) {
651 if (!mouseOwner)
652 mouseOwner = ec;
653 return true;
654 }
655 }
656 return false;
657 }
658
659
MouseRelease(int x,int y,int button)660 void CEventHandler::MouseRelease(int x, int y, int button)
661 {
662 if (mouseOwner) {
663 mouseOwner->MouseRelease(x, y, button);
664 mouseOwner = NULL;
665 }
666 }
667
668
MouseMove(int x,int y,int dx,int dy,int button)669 bool CEventHandler::MouseMove(int x, int y, int dx, int dy, int button)
670 {
671 if (mouseOwner == NULL) {
672 return false;
673 }
674
675 return mouseOwner->MouseMove(x, y, dx, dy, button);
676 }
677
678
MouseWheel(bool up,float value)679 bool CEventHandler::MouseWheel(bool up, float value)
680 {
681 CONTROL_REVERSE_ITERATE_DEF_TRUE(MouseWheel, up, value)
682 return false;
683 }
684
JoystickEvent(const std::string & event,int val1,int val2)685 bool CEventHandler::JoystickEvent(const std::string& event, int val1, int val2)
686 {
687 CONTROL_REVERSE_ITERATE_DEF_TRUE(JoystickEvent, event, val1, val2)
688 return false;
689 }
690
IsAbove(int x,int y)691 bool CEventHandler::IsAbove(int x, int y)
692 {
693 CONTROL_REVERSE_ITERATE_DEF_TRUE(IsAbove, x, y)
694 return false;
695 }
696
GetTooltip(int x,int y)697 string CEventHandler::GetTooltip(int x, int y)
698 {
699 CONTROL_REVERSE_ITERATE_STRING(GetTooltip, x, y)
700 return "";
701 }
702
703
AddConsoleLine(const std::string & msg,const std::string & section,int level)704 bool CEventHandler::AddConsoleLine(const std::string& msg, const std::string& section, int level)
705 {
706 if (listAddConsoleLine.empty())
707 return false;
708
709 ITERATE_EVENTCLIENTLIST(AddConsoleLine, msg, section, level);
710 return true;
711 }
712
713
LastMessagePosition(const float3 & pos)714 void CEventHandler::LastMessagePosition(const float3& pos)
715 {
716 ITERATE_EVENTCLIENTLIST(LastMessagePosition, pos);
717 }
718
719
GroupChanged(int groupID)720 bool CEventHandler::GroupChanged(int groupID)
721 {
722 ITERATE_EVENTCLIENTLIST(GroupChanged, groupID);
723 return false;
724 }
725
726
727
GameSetup(const string & state,bool & ready,const map<int,string> & playerStates)728 bool CEventHandler::GameSetup(const string& state, bool& ready,
729 const map<int, string>& playerStates)
730 {
731 CONTROL_REVERSE_ITERATE_DEF_TRUE(GameSetup, state, ready, playerStates)
732 return false;
733 }
734
735
WorldTooltip(const CUnit * unit,const CFeature * feature,const float3 * groundPos)736 string CEventHandler::WorldTooltip(const CUnit* unit,
737 const CFeature* feature,
738 const float3* groundPos)
739 {
740 CONTROL_REVERSE_ITERATE_STRING(WorldTooltip, unit, feature, groundPos)
741 return "";
742 }
743
744
MapDrawCmd(int playerID,int type,const float3 * pos0,const float3 * pos1,const string * label)745 bool CEventHandler::MapDrawCmd(int playerID, int type,
746 const float3* pos0, const float3* pos1,
747 const string* label)
748 {
749 CONTROL_REVERSE_ITERATE_DEF_TRUE(MapDrawCmd, playerID, type, pos0, pos1, label)
750 return false;
751 }
752
753
754 /******************************************************************************/
755 /******************************************************************************/
756
UnsyncedProjectileCreated(const CProjectile * proj)757 void CEventHandler::UnsyncedProjectileCreated(const CProjectile* proj) {
758 //FIXME no real event
759 (eventBatchHandler->GetUnsyncedProjectileCreatedDestroyedBatch()).insert(proj);
760 }
761
UnsyncedProjectileDestroyed(const CProjectile * proj)762 void CEventHandler::UnsyncedProjectileDestroyed(const CProjectile* proj) {
763 //FIXME no real event
764 (eventBatchHandler->GetUnsyncedProjectileCreatedDestroyedBatch()).erase_delete(proj);
765 }
766
LoadedModelRequested()767 void CEventHandler::LoadedModelRequested() {
768 //FIXME no real event
769 eventBatchHandler->LoadedModelRequested();
770 }
771
772
773 /******************************************************************************/
774 /******************************************************************************/
775
776