1 #include "MouseEvents.h"
2
3 #include "iregistry.h"
4 #include "iselection.h"
5 #include <iostream>
6
7 #include "iradiant.h"
8 #include "radiant_i18n.h"
9 #include "string/string.h"
10
11 namespace {
12 // Needed for string::splitBy
13 typedef std::vector<std::string> StringParts;
14
15 const float DEFAULT_STRAFE_SPEED = 0.65f;
16 const int DEFAULT_MIN_SELECTION_COUNT = -1;
17 }
18
MouseEventManager(Modifiers & modifiers)19 MouseEventManager::MouseEventManager (Modifiers& modifiers) :
20 _modifiers(modifiers), _selectionSystem(NULL), _activeFlags(0)
21 {
22 loadButtonDefinitions();
23
24 loadXYViewEventDefinitions();
25 loadObserverEventDefinitions();
26
27 loadCameraEventDefinitions();
28 loadCameraStrafeDefinitions();
29 }
30
connectSelectionSystem(SelectionSystem * selectionSystem)31 void MouseEventManager::connectSelectionSystem (SelectionSystem* selectionSystem)
32 {
33 _selectionSystem = selectionSystem;
34 }
35
getButtonId(const std::string & buttonName)36 unsigned int MouseEventManager::getButtonId (const std::string& buttonName)
37 {
38 ButtonIdMap::iterator it = _buttonId.find(buttonName);
39 if (it != _buttonId.end()) {
40 return it->second;
41 } else {
42 globalOutputStream() << "MouseEventManager: Warning: Button " << buttonName << " not found, returning ID=0\n";
43 return 0;
44 }
45 }
46
getCondition(xml::Node node)47 MouseEventManager::ConditionStruc MouseEventManager::getCondition (xml::Node node)
48 {
49 const std::string button = node.getAttributeValue("button");
50 const std::string modifiers = node.getAttributeValue("modifiers");
51 const std::string minSelectionCount = node.getAttributeValue("minSelectionCount");
52
53 ConditionStruc returnValue;
54
55 returnValue.buttonId = getButtonId(button);
56 returnValue.modifierFlags = _modifiers.getModifierFlags(modifiers);
57 returnValue.minSelectionCount = string::toInt(minSelectionCount, DEFAULT_MIN_SELECTION_COUNT);
58
59 return returnValue;
60 }
61
loadCameraStrafeDefinitions()62 void MouseEventManager::loadCameraStrafeDefinitions ()
63 {
64 // Find all the camera strafe definitions
65 xml::NodeList strafeList = GlobalRegistry().findXPath("user/ui/input/cameraview/strafemode");
66
67 if (strafeList.size() > 0) {
68 // Get the strafe condition flags
69 _toggleStrafeCondition.modifierFlags = _modifiers.getModifierFlags(strafeList[0].getAttributeValue("toggle"));
70 _toggleForwardStrafeCondition.modifierFlags = _modifiers.getModifierFlags(strafeList[0].getAttributeValue(
71 "forward"));
72 _strafeSpeed = string::toFloat(strafeList[0].getAttributeValue("speed"), DEFAULT_STRAFE_SPEED);
73 _forwardStrafeFactor = string::toFloat(strafeList[0].getAttributeValue("forwardFactor"), 1.0f);
74 } else {
75 // No Camera strafe definitions found!
76 globalOutputStream() << "MouseEventManager: Critical: No camera strafe definitions found!\n";
77 }
78 }
79
loadCameraEventDefinitions()80 void MouseEventManager::loadCameraEventDefinitions ()
81 {
82 xml::NodeList camviews = GlobalRegistry().findXPath("user/ui/input//cameraview");
83
84 if (camviews.size() > 0) {
85
86 // Find all the camera definitions
87 xml::NodeList eventList = camviews[0].getNamedChildren("event");
88
89 if (eventList.size() > 0) {
90 globalOutputStream() << "MouseEventManager: Camera Definitions found: " << eventList.size() << "\n";
91 for (unsigned int i = 0; i < eventList.size(); i++) {
92 // Get the event name
93 const std::string eventName = eventList[i].getAttributeValue("name");
94
95 // Check if any recognised event names are found and construct the according condition.
96 if (eventName == "EnableFreeLookMode") {
97 _cameraConditions[ui::camEnableFreeLookMode] = getCondition(eventList[i]);
98 } else if (eventName == "DisableFreeLookMode") {
99 _cameraConditions[ui::camDisableFreeLookMode] = getCondition(eventList[i]);
100 } else {
101 globalOutputStream() << "MouseEventManager: Warning: Ignoring unkown event name: " << eventName
102 << "\n";
103 }
104 }
105 } else {
106 // No Camera definitions found!
107 globalOutputStream() << "MouseEventManager: Critical: No camera event definitions found!\n";
108 }
109 } else {
110 // No Camera definitions found!
111 globalOutputStream() << "MouseEventManager: Critical: No camera event definitions found!\n";
112 }
113 }
114
loadObserverEventDefinitions()115 void MouseEventManager::loadObserverEventDefinitions ()
116 {
117 xml::NodeList observers = GlobalRegistry().findXPath("user/ui/input//observer");
118
119 if (observers.size() > 0) {
120
121 // Find all the observer definitions
122 xml::NodeList eventList = observers[0].getNamedChildren("event");
123
124 if (eventList.size() > 0) {
125 globalOutputStream() << "MouseEventManager: Observer Definitions found: " << eventList.size() << "\n";
126 for (unsigned int i = 0; i < eventList.size(); i++) {
127 // Get the event name
128 const std::string eventName = eventList[i].getAttributeValue("name");
129
130 // Check if any recognised event names are found and construct the according condition.
131 if (eventName == "Manipulate") {
132 _observerConditions[ui::obsManipulate] = getCondition(eventList[i]);
133 } else if (eventName == "Select") {
134 _observerConditions[ui::obsSelect] = getCondition(eventList[i]);
135 } else if (eventName == "ToggleSelection") {
136 _observerConditions[ui::obsToggle] = getCondition(eventList[i]);
137 } else if (eventName == "ToggleFaceSelection") {
138 _observerConditions[ui::obsToggleFace] = getCondition(eventList[i]);
139 } else if (eventName == "CycleSelection") {
140 _observerConditions[ui::obsReplace] = getCondition(eventList[i]);
141 } else if (eventName == "CycleFaceSelection") {
142 _observerConditions[ui::obsReplaceFace] = getCondition(eventList[i]);
143 } else if (eventName == "CopyTexture") {
144 _observerConditions[ui::obsCopyTexture] = getCondition(eventList[i]);
145 } else if (eventName == "PasteTexture") {
146 _observerConditions[ui::obsPasteTexture] = getCondition(eventList[i]);
147 } else if (eventName == "PasteTextureToBrush") {
148 _observerConditions[ui::obsPasteTextureToBrush] = getCondition(eventList[i]);
149 } else if (eventName == "JumpToObject") {
150 _observerConditions[ui::obsJumpToObject] = getCondition(eventList[i]);
151 } else {
152 globalOutputStream() << "MouseEventManager: Warning: Ignoring unkown event name: " << eventName
153 << "\n";
154 }
155 }
156 } else {
157 // No observer definitions found!
158 globalOutputStream() << "MouseEventManager: Critical: No observer event definitions found!\n";
159 }
160 } else {
161 // No observer definitions found!
162 globalOutputStream() << "MouseEventManager: Critical: No observer event definitions found!\n";
163 }
164 }
165
loadXYViewEventDefinitions()166 void MouseEventManager::loadXYViewEventDefinitions ()
167 {
168 xml::NodeList xyviews = GlobalRegistry().findXPath("user/ui/input//xyview");
169
170 if (xyviews.size() > 0) {
171
172 // Find all the xy view definitions
173 xml::NodeList eventList = xyviews[0].getNamedChildren("event");
174
175 if (eventList.size() > 0) {
176 globalOutputStream() << "MouseEventManager: XYView Definitions found: " << eventList.size() << "\n";
177 for (unsigned int i = 0; i < eventList.size(); i++) {
178 // Get the event name
179 const std::string eventName = eventList[i].getAttributeValue("name");
180
181 // Check if any recognised event names are found and construct the according condition.
182 if (eventName == "MoveView") {
183 _xyConditions[ui::xyMoveView] = getCondition(eventList[i]);
184 } else if (eventName == "Select") {
185 _xyConditions[ui::xySelect] = getCondition(eventList[i]);
186 } else if (eventName == "Zoom") {
187 _xyConditions[ui::xyZoom] = getCondition(eventList[i]);
188 } else if (eventName == "CameraMove") {
189 _xyConditions[ui::xyCameraMove] = getCondition(eventList[i]);
190 } else if (eventName == "CameraAngle") {
191 _xyConditions[ui::xyCameraAngle] = getCondition(eventList[i]);
192 } else if (eventName == "NewBrushDrag") {
193 _xyConditions[ui::xyNewBrushDrag] = getCondition(eventList[i]);
194 } else {
195 globalOutputStream() << "MouseEventManager: Warning: Ignoring unkown event name: " << eventName
196 << "\n";
197 }
198 }
199 } else {
200 // No event definitions found!
201 globalOutputStream() << "MouseEventManager: Critical: No XYView event definitions found!\n";
202 }
203 } else {
204 // No event definitions found!
205 globalOutputStream() << "MouseEventManager: Critical: No XYView event definitions found!\n";
206 }
207 }
208
loadButtonDefinitions()209 void MouseEventManager::loadButtonDefinitions ()
210 {
211 xml::NodeList buttons = GlobalRegistry().findXPath("user/ui/input//buttons");
212
213 if (buttons.size() > 0) {
214
215 // Find all the button definitions
216 xml::NodeList buttonList = buttons[0].getNamedChildren("button");
217
218 if (buttonList.size() > 0) {
219 globalOutputStream() << "MouseEventManager: Buttons found: " << buttonList.size() << "\n";
220 for (unsigned int i = 0; i < buttonList.size(); i++) {
221 const std::string name = buttonList[i].getAttributeValue("name");
222
223 unsigned int id = string::toInt(buttonList[i].getAttributeValue("id"));
224
225 if (name != "" && id > 0) {
226 // Save the button ID into the map
227 _buttonId[name] = id;
228 } else {
229 globalOutputStream() << "MouseEventManager: Warning: Invalid button definition found.\n";
230 }
231 }
232 } else {
233 // No Button definitions found!
234 globalOutputStream() << "MouseEventManager: Critical: No button definitions found!\n";
235 }
236 } else {
237 // No Button definitions found!
238 globalOutputStream() << "MouseEventManager: Critical: No button definitions found!\n";
239 }
240 }
241
242 // Retrieves the button from an GdkEventMotion state
getButtonFlags(const unsigned int & state)243 unsigned int MouseEventManager::getButtonFlags (const unsigned int& state)
244 {
245 if ((state & GDK_BUTTON1_MASK) != 0)
246 return 1;
247 if ((state & GDK_BUTTON2_MASK) != 0)
248 return 2;
249 if ((state & GDK_BUTTON3_MASK) != 0)
250 return 3;
251 if ((state & GDK_BUTTON4_MASK) != 0)
252 return 3;
253 if ((state & GDK_BUTTON5_MASK) != 0)
254 return 3;
255
256 return 0;
257 }
258
findCameraViewEvent(const unsigned int & button,const unsigned int & modifierFlags)259 ui::CamViewEvent MouseEventManager::findCameraViewEvent (const unsigned int& button, const unsigned int& modifierFlags)
260 {
261 if (_selectionSystem == NULL) {
262 globalErrorStream() << "MouseEventManager: No connection to SelectionSystem\n";
263 return ui::camNothing;
264 }
265
266 for (CameraConditionMap::iterator it = _cameraConditions.begin(); it != _cameraConditions.end(); ++it) {
267 ui::CamViewEvent event = it->first;
268 ConditionStruc conditions = it->second;
269
270 if (button == conditions.buttonId && modifierFlags == conditions.modifierFlags
271 && static_cast<int> (_selectionSystem->countSelected()) >= conditions.minSelectionCount) {
272 return event;
273 }
274 }
275 return ui::camNothing;
276 }
277
findXYViewEvent(const unsigned int & button,const unsigned int & modifierFlags)278 ui::XYViewEvent MouseEventManager::findXYViewEvent (const unsigned int& button, const unsigned int& modifierFlags)
279 {
280 if (_selectionSystem == NULL) {
281 globalErrorStream() << "MouseEventManager: No connection to SelectionSystem\n";
282 return ui::xyNothing;
283 }
284
285 for (XYConditionMap::iterator it = _xyConditions.begin(); it != _xyConditions.end(); ++it) {
286 ui::XYViewEvent event = it->first;
287 ConditionStruc conditions = it->second;
288
289 if (button == conditions.buttonId && modifierFlags == conditions.modifierFlags
290 && static_cast<int> (_selectionSystem->countSelected()) >= conditions.minSelectionCount) {
291 return event;
292 }
293 }
294 return ui::xyNothing;
295 }
296
findObserverEvent(const unsigned int & button,const unsigned int & modifierFlags)297 ui::ObserverEvent MouseEventManager::findObserverEvent (const unsigned int& button, const unsigned int& modifierFlags)
298 {
299 if (_selectionSystem == NULL) {
300 globalErrorStream() << "MouseEventManager: No connection to SelectionSystem\n";
301 return ui::obsNothing;
302 }
303
304 for (ObserverConditionMap::iterator it = _observerConditions.begin(); it != _observerConditions.end(); ++it) {
305 ui::ObserverEvent event = it->first;
306 ConditionStruc conditions = it->second;
307
308 if (button == conditions.buttonId && modifierFlags == conditions.modifierFlags
309 && static_cast<int> (_selectionSystem->countSelected()) >= conditions.minSelectionCount) {
310 return event;
311 }
312 }
313 return ui::obsNothing;
314 }
315
getCameraViewEvent(GdkEventButton * event)316 ui::CamViewEvent MouseEventManager::getCameraViewEvent (GdkEventButton* event)
317 {
318 unsigned int button = event->button;
319 unsigned int modifierFlags = _modifiers.getKeyboardFlags(event->state);
320
321 return findCameraViewEvent(button, modifierFlags);
322 }
323
getXYViewEvent(GdkEventButton * event)324 ui::XYViewEvent MouseEventManager::getXYViewEvent (GdkEventButton* event)
325 {
326 unsigned int button = event->button;
327 unsigned int modifierFlags = _modifiers.getKeyboardFlags(event->state);
328
329 return findXYViewEvent(button, modifierFlags);
330 }
331
332 // The same as above, just with a state as argument rather than a GdkEventButton
getXYViewEvent(const unsigned int & state)333 ui::XYViewEvent MouseEventManager::getXYViewEvent (const unsigned int& state)
334 {
335 unsigned int button = getButtonFlags(state);
336 unsigned int modifierFlags = _modifiers.getKeyboardFlags(state);
337
338 return findXYViewEvent(button, modifierFlags);
339 }
340
matchXYViewEvent(const ui::XYViewEvent & xyViewEvent,const unsigned int & button,const unsigned int & modifierFlags)341 bool MouseEventManager::matchXYViewEvent (const ui::XYViewEvent& xyViewEvent, const unsigned int& button,
342 const unsigned int& modifierFlags)
343 {
344 if (_selectionSystem == NULL) {
345 globalErrorStream() << "MouseEventManager: No connection to SelectionSystem\n";
346 return false;
347 }
348
349 XYConditionMap::iterator it = _xyConditions.find(xyViewEvent);
350 if (it != _xyConditions.end()) {
351 // Load the condition
352 ConditionStruc conditions = it->second;
353
354 return (button == conditions.buttonId && modifierFlags == conditions.modifierFlags
355 && static_cast<int> (_selectionSystem->countSelected()) >= conditions.minSelectionCount);
356 } else {
357 globalOutputStream() << "MouseEventManager: Warning: Query for event " << xyViewEvent << ": not found.\n";
358 return false;
359 }
360 }
361
matchObserverEvent(const ui::ObserverEvent & observerEvent,const unsigned int & button,const unsigned int & modifierFlags)362 bool MouseEventManager::matchObserverEvent (const ui::ObserverEvent& observerEvent, const unsigned int& button,
363 const unsigned int& modifierFlags)
364 {
365 if (_selectionSystem == NULL) {
366 globalErrorStream() << "MouseEventManager: No connection to SelectionSystem\n";
367 return false;
368 }
369
370 ObserverConditionMap::iterator it = _observerConditions.find(observerEvent);
371 if (it != _observerConditions.end()) {
372 // Load the condition
373 ConditionStruc conditions = it->second;
374
375 return (button == conditions.buttonId && modifierFlags == conditions.modifierFlags
376 && static_cast<int> (_selectionSystem->countSelected()) >= conditions.minSelectionCount);
377 } else {
378 globalOutputStream() << "MouseEventManager: Warning: Query for event " << observerEvent << ": not found.\n";
379 return false;
380 }
381 }
382
matchCameraViewEvent(const ui::CamViewEvent & camViewEvent,const unsigned int & button,const unsigned int & modifierFlags)383 bool MouseEventManager::matchCameraViewEvent (const ui::CamViewEvent& camViewEvent, const unsigned int& button,
384 const unsigned int& modifierFlags)
385 {
386 if (_selectionSystem == NULL) {
387 globalErrorStream() << "MouseEventManager: No connection to SelectionSystem\n";
388 return false;
389 }
390
391 CameraConditionMap::iterator it = _cameraConditions.find(camViewEvent);
392 if (it != _cameraConditions.end()) {
393 // Load the condition
394 ConditionStruc conditions = it->second;
395
396 return (button == conditions.buttonId && modifierFlags == conditions.modifierFlags
397 && static_cast<int> (_selectionSystem->countSelected()) >= conditions.minSelectionCount);
398 } else {
399 globalOutputStream() << "MouseEventManager: Warning: Query for event " << camViewEvent << ": not found.\n";
400 return false;
401 }
402 }
403
stateMatchesXYViewEvent(const ui::XYViewEvent & xyViewEvent,GdkEventButton * event)404 bool MouseEventManager::stateMatchesXYViewEvent (const ui::XYViewEvent& xyViewEvent, GdkEventButton* event)
405 {
406 return matchXYViewEvent(xyViewEvent, event->button, _modifiers.getKeyboardFlags(event->state));
407 }
408
409 // The same as above, just with a state as argument rather than a GdkEventButton
stateMatchesXYViewEvent(const ui::XYViewEvent & xyViewEvent,const unsigned int & state)410 bool MouseEventManager::stateMatchesXYViewEvent (const ui::XYViewEvent& xyViewEvent, const unsigned int& state)
411 {
412 return matchXYViewEvent(xyViewEvent, getButtonFlags(state), _modifiers.getKeyboardFlags(state));
413 }
414
stateMatchesObserverEvent(const ui::ObserverEvent & observerEvent,GdkEventButton * event)415 bool MouseEventManager::stateMatchesObserverEvent (const ui::ObserverEvent& observerEvent, GdkEventButton* event)
416 {
417 return matchObserverEvent(observerEvent, event->button, _modifiers.getKeyboardFlags(event->state));
418 }
419
stateMatchesCameraViewEvent(const ui::CamViewEvent & camViewEvent,GdkEventButton * event)420 bool MouseEventManager::stateMatchesCameraViewEvent (const ui::CamViewEvent& camViewEvent, GdkEventButton* event)
421 {
422 return matchCameraViewEvent(camViewEvent, event->button, _modifiers.getKeyboardFlags(event->state));
423 }
424
getObserverEvent(GdkEventButton * event)425 ui::ObserverEvent MouseEventManager::getObserverEvent (GdkEventButton* event)
426 {
427 unsigned int button = event->button;
428 unsigned int modifierFlags = _modifiers.getKeyboardFlags(event->state);
429
430 return findObserverEvent(button, modifierFlags);
431 }
432
getObserverEvent(const unsigned int & state)433 ui::ObserverEvent MouseEventManager::getObserverEvent (const unsigned int& state)
434 {
435 unsigned int button = getButtonFlags(state);
436 unsigned int modifierFlags = _modifiers.getKeyboardFlags(state);
437
438 return findObserverEvent(button, modifierFlags);
439 }
440
printXYViewEvent(const ui::XYViewEvent & xyViewEvent)441 std::string MouseEventManager::printXYViewEvent (const ui::XYViewEvent& xyViewEvent)
442 {
443 switch (xyViewEvent) {
444 case ui::xyNothing:
445 return _("<b>Nothing</b>");
446 case ui::xyMoveView:
447 return _("<b>MoveView</b>");
448 case ui::xySelect:
449 return _("<b>Select</b>");
450 case ui::xyZoom:
451 return _("<b>Zoom</b>");
452 case ui::xyCameraMove:
453 return _("<b>CameraMove</b>");
454 case ui::xyCameraAngle:
455 return _("<b>CameraAngle</b>");
456 case ui::xyNewBrushDrag:
457 return _("<b>NewBrushDrag</b>");
458 default:
459 return _("<b>Unknown event</b>");
460 }
461 }
462
printObserverEvent(const ui::ObserverEvent & observerEvent)463 std::string MouseEventManager::printObserverEvent (const ui::ObserverEvent& observerEvent)
464 {
465 switch (observerEvent) {
466 case ui::obsNothing:
467 return _("<b>Nothing</b>");
468 case ui::obsManipulate:
469 return _("<b>Manipulate</b>");
470 case ui::obsSelect:
471 return _("<b>Select</b>");
472 case ui::obsToggle:
473 return _("<b>Toggle</b>");
474 case ui::obsToggleFace:
475 return _("<b>ToggleFace</b>");
476 case ui::obsReplace:
477 return _("<b>Replace</b>");
478 case ui::obsReplaceFace:
479 return _("<b>ReplaceFace</b>");
480 case ui::obsCopyTexture:
481 return _("<b>CopyTexture</b>");
482 case ui::obsPasteTexture:
483 return _("<b>PasteTexture</b>");
484 case ui::obsJumpToObject:
485 return _("<b>Jump to Object</b>");
486 default:
487 return _("<b>Unknown event</b>");
488 }
489 }
490
getShortButtonName(const std::string & longName)491 std::string MouseEventManager::getShortButtonName(const std::string& longName) {
492 if (longName == "MOUSE_LEFT") {
493 return "LMB";
494 }
495 else if (longName == "MOUSE_RIGHT") {
496 return "RMB";
497 }
498 else if (longName == "MOUSE_MIDDLE") {
499 return "MMB";
500 }
501 else if (longName == "MOUSE_THUMB") {
502 return "MB4";
503 }
504 else if (longName == "MOUSE_FIVE") {
505 return "MB5";
506 }
507 else {
508 return "";
509 }
510 }
511
updateStatusText(GdkEventKey * event)512 void MouseEventManager::updateStatusText(GdkEventKey* event) {
513 _activeFlags = _modifiers.getKeyboardFlags(event->state);
514
515 std::string statusText("");
516
517 if (_activeFlags != 0) {
518 for (ButtonIdMap::iterator it = _buttonId.begin(); it != _buttonId.end(); ++it) {
519 // Look up an event with this button ID and the given modifier
520 ui::XYViewEvent xyEvent = findXYViewEvent(it->second, _activeFlags);
521
522 if (xyEvent != ui::xyNothing) {
523 statusText += _modifiers.getModifierStr(_activeFlags, true) + "-";
524 statusText += getShortButtonName(it->first) + ": ";
525 statusText += printXYViewEvent(xyEvent);
526 statusText += " ";
527 }
528
529 // Look up an event with this button ID and the given modifier
530 ui::ObserverEvent obsEvent = findObserverEvent(it->second, _activeFlags);
531
532 if (obsEvent != ui::obsNothing) {
533 statusText += _modifiers.getModifierStr(_activeFlags, true) + "-";
534 statusText += getShortButtonName(it->first) + ": ";
535 statusText += printObserverEvent(obsEvent);
536 statusText += " ";
537 }
538 }
539 }
540
541 GlobalRadiant().setStatusText(statusText);
542 }
543
getCameraStrafeSpeed()544 float MouseEventManager::getCameraStrafeSpeed ()
545 {
546 return _strafeSpeed;
547 }
548
getCameraForwardStrafeFactor()549 float MouseEventManager::getCameraForwardStrafeFactor ()
550 {
551 return _forwardStrafeFactor;
552 }
553
strafeActive(unsigned int & state)554 bool MouseEventManager::strafeActive (unsigned int& state)
555 {
556 return ((_modifiers.getKeyboardFlags(state) & _toggleStrafeCondition.modifierFlags) != 0);
557 }
558
strafeForwardActive(unsigned int & state)559 bool MouseEventManager::strafeForwardActive (unsigned int& state)
560 {
561 return ((_modifiers.getKeyboardFlags(state) & _toggleForwardStrafeCondition.modifierFlags) != 0);
562 }
563