MezzanineEngine 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
fieldofforce.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 _fieldofforce_cpp
41 #define _fieldofforce_cpp
42 
43 #include "fieldofforce.h"
44 
45 #include "Physics/rigidproxy.h"
46 
47 #include "serialization.h"
48 #include "exception.h"
49 
50 namespace Mezzanine
51 {
52  ///////////////////////////////////////////////////////////////////////////////
53  // FieldOfForce Methods
54 
56  AreaEffect(TheWorld),
57  AttenSource(Vector3(0,0,0)),
58  Direction(Vector3(0,1,0)),
59  AttenAmount(0),
60  Strength(0),
61  AttenStyle(Mezzanine::Att_None)
62  { }
63 
64  FieldOfForce::FieldOfForce(const String& Name, World* TheWorld) :
65  AreaEffect(Name,TheWorld),
66  AttenSource(Vector3(0,0,0)),
67  Direction(Vector3(0,1,0)),
68  AttenAmount(0),
69  Strength(0),
70  AttenStyle(Mezzanine::Att_None)
71  { }
72 
73  FieldOfForce::FieldOfForce(const XML::Node& SelfRoot, World* TheWorld) :
74  AreaEffect(TheWorld),
75  AttenSource(Vector3(0,0,0)),
76  Direction(Vector3(0,1,0)),
77  AttenAmount(0),
78  Strength(0),
79  AttenStyle(Mezzanine::Att_None)
80  { this->ProtoDeSerialize(SelfRoot); }
81 
83  { }
84 
85  ///////////////////////////////////////////////////////////////////////////////
86  // Utility
87 
88  Mezzanine::WorldObjectType FieldOfForce::GetType() const
89  { return Mezzanine::WO_AreaEffectFieldOfForce; }
90 
92  {
93  /// @todo This currently will apply this fields force uniformly to all rigid proxies contained in a WorldObject.
94  /// Instead this should perhaps apply only to the ones in the field, or perhaps apply force based on the proxy position
95  /// rather than the WorldObject position to get more interesting results.
96  /// @todo Update to allow the application of force to soft proxies.
97 
98  if(0 == this->Strength)
99  return;
100  if( !this->OverlappingObjects.empty() )
101  {
102  Vector3 ObjectLoc;
103  //Real Distance, AppliedStrength, InvMass;
104  Real Distance, AppliedStrength;
105  for( ObjectIterator ObjIt = this->OverlappingObjects.begin() ; ObjIt != this->OverlappingObjects.end() ; ObjIt++ )
106  {
107  ProxyContainer RigidProxies;
108  (*ObjIt)->GetProxies(Mezzanine::PT_Physics_RigidProxy,RigidProxies);
109  if( RigidProxies.empty() )
110  continue;
111 
112  ObjectLoc = (*ObjIt)->GetLocation();
113  switch(this->AttenStyle)
114  {
116  {
117  Distance = ObjectLoc.Distance(this->AttenSource);
118  AppliedStrength = this->Strength - (this->AttenAmount * Distance);
119  break;
120  }
122  {
123  Distance = ObjectLoc.Distance(this->AttenSource);
124  AppliedStrength = this->Strength - (this->AttenAmount * (Distance * Distance));
125  break;
126  }
127  case Mezzanine::Att_None:
128  {
129  AppliedStrength = this->Strength;
130  break;
131  }
132  }
133 
134  // ©ollect necessary data
135  //InvMass = (*ObjIt)->GetBulletObject()->getInvMass();
136  //if(0 != InvMass)
137  // AppliedStrength *= (1 / (*ObjIt)->GetBulletObject()->getInvMass());
138  //else
139  // AppliedStrength = 0;
140  if(0 > AppliedStrength)
141  AppliedStrength = 0;
142 
143  //Apply the Force
144  for( ProxyIterator ProxIt = RigidProxies.begin() ; ProxIt != RigidProxies.end() ; ++ProxIt )
145  {
146  Physics::RigidProxy* RigProx = static_cast<Physics::RigidProxy*>( *ProxIt );
147  RigProx->ApplyForce( Direction * AppliedStrength );
148  }
149  }
150  }
151  }
152 
153  ///////////////////////////////////////////////////////////////////////////////
154  // FieldOfForce Properties
155 
156  void FieldOfForce::SetFieldStrength(const Real FieldStrength)
157  { this->Strength = FieldStrength; }
158 
160  { return this->Strength; }
161 
162  void FieldOfForce::SetDirectionOfForce(const Vector3& ForceDirection)
163  { this->Direction = ForceDirection; }
164 
166  { return this->Direction; }
167 
168  void FieldOfForce::SetAttenuation(const Real Amount, const Mezzanine::AttenuationStyle Style, const Vector3& Source)
169  {
170  this->AttenAmount = Amount;
171  this->AttenStyle = Style;
172  this->AttenSource = Source;
173  }
174 
176  { this->AttenStyle = Style; }
177 
179  { return this->AttenStyle; }
180 
182  { this->AttenAmount = Amount; }
183 
185  { return this->AttenAmount; }
186 
188  { this->AttenSource = Source; }
189 
191  { return this->AttenSource; }
192 
193  ///////////////////////////////////////////////////////////////////////////////
194  // Serialization
195 
197  {
198  this->AreaEffect::ProtoSerializeProperties(SelfRoot);
199 
200  XML::Node PropertiesNode = SelfRoot.AppendChild( FieldOfForce::GetSerializableName() + "Properties" );
201 
202  if( PropertiesNode.AppendAttribute("Version").SetValue("1") &&
203  PropertiesNode.AppendAttribute("AttenAmount").SetValue( this->GetAttenuationAmount() ) &&
204  PropertiesNode.AppendAttribute("AttenStyle").SetValue( this->GetAttenuationStyle() ) &&
205  PropertiesNode.AppendAttribute("Strength").SetValue( this->GetFieldStrength() ) )
206  {
207  XML::Node AttenSourceNode = PropertiesNode.AppendChild("AttenSource");
208  this->GetAttenuationSource().ProtoSerialize( AttenSourceNode );
209  XML::Node DirectionNode = PropertiesNode.AppendChild("Direction");
210  this->GetDirectionOfForce().ProtoSerialize( DirectionNode );
211 
212  return;
213  }else{
214  SerializeError("Create XML Attribute Values",FieldOfForce::GetSerializableName() + "Properties",true);
215  }
216  }
217 
219  {
221 
222  XML::Attribute CurrAttrib;
223  XML::Node PropertiesNode = SelfRoot.GetChild( FieldOfForce::GetSerializableName() + "Properties" );
224 
225  if( !PropertiesNode.Empty() ) {
226  if(PropertiesNode.GetAttribute("Version").AsInt() == 1) {
227  CurrAttrib = PropertiesNode.GetAttribute("AttenAmount");
228  if( !CurrAttrib.Empty() )
229  this->SetAttenuationAmount( CurrAttrib.AsReal() );
230 
231  CurrAttrib = PropertiesNode.GetAttribute("AttenStyle");
232  if( !CurrAttrib.Empty() )
233  this->SetAttenuationStyle( static_cast<Mezzanine::AttenuationStyle>( CurrAttrib.AsWhole() ) );
234 
235  CurrAttrib = PropertiesNode.GetAttribute("Strength");
236  if( !CurrAttrib.Empty() )
237  this->SetFieldStrength( CurrAttrib.AsReal() );
238 
239  XML::Node AttenSourceNode = PropertiesNode.GetChild("AttenSource").GetFirstChild();
240  if( !AttenSourceNode.Empty() ) {
241  Vector3 Source(AttenSourceNode);
242  this->SetAttenuationSource(Source);
243  }
244 
245  XML::Node DirectionNode = PropertiesNode.GetChild("Direction").GetFirstChild();
246  if( !DirectionNode.Empty() ) {
247  Vector3 Dir(DirectionNode);
248  this->SetDirectionOfForce(Dir);
249  }
250  }else{
251  MEZZ_EXCEPTION(Exception::INVALID_VERSION_EXCEPTION,"Incompatible XML Version for " + (FieldOfForce::GetSerializableName() + "Properties" ) + ": Not Version 1.");
252  }
253  }else{
254  MEZZ_EXCEPTION(Exception::II_IDENTITY_NOT_FOUND_EXCEPTION,FieldOfForce::GetSerializableName() + "Properties" + " was not found in the provided XML node, which was expected.");
255  }
256  }
257 
260 
262  { return "FieldOfForce"; }
263 
264  ///////////////////////////////////////////////////////////////////////////////
265  // FieldOfForceFactory Methods
266 
268  { }
269 
271  { }
272 
275 
277  { return new FieldOfForce(Name,TheWorld); }
278 
280  { return static_cast<FieldOfForce*>( this->CreateAreaEffect(XMLNode,TheWorld) ); }
281 
283  { return new FieldOfForce(Name,TheWorld); }
284 
286  { return new FieldOfForce(XMLNode,TheWorld); }
287 
289  { delete ToBeDestroyed; }
290 }//Mezzanine
291 
292 #endif