MezzanineEngine 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
eventuserinput.cpp
1 // © Copyright 2010 - 2014 BlackTopp Studios Inc.
2 /* This file is part of The Mezzanine Engine.
3 
4  The Mezzanine Engine is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  The Mezzanine Engine is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with The Mezzanine Engine. If not, see <http://www.gnu.org/licenses/>.
16 */
17 /* The original authors have included a copy of the license specified above in the
18  'Docs' folder. See 'gpl.txt'
19 */
20 /* We welcome the use of the Mezzanine engine to anyone, including companies who wish to
21  Build professional software and charge for their product.
22 
23  However there are some practical restrictions, so if your project involves
24  any of the following you should contact us and we will try to work something
25  out:
26  - DRM or Copy Protection of any kind(except Copyrights)
27  - Software Patents You Do Not Wish to Freely License
28  - Any Kind of Linking to Non-GPL licensed Works
29  - Are Currently In Violation of Another Copyright Holder's GPL License
30  - If You want to change our code and not add a few hundred MB of stuff to
31  your distribution
32 
33  These and other limitations could cause serious legal problems if you ignore
34  them, so it is best to simply contact us or the Free Software Foundation, if
35  you have any questions.
36 
37  Joseph Toppi - toppij@gmail.com
38  John Blackwood - makoenergy02@gmail.com
39 */
40 #ifndef _EVENTUSERINPUT_CPP
41 #define _EVENTUSERINPUT_CPP
42 ///////////////////////////////////////////////////////////////////////////////
43 // This will expose all keyboard and mouse, joystick and other userinput events
44 // to developers, we are using the SDL keymap to get us started, large portions
45 // are directly copy/pasta'd, so we included their license too
46 ///////////////////////////////////////
47 
48 
49 ///////////////////////////////////////////////////////////////////////////////
50 // Includes
51 ///////////////////////////////////////
52 #include "eventuserinput.h"
53 //#include "eventbase.h"
54 #include "exception.h"
55 #include "stringtool.h"
56 
57 #include <memory>
58 #include <vector>
59 
60 #include "SDL.h"
61 
62 using namespace std;
63 
64 
65 namespace Mezzanine
66 {
67  ///////////////////////////////////////////////////////////////////////////////
68  // EventUserInput
69  ///////////////////////////////////////
70  EventUserInput::EventUserInput()
71  {}
72 
73  EventUserInput::EventUserInput(const Input::MetaCode& Code_)
74  { this->push_back(Code_); }
75 
76  EventUserInput::EventUserInput(const vector<Input::MetaCode>& Code_)
77  { AddCodes(Code_); }
78 
79  EventUserInput::~EventUserInput()
80  {}
81 
82  const Input::MetaCode& EventUserInput::GetMetaCode(const unsigned int& Index)
83  { return this->at(Index); }
84 
85  size_t EventUserInput::GetMetaCodeCount()
86  { return this->size(); }
87 
88  Input::MetaCode EventUserInput::AddCode(const Input::MetaCode& Code_)
89  {
90  this->push_back(Code_);
91  return Code_;
92  }
93 
94  Input::MetaCode EventUserInput::AddCode(const RawEvent& RawEvent_)
95  {
96  Input::MetaCode CurrentMetaCode( RawEvent_ );
97  return this->AddCode(CurrentMetaCode);
98  }
99 
100  Input::MetaCode EventUserInput::AddCode(const int& MetaValue_, const Input::InputCode& Code_)
101  {
102  Input::MetaCode CurrentMetaCode( MetaValue_, Code_ );
103  return this->AddCode(CurrentMetaCode);
104  }
105 
106  Input::MetaCode EventUserInput::AddCode(const int& MetaValue_, const Input::InputCode& Code_, const UInt16& DeviceIndex_)
107  {
108  Input::MetaCode CurrentMetaCode( MetaValue_, Code_, DeviceIndex_ );
109  return this->AddCode(CurrentMetaCode);
110  }
111 
112  void EventUserInput::AddCodes(const vector<Input::MetaCode>& Codes)
113  {
114  for(unsigned int c=0; Codes.size()>c ; c++)
115  { this->push_back(Codes.at(c)); }
116  }
117 
118  void EventUserInput::EraseCode(const Input::MetaCode& Code_)
119  {
120  vector<Input::MetaCode>::iterator iter;
121 
122  for(iter=this->begin(); this->end()!=iter ; iter++)
123  {
124  if(*iter == Code_)
125  {
126  this->erase(iter);
127  }
128  }
129  }
130 
131  void EventUserInput::EraseCode(const unsigned int& Index)
132  { this->erase(this->begin()+Index); }
133 
134  EventBase::EventType EventUserInput::GetType() const
135  { return UserInput; }
136 
137  vector<Input::MetaCode> EventUserInput::AddCodesFromRawEvent(const RawEvent& RawEvent_)
138  {
139  vector<Input::MetaCode> Results;
140  switch(RawEvent_.type)
141  {
142  case SDL_KEYUP: case SDL_KEYDOWN:
143  case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONDOWN:
144  case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP:
145  Results.push_back(this->AddCode(RawEvent_));
146  break;
147 
148  case SDL_MOUSEMOTION:{ // ©an contain Multiple Metacodes
149  std::vector<Input::MetaCode> Transport(this->AddCodesFromSDLMouseMotion(RawEvent_));
150  Results.insert(Results.end(), Transport.begin(),Transport.end());
151  break;}
152 
153  case SDL_JOYAXISMOTION: { // ©an contain Multiple Metacodes
154  std::vector<Input::MetaCode> Transport(this->AddCodesFromSDLJoyStickMotion(RawEvent_));
155  Results.insert(Results.end(), Transport.begin(),Transport.end());
156  break;}
157 
158  case SDL_JOYBALLMOTION:{
159  std::vector<Input::MetaCode> Transport(this->AddCodeFromSDLJoyStickBall(RawEvent_));
160  Results.insert(Results.end(), Transport.begin(),Transport.end());
161  break;}
162 
163  case SDL_JOYHATMOTION:{
164  std::vector<Input::MetaCode> Transport(this->AddCodeFromSDLJoyStickHat(RawEvent_));
165  Results.insert(Results.end(), Transport.begin(),Transport.end());
166  break;}
167 
168  default:
169  MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Unknown SDL Event Inserted");
170  break;
171  }
172 
173  return Results;
174  }
175 
176  ///////////////////////////////////////////////////////////////////////////////
177  // EventUserInput Private Methods
178  ///////////////////////////////////////
179 
180  vector<Input::MetaCode> EventUserInput::AddCodesFromSDLMouseMotion(const RawEvent& RawEvent_)
181  {
182  vector<Input::MetaCode> Results;
183 
184  Results.push_back(this->AddCode(RawEvent_.motion.x, Input::MOUSEABSOLUTEHORIZONTAL));
185  Results.push_back(this->AddCode(RawEvent_.motion.y, Input::MOUSEABSOLUTEVERTICAL));
186 
187  if(0 != RawEvent_.motion.xrel)
188  { Results.push_back(this->AddCode(RawEvent_.motion.xrel, Input::MOUSEHORIZONTAL));}
189 
190  if(0 != RawEvent_.motion.yrel)
191  { Results.push_back(this->AddCode(RawEvent_.motion.yrel, Input::MOUSEVERTICAL));}
192  return Results;
193  }
194 
195  vector<Input::MetaCode> EventUserInput::AddCodesFromSDLJoyStickMotion(const RawEvent& RawEvent_)
196  {
197  vector<Input::MetaCode> Results;
198 
199  Results.push_back(this->AddCode(RawEvent_.jaxis.value, Input::MetaCode::GetControllerAxisCode(RawEvent_.jaxis.axis+1), RawEvent_.jaxis.which));
200 
201  return Results;
202  }
203 
204  vector<Input::MetaCode> EventUserInput::AddCodeFromSDLJoyStickHat(const RawEvent& RawEvent_)
205  {
206  vector<Input::MetaCode> Results;
207  Input::InputCode Hat = (Input::InputCode)(RawEvent_.jhat.hat + Input::CONTROLLERHAT_FIRST);
208 
209  if( Input::CONTROLLERHAT_FIRST > Hat || Input::CONTROLLERHAT_LAST < Hat )
210  {
211  MEZZ_EXCEPTION(Exception::NOT_IMPLEMENTED_EXCEPTION,"Unsupported Controller Hat Event");
212  }
213 
214  Results.push_back(this->AddCode( RawEvent_.jhat.value, Hat, RawEvent_.jhat.which ));
215  return Results;
216  }
217 
218  vector<Input::MetaCode> EventUserInput::AddCodeFromSDLJoyStickBall(const RawEvent& RawEvent_)
219  {
220  vector<Input::MetaCode> Results;
221 
222  if( 0 == RawEvent_.jball.ball )
223  {
224  if( RawEvent_.jball.yrel != 0 )
225  { Results.push_back(this->AddCode(RawEvent_.jball.yrel, Input::CONTROLLERBALL_1_VERTICAL, RawEvent_.jball.which)); }
226  if( RawEvent_.jball.xrel != 0 )
227  { Results.push_back(this->AddCode(RawEvent_.jball.xrel, Input::CONTROLLERBALL_1_HORIZONTAL, RawEvent_.jball.which)); }
228  }else if( 1 == RawEvent_.jball.ball ){
229  if( RawEvent_.jball.yrel != 0 )
230  { Results.push_back(this->AddCode(RawEvent_.jball.yrel, Input::CONTROLLERBALL_2_VERTICAL, RawEvent_.jball.which)); }
231  if( RawEvent_.jball.xrel != 0 )
232  { Results.push_back(this->AddCode(RawEvent_.jball.xrel, Input::CONTROLLERBALL_2_HORIZONTAL, RawEvent_.jball.which)); }
233  }else{
234  MEZZ_EXCEPTION(Exception::NOT_IMPLEMENTED_EXCEPTION,"More then 2 trackballs is currently not supported. Perhaps we should expand our enum.");
235  }
236 
237  return Results;
238  }
239 
240 } // /Mezz
241 
242 ///////////////////////////////////////////////////////////////////////////////
243 // Class External << Operators for streaming or assignment
244 std::ostream& operator << (std::ostream& stream, const Mezzanine::EventUserInput& Ev)
245 {
246  stream << "<EventUserInput Version=\"1\">";
247  for (vector<Mezzanine::Input::MetaCode>::const_iterator Iter = Ev.begin(); Iter!=Ev.end(); ++Iter)
248  {
249  stream << *Iter;
250  }
251  stream << "</EventUserInput>";
252 
253  return stream;
254 }
255 
256 std::istream& MEZZ_LIB operator >> (std::istream& stream, Mezzanine::EventUserInput& Ev)
257 {
260 
261  Doc->GetFirstChild() >> Ev;
262 
263  return stream;
264 }
265 
266 void operator >> (const Mezzanine::XML::Node& OneNode, Mezzanine::EventUserInput& Ev)
267 {
268  if ( Mezzanine::String(OneNode.Name())==Mezzanine::String("EventUserInput") )
269  {
270  if(OneNode.GetAttribute("Version").AsInt() == 1)
271  { Ev.clear();
272 
273  //Ev.Impulse=OneNode.GetAttribute("Impulse").AsReal();
274  Mezzanine::XML::Node Child = OneNode.GetFirstChild();
276  while(Child)
277  {
278  Child >> ACode;
279  Ev.AddCode(ACode);
280  Child = Child.GetNextSibling();
281  }
282 
283  }else{
284  MEZZ_EXCEPTION(Mezzanine::Exception::INVALID_VERSION_EXCEPTION,"Incompatible XML Version for EventUserInput: Not Version 1.");
285  }
286  }else{
287  MEZZ_EXCEPTION(Mezzanine::Exception::II_IDENTITY_INVALID_EXCEPTION,"Attempting to deserialize a EventUserInput, found a " + Mezzanine::String(OneNode.Name()));
288  }
289 }
290 
291 
292 #endif