MezzanineEngine 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
areaeffect.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 _areaeffect_cpp
41 #define _areaeffect_cpp
42 
43 #include "areaeffect.h"
44 
45 #include "Physics/physicsmanager.h"
46 #include "Physics/collisionshape.h"
47 #include "Physics/collisionshapemanager.h"
48 #include "Physics/ghostproxy.h"
49 
50 #include "Graphics/mesh.h"
51 #include "Graphics/meshmanager.h"
52 #include "Graphics/entityproxy.h"
54 #include "Graphics/scenemanager.h"
55 
56 #include "serialization.h"
57 #include "exception.h"
58 #include "entresol.h"
59 
60 #include <algorithm>
61 
62 #ifdef GetObject
63 #undef GetObject
64 #endif
65 
66 namespace Mezzanine
67 {
69  WorldObject(TheWorld),
70  Ghost(NULL)
71  { this->CreateAreaEffect(); }
72 
73  AreaEffect::AreaEffect(const String& Name, World* TheWorld) :
74  WorldObject(Name,TheWorld),
75  Ghost(NULL)
76  { this->CreateAreaEffect(); }
77 
79  { this->DestroyAreaEffect(); }
80 
82  {
84  if( PhysMan != NULL ) {
85  this->Ghost = PhysMan->CreateGhostProxy();
86 
87  UInt16 ColGroup = Physics::CF_SensorFilter;
88  UInt16 ColMask = Physics::CF_AllFilter & ~(Physics::CF_SensorFilter | Physics::CF_StaticFilter);
89  this->Ghost->SetCollisionGroupAndMask(ColGroup,ColMask);
90  this->Ghost->_Bind(this);
91  }
92  }
93 
95  {
96  this->RemoveFromWorld();
98  if( this->Ghost != NULL && PhysMan != NULL ) {
99  PhysMan->DestroyProxy( this->Ghost );
100  this->Ghost = NULL;
101  }
102  }
103 
104  ///////////////////////////////////////////////////////////////////////////////
105  // Utility
106 
107  Mezzanine::WorldObjectType AreaEffect::GetType() const
108  { return Mezzanine::WO_AreaEffectUnknown; }
109 
111  { return this->Ghost; }
112 
113  Boolean AreaEffect::IsInWorld() const
114  { return this->Ghost->IsInWorld(); }
115 
116  Boolean AreaEffect::IsStatic() const
117  { return this->Ghost->IsStatic(); }
118 
119  Boolean AreaEffect::IsKinematic() const
120  { return this->Ghost->IsKinematic(); }
121 
122  void AreaEffect::GetProxies(ProxyContainer& Proxies)
123  {
124  Proxies.push_back( this->Ghost );
125  }
126 
127  void AreaEffect::GetProxies(const UInt32 Types, ProxyContainer& Proxies)
128  {
129  if( Types & Mezzanine::PT_Physics_GhostProxy ) {
130  Proxies.push_back( this->Ghost );
131  }
132  }
133 
134  ///////////////////////////////////////////////////////////////////////////////
135  // Working with the World
136 
138  {
139  if( this->Ghost )
140  this->Ghost->AddToWorld();
141  }
142 
144  {
145  if( this->Ghost )
146  this->Ghost->RemoveFromWorld();
147  }
148 
149  ///////////////////////////////////////////////////////////////////////////////
150  // Overlapping Object Management
151 
153  { return this->OverlappingObjects.size(); }
154 
156  { return this->AddedObjects.size(); }
157 
159  { return this->RemovedObjects.size(); }
160 
162  { return this->OverlappingObjects; }
163 
165  { return this->AddedObjects; }
166 
168  { return this->RemovedObjects; }
169 
170  ///////////////////////////////////////////////////////////////////////////////
171  // AreaEffect Properties
172 
173  ///////////////////////////////////////////////////////////////////////////////
174  // Transform Methods
175 
177  {
178  this->Ghost->SetLocation(Loc);
179  }
180 
181  void AreaEffect::SetLocation(const Real X, const Real Y, const Real Z)
182  {
183  this->Ghost->SetLocation(X,Y,Z);
184  }
185 
187  {
188  return this->Ghost->GetLocation();
189  }
190 
192  {
193  this->Ghost->SetOrientation(Ori);
194  }
195 
196  void AreaEffect::SetOrientation(const Real X, const Real Y, const Real Z, const Real W)
197  {
198  this->Ghost->SetOrientation(X,Y,Z,W);
199  }
200 
202  {
203  return this->Ghost->GetOrientation();
204  }
205 
207  {
208  this->Ghost->SetScale(Sc);
209  }
210 
211  void AreaEffect::SetScale(const Real X, const Real Y, const Real Z)
212  {
213  this->Ghost->SetScale(X,Y,Z);
214  }
215 
217  {
218  return this->Ghost->GetScale();
219  }
220 
221  void AreaEffect::Translate(const Vector3& Trans)
222  {
223  this->Ghost->Translate(Trans);
224  }
225 
226  void AreaEffect::Translate(const Real X, const Real Y, const Real Z)
227  {
228  this->Ghost->Translate(X,Y,Z);
229  }
230 
231  void AreaEffect::Yaw(const Real Angle)
232  {
233  this->Ghost->Yaw(Angle);
234  }
235 
236  void AreaEffect::Pitch(const Real Angle)
237  {
238  this->Ghost->Pitch(Angle);
239  }
240 
241  void AreaEffect::Roll(const Real Angle)
242  {
243  this->Ghost->Roll(Angle);
244  }
245 
246  void AreaEffect::Rotate(const Vector3& Axis, const Real Angle)
247  {
248  this->Ghost->Rotate(Axis,Angle);
249  }
250 
251  void AreaEffect::Rotate(const Quaternion& Rotation)
252  {
253  this->Ghost->Rotate(Rotation);
254  }
255 
256  void AreaEffect::Scale(const Vector3& Scale)
257  {
258  this->Ghost->Scale(Scale);
259  }
260 
261  void AreaEffect::Scale(const Real X, const Real Y, const Real Z)
262  {
263  this->Ghost->Scale(X,Y,Z);
264  }
265 
266  ///////////////////////////////////////////////////////////////////////////////
267  // Serialization
268 
270  {
272  }
273 
275  {
276  // No base implementations to call
277  XML::Node ProxiesNode = SelfRoot.AppendChild( AreaEffect::GetSerializableName() + "Proxies" );
278 
279  if( ProxiesNode.AppendAttribute("Version").SetValue("1") )
280  {
281  XML::Node GhostProxNode = ProxiesNode.AppendChild("Ghost");
282  this->Ghost->ProtoSerialize( GhostProxNode );
283 
284  return;
285  }else{
286  SerializeError("Create XML Attribute Values",AreaEffect::GetSerializableName() + "Proxies",true);
287  }
288  }
289 
291  {
293  }
294 
296  {
297  this->DestroyAreaEffect();
298  // No base implementations to call
299  //XML::Attribute CurrAttrib;
300  XML::Node ProxiesNode = SelfRoot.GetChild( AreaEffect::GetSerializableName() + "Proxies" );
301 
302  if( !ProxiesNode.Empty() ) {
303  if(ProxiesNode.GetAttribute("Version").AsInt() == 1) {
304  /// @todo I don't think an exception is appropriate for the failure of the worldmanager validity checks,
305  /// however a warning should be written to the log if that happens. This should be updated to do that once
306  /// logging refactors are done.
307 
308  XML::Node GhostProxNode = ProxiesNode.GetChild("Ghost").GetFirstChild();
309  if( !GhostProxNode.Empty() ) {
311  if( PhysMan ) {
312  this->Ghost = PhysMan->CreateGhostProxy(GhostProxNode);
313  this->Ghost->_Bind( this );
314  }
315  }
316  }else{
317  MEZZ_EXCEPTION(Exception::INVALID_VERSION_EXCEPTION,"Incompatible XML Version for " + (AreaEffect::GetSerializableName() + "Proxies" ) + ": Not Version 1.");
318  }
319  }else{
320  MEZZ_EXCEPTION(Exception::II_IDENTITY_NOT_FOUND_EXCEPTION,AreaEffect::GetSerializableName() + "Proxies" + " was not found in the provided XML node, which was expected.");
321  }
322  }
323 
325  { return AreaEffect::GetSerializableName(); }
326 
328  { return "AreaEffect"; }
329 
330  ///////////////////////////////////////////////////////////////////////////////
331  // Internal Methods
332 
334  {
335  this->AddedObjects.clear();
336  this->RemovedObjects.clear();
337 
338  ObjectContainer PrevOverlapping;
339  PrevOverlapping.swap( this->OverlappingObjects );
340 
341  const UInt32 NumProxies = this->Ghost->GetNumShapeOverlappingProxies();
342  for( UInt32 ProxIndex = 0 ; ProxIndex < NumProxies ; ++ProxIndex )
343  {
344  Physics::CollidableProxy* CurrProxy = this->Ghost->GetShapeOverlappingProxy( ProxIndex );
345  if( CurrProxy != NULL ) {
346  WorldObject* CurrObject = CurrProxy->GetParentObject();
347  if( CurrObject != NULL ) {
348  // We need to check for unique world objects just in case a world object contains multiple collidable proxies
349  ObjectIterator UniqueCheck = std::find( this->OverlappingObjects.begin(), this->OverlappingObjects.end(), CurrObject );
350  if( UniqueCheck == this->OverlappingObjects.end() ) {
351  // We've established that this object is unique, so lets try to remove it from our temporary vector
352  ObjectIterator PrevCheck = std::find( PrevOverlapping.begin(), PrevOverlapping.end(), CurrObject );
353  if( PrevCheck == PrevOverlapping.end() ) {
354  // If we've failed to find it, then it's new
355  this->OverlappingObjects.push_back( CurrObject );
356  this->AddedObjects.push_back( CurrObject );
357  }else{
358  // If it was in the previous frame it isn't new, but it may be removed
359  this->OverlappingObjects.push_back( CurrObject );
360  PrevOverlapping.erase( PrevCheck );
361  }
362  }
363  }
364  }
365  }
366 
367  // If we have anything left over in our prev-overlapping, it's not inside this anymore so put them in the removed vector
368  if( !PrevOverlapping.empty() ) {
369  this->RemovedObjects.swap( PrevOverlapping );
370  }
371  }
372 
374  {
375  if( ToBeDestroyed == NULL )
376  return;
377 
378  if( this->Ghost == ToBeDestroyed ) {
379  this->Ghost = NULL;
380  }
381  }
382 }
383 
384 #endif