Spinning Topp Logo BlackTopp Studios
inc
sequencecontainer.cpp
1 // © Copyright 2010 - 2016 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 _inputsequencecontainer_cpp
41 #define _inputsequencecontainer_cpp
42 
43 #include "Input/sequencecontainer.h"
44 #include "timer.h"
45 #include "exception.h"
46 
47 #include <limits>
48 
49 namespace Mezzanine
50 {
51  namespace Input
52  {
54  MaxSequenceSize(0),
55  DeviceIndex(std::numeric_limits<UInt32>::max()),
56  SequencedInputs(MetaCode())
57  {
58  this->SequenceTimer = new Timer();
61  }
62 
64  MaxSequenceSize(0),
65  DeviceIndex(Device),
66  SequencedInputs(MetaCode())
67  {
68  this->SequenceTimer = new Timer();
71  }
72 
74  {
75  delete this->SequenceTimer;
76  this->SequencedInputs.clear();
77  }
78 
80  {
81  const Input::MetaCode NullCode;
82  if( Codes.size() < 3 ) {
83  MEZZ_EXCEPTION(ExceptionBase::PARAMETERS_EXCEPTION,"Attempting to add a Sequenced Input that is less then 3 MetaCodes long(including the Null MetaCode). "
84  "A sequence with only one(or less) actual MetaCode isn't a sequence.");
85  }
86  if( NullCode != Codes.back() )
87  { MEZZ_EXCEPTION(ExceptionBase::PARAMETERS_EXCEPTION,"Attempting to add a Sequenced Input that is not terminated with a null MetaCode."); }
88  }
89 
91  {
92  if( std::numeric_limits<Int32>::max() == ID )
93  { MEZZ_EXCEPTION(ExceptionBase::PARAMETERS_EXCEPTION,"Attempting to use max value of Int32 as an ID for an input sequence. This value is reserved for error conditions."); }
94  }
95 
97  {
98  // Set up our data
99  MetaCode Ret;
100  MetaCodeContainer Key(this->CurrSequenceCache.begin(),this->CurrSequenceCache.end());
101  Key.push_back(this->SequencedInputs.endSymbol());
102  // Do the actual search
103  SequencedInputIterator SeqIt = this->SequencedInputs.find(Key);
104  // Return a "Null" metacode if nothing was found
105  if( SeqIt == this->SequencedInputs.end() ) {
106  return Ret;
107  }else{
108  Ret.SetCode(Input::COMPOUNDINPUT_CUSTOMSEQUENCE);
109  Ret.SetMetaValue( *(*SeqIt).second );
110  Ret.SetDeviceIndex(this->DeviceIndex);
111  return Ret;
112  }
113  }
114 
115  ///////////////////////////////////////////////////////////////////////////////
116  // Sequenced Input Management
117 
118  void SequenceContainer::AddInputSequence(const MetaCodeContainer& Codes, const Int32& SequenceID)
119  {
120  this->VerifyInputSequence(Codes);
121  this->VerifyInputID(SequenceID);
122  this->SequencedInputs.insert(Codes,SequenceID);
123  if( this->MaxSequenceSize < Codes.size() - 1 )
124  this->MaxSequenceSize = Codes.size() - 1;
125  }
126 
128  {
129  this->VerifyInputSequence(Codes);
130  return this->SequencedInputs.hasKey(Codes);
131  }
132 
134  {
135  this->VerifyInputSequence(Codes);
136  SequencedInputIterator SqIt = this->SequencedInputs.find(Codes);
137  if( SqIt != this->SequencedInputs.end() ) return *(SqIt->second);
138  else return std::numeric_limits<Int32>::max();
139 
140  /*UInt32* Ret = SequencedInputs.get(Codes);
141  if(Ret) return *Ret;
142  else return ULONG_MAX;// */
143  }
144 
146  {
147  this->VerifyInputSequence(Codes);
148  this->SequencedInputs.erase(Codes);
149  }
150 
152  {
153  this->SequencedInputs.clear();
154  }
155 
156  ///////////////////////////////////////////////////////////////////////////////
157  // Utility
158 
160  {
161  return static_cast<UInt32>(this->SequencedInputs.size());
162  }
163 
164  void SequenceContainer::Update(const MetaCodeContainer& NormalCodes, MetaCodeContainer& SequenceCodes)
165  {
166  // Set up our compare data
167  const MetaCode NullMetaCode;
168  // Escape early if we have nothing to do
169  if(this->SequencedInputs.empty())
170  return;
171 
172  // Check our timer and clear our cache if it's been long enough since the last input
173  if( this->SequenceTimer->IsStopped() <= 0 ) {
174  this->CurrSequenceCache.clear();
175  }else{
176  this->SequenceTimer->Reset(300 * 1000);
177  }
178 
179  // Perform our per-code processing
180  for( ConstMetaCodeIterator MCIt = NormalCodes.begin() ; MCIt != NormalCodes.end() ; ++MCIt )
181  {
182  if( this->CurrSequenceCache.empty() ) {
183  MetaCodeContainer TestVec;
184  TestVec.push_back( (*MCIt) );
185  TestVec.push_back(NullMetaCode);
186  SequencedInputIterator SeqIt = this->SequencedInputs.startsWith(TestVec);
187  if( SeqIt != this->SequencedInputs.end() ) {
188  this->CurrSequenceCache.push_back( (*MCIt) );
189  this->SequenceTimer->Start();
190  }
191  }else{
192  this->CurrSequenceCache.push_back( (*MCIt) );
193  if( this->MaxSequenceSize == this->CurrSequenceCache.size() ) {
194  // Commented out the line below since we shouldn't ever encounter a case where the size is more then 1 greater, since we process one MetaCode at a time
195  //MetaCodeContainer SwapVec(CurrSequenceCache.begin() + ( CurrSequenceCache.size() - MaxSequenceSize ),CurrSequenceCache.end());
196  this->CurrSequenceCache.erase(this->CurrSequenceCache.begin());
197  }else if( this->MaxSequenceSize < this->CurrSequenceCache.size() ) {
198  MEZZ_EXCEPTION(ExceptionBase::INVALID_STATE_EXCEPTION,"Somehow managed to have the sequence cache in this SequenceContainer jump to more than 1 greater than the longest stored sequence. "
199  "Don't know how that happened, but if you see this error then the class needs a patch.");
200  }
201  // Compare current cache to existing stored sequences
202  MetaCode New = this->ProcessSequence(this->CurrSequenceCache.begin(),this->CurrSequenceCache.end());
203  if( NullMetaCode != New )
204  SequenceCodes.push_back(New);
205  }
206  }
207  }
208  }//Input
209 }//Mezzanine
210 
211 #endif
int32_t Int32
An 32-bit integer.
Definition: datatypes.h:124
void SetCode(const Input::InputCode NewCode)
This Sets The InputCode.
Definition: metacode.cpp:238
bool Boole
Generally acts a single bit, true or false.
Definition: datatypes.h:173
UInt32 GetNumInputSequences() const
Gets the number of input sequences stored in this sequence container.
UInt16 MaxSequenceSize
The maximum number of inputs to keep cached for detecting sequenced inputs.
This is a base class for all input devices.
Definition: device.h:55
Boole IsStopped()
Gets whether or not this Timer is currently running.
Definition: timer.cpp:139
#define MEZZ_EXCEPTION(num, desc)
An easy way to throw exceptions with rich information.
Definition: exception.h:3048
STL namespace.
void AddInputSequence(const MetaCodeContainer &Codes, const Int32 &SequenceID)
Adds a custom sequence of inputs that this system will look for and generate MetaCode's for when they...
Input::MetaCode::MetaCodeIterator MetaCodeIterator
Iterator type for convenient MetaCode storage.
Definition: metacode.h:353
This implements the exception hiearchy for Mezzanine.
virtual void VerifyInputSequence(const MetaCodeContainer &Codes) const
Verify's a sequence of MetaCode's is terminated with a null MetaCode.
void VerifyInputID(const Int32 &ID) const
Verify's a numer is valid to be used as an ID for an input sequence being inserted.
uint32_t UInt32
An 32-bit unsigned integer.
Definition: datatypes.h:126
void Start()
Activates the Timer.
Definition: timer.cpp:113
void SetDeviceIndex(const Int32 Index)
Sets the device index if applicable.
Definition: metacode.cpp:253
void SetCountMode(const Mezzanine::CountMode Mode)
Sets the mode the timer should use to increment time.
Definition: timer.cpp:101
void SetCurrentTimeInMilliseconds(const Whole Current)
Sets the current time in Milliseconds. The time that resetting sets the Timer to. ...
Definition: timer.cpp:92
Timer * SequenceTimer
Timer used to help detect input sequences.
Thrown when the available information should have worked but failed for unknown reasons.
Definition: exception.h:113
void Reset(const Whole StartTime=0)
Sets the current time to an initial value and stops the Timer if it is running.
Definition: timer.cpp:127
Thrown when parameters are checked at runtime and found invalid.
Definition: exception.h:108
Input::MetaCode::ConstMetaCodeIterator ConstMetaCodeIterator
Const Iterator type for convenient MetaCode storage.
Definition: metacode.h:355
Boole InputSequenceExists(const MetaCodeContainer &Codes)
Checks to see if the provided sequence of MetaCode's is already being checked for. the vector of MetaCode's doesn't end with a null MetaCode, an exception will be thrown.
This Determines the kind of user input.
Definition: metacode.h:93
Input::MetaCode::MetaCodeContainer MetaCodeContainer
Convenience datatype for storage of MetaCodes.
Definition: metacode.h:351
Int32 GetIDofInputSequence(const MetaCodeContainer &Codes)
Gets the ID of the provided sequence of MetaCode's. the vector of MetaCode's doesn't end with a null ...
The timer counts down, meaning the Timer current time is showing remaining time.
Definition: timer.h:61
A basic timer class to assist in timed operations.
Definition: timer.h:67
MetaCode ProcessSequence(MetaCodeIterator First, MetaCodeIterator OneAfterLast)
Processes a sequence(as defined by an iterator range) to see if any action needs to be taken...
void SetMetaValue(const Int32 Value)
This Sets The MetaValue.
Definition: metacode.cpp:247
The bulk of the engine components go in this namspace.
Definition: actor.cpp:56
SequencedInputContainer SequencedInputs
Container storing all the recognized input sequences.
void Update(const MetaCodeContainer &NormalCodes, MetaCodeContainer &SequenceCodes)
Adds provided codes to the cache if necessary and checks for sequences that have been met...
const UInt32 DeviceIndex
The index of the device to detect sequenced inputs for.
virtual ~SequenceContainer()
Class destructor.
SequencedInputContainer::iterator SequencedInputIterator
Iterator type for recognized input sequences.
MetaCodeContainer CurrSequenceCache
Container storing the current input sequence.
void RemoveAllInputSequences()
Removes all stored input sequences.
void RemoveInputSequence(const MetaCodeContainer &Codes)
Removes the specified custom sequence of MetaCode's. the vector of MetaCode's doesn't end with a null...