MezzanineEngine 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
particlesystemproxy.cpp
Go to the documentation of this file.
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 _graphicsparticlesystemproxy_cpp
41 #define _graphicsparticlesystemproxy_cpp
42 
43 /// @file
44 /// @brief This file contains the implementation for the World proxy wrapping particle functionality.
45 
47 #include "Graphics/particleaffector.h"
48 #include "Graphics/particleemitter.h"
49 #include "Graphics/scenemanager.h"
50 
51 #include "exception.h"
52 #include "serialization.h"
53 #include "stringtool.h"
54 
55 #include <Ogre.h>
56 
57 namespace Mezzanine
58 {
59  namespace Graphics
60  {
62  RenderableProxy(Creator),
63  GraphicsParticleSystem(NULL),
64  SpeedFactor(1.0),
65  Paused(false)
66  { this->CreateParticleSystem(Template); }
67 
69  RenderableProxy(Creator),
70  GraphicsParticleSystem(NULL),
71  SpeedFactor(1.0),
72  Paused(false)
73  { this->ProtoDeSerialize(SelfRoot); }
74 
76  { this->DestroyParticleSystem(); }
77 
79  {
80  this->GraphicsParticleSystem = this->Manager->_GetGraphicsWorldPointer()->createParticleSystem(ParticleSystemProxy::GenerateName(),Template);
81  this->GraphicsNode->attachObject( this->GraphicsParticleSystem );
82  this->GraphicsParticleSystem->setUserAny( Ogre::Any( static_cast<RenderableProxy*>( this ) ) );
83  this->GraphicsParticleSystem->setVisibilityFlags(0);
84  this->GraphicsParticleSystem->setQueryFlags(0);
85 
86  // Wrap our emitters
87  UInt16 NumEmitters = this->GraphicsParticleSystem->getNumEmitters();
88  for( UInt16 X = 0 ; X < NumEmitters ; ++X )
89  {
90  Graphics::ParticleEmitter* NewEmitter = new Graphics::ParticleEmitter( this->GraphicsParticleSystem->getEmitter(X), this );
91  this->Emitters.push_back(NewEmitter);
92  }
93  // Wrap our affectors
94  UInt16 NumAffectors = this->GraphicsParticleSystem->getNumAffectors();
95  for( UInt16 X = 0 ; X < NumAffectors ; ++X )
96  {
97  Graphics::ParticleAffector* NewAffector = new Graphics::ParticleAffector( this->GraphicsParticleSystem->getAffector(X), this );
98  this->Affectors.push_back(NewAffector);
99  }
100  }
101 
103  {
104  this->DestroyAllEmitters();
105  this->DestroyAllAffectors();
106 
107  if( this->GraphicsParticleSystem ) {
108  this->GraphicsNode->detachObject( this->GraphicsParticleSystem );
109  this->Manager->_GetGraphicsWorldPointer()->destroyParticleSystem( this->GraphicsParticleSystem );
110  }
111  this->CustomSystemParameters.clear();
112  }
113 
115  {
116  static UInt32 NameCounter = 0;
117  StringStream NameStream;
118  NameStream << "ParticleSystem" << ++NameCounter;
119  return NameStream.str();
120  }
121 
122  ///////////////////////////////////////////////////////////////////////////////
123  // Utility
124 
126  {
127  return PT_Graphics_ParticleSystemProxy;
128  }
129 
131  {
132  return this->GraphicsParticleSystem->getName();
133  }
134 
136  {
137  return this->Template;
138  }
139 
141  {
142  if( this->Paused != Pause ) {
143  this->Paused = Pause;
144  this->GraphicsParticleSystem->setSpeedFactor( this->Paused ? 0.0 : this->SpeedFactor );
145  }
146  }
147 
149  {
150  return this->Paused;
151  }
152 
153  void ParticleSystemProxy::SetCustomParam(const String& Name, const String& Value)
154  {
155  this->GraphicsParticleSystem->setParameter(Name,Value);
156  this->CustomSystemParameters[Name] = Value;
157  }
158 
160  {
161  return this->GraphicsParticleSystem->getParameter(Name);
162  }
163 
164  ///////////////////////////////////////////////////////////////////////////////
165  // Emitters
166 
168  { return this->Emitters.at(Index); }
169 
171  { return this->Emitters.size(); }
172 
174  {
175  ParticleEmitter* ToBeDestroyed = this->GetEmitter(Index);
176  this->Emitters.erase( this->Emitters.begin() + Index );
177  delete ToBeDestroyed;
178  this->GraphicsParticleSystem->removeEmitter(Index);
179  }
180 
182  {
183  for( EmitterIterator EmitIt = this->Emitters.begin() ; EmitIt != this->Emitters.end() ; ++EmitIt )
184  {
185  delete (*EmitIt);
186  }
187  this->Emitters.clear();
188  this->GraphicsParticleSystem->removeAllEmitters();
189  }
190 
191  ///////////////////////////////////////////////////////////////////////////////
192  // Affectors
193 
195  { return this->Affectors.at(Index); }
196 
198  { return this->Affectors.size(); }
199 
201  {
202  ParticleAffector* ToBeDestroyed = this->GetAffector(Index);
203  this->Affectors.erase( this->Affectors.begin() + Index );
204  delete ToBeDestroyed;
205  this->GraphicsParticleSystem->removeAffector(Index);
206  }
207 
209  {
210  for( AffectorIterator AffectIt = this->Affectors.begin() ; AffectIt != this->Affectors.end() ; ++AffectIt )
211  {
212  delete (*AffectIt);
213  }
214  this->Affectors.clear();
215  this->GraphicsParticleSystem->removeAllAffectors();
216  }
217 
218  ///////////////////////////////////////////////////////////////////////////////
219  // ParticleSystem Properties
220 
222  {
223  this->SpeedFactor = Factor;
224  if( !this->Paused ) {
225  this->GraphicsParticleSystem->setSpeedFactor( this->SpeedFactor );
226  }
227  }
228 
230  {
231  return this->SpeedFactor;
232  }
233 
234  ///////////////////////////////////////////////////////////////////////////////
235  // Serialization
236 
238  {
239  XML::Node SelfRoot = ParentNode.AppendChild(this->GetDerivedSerializableName());
240  if( !SelfRoot.AppendAttribute("InWorld").SetValue( this->IsInWorld() ? "true" : "false" ) ) {
241  SerializeError("Create XML Attribute Values",ParticleSystemProxy::GetSerializableName(),true);
242  }
243 
244  this->ProtoSerializeTemplate(SelfRoot);
245  this->ProtoSerializeCustomParameters(SelfRoot);
246  this->ProtoSerializeProperties(SelfRoot);
247  this->ProtoSerializeEmitters(SelfRoot);
248  this->ProtoSerializeAffectors(SelfRoot);
249  }
250 
252  {
253  XML::Node ConstructionParamNode = SelfRoot.AppendChild( ParticleSystemProxy::GetSerializableName() + "Template" );
254 
255  if( ConstructionParamNode.AppendAttribute("Version").SetValue("1") &&
256  ConstructionParamNode.AppendAttribute("TemplateName").SetValue( this->GetTemplate() ) )
257  {
258  return;
259  }else{
260  SerializeError("Create XML Attribute Values",ParticleSystemProxy::GetSerializableName() + "TemplateAndName",true);
261  }
262  }
263 
265  {
266  XML::Node CustomParametersNode = SelfRoot.AppendChild( ParticleSystemProxy::GetSerializableName() + "CustomParameters" );
267 
268  if( CustomParametersNode.AppendAttribute("Version").SetValue("1") )
269  {
270  for( NameValuePairMap::const_iterator ParamIt = this->CustomSystemParameters.begin() ; ParamIt != this->CustomSystemParameters.end() ; ++ParamIt )
271  {
272  XML::Node CustomParamNode = CustomParametersNode.AppendChild( "CustomParam" );
273  if( CustomParamNode.AppendAttribute("Version").SetValue("1") &&
274  CustomParamNode.AppendAttribute("ParamName").SetValue( (*ParamIt).first ) &&
275  CustomParamNode.AppendAttribute("ParamValue").SetValue( (*ParamIt).second ) )
276  {
277  return;
278  }else{
279  SerializeError("Create XML Attribute Values",ParticleSystemProxy::GetSerializableName() + "CustomParameters",true);
280  }
281  }
282  }else{
283  SerializeError("Create XML Attribute Values",ParticleSystemProxy::GetSerializableName() + "CustomParameters",true);
284  }
285  }
286 
288  {
289  XML::Node EmittersNode = SelfRoot.AppendChild( ParticleSystemProxy::GetSerializableName() + "Emitters" );
290 
291  if( EmittersNode.AppendAttribute("Version").SetValue("1") )
292  {
293  const UInt16 NumEmitters = this->GetNumEmitters();
294  for( UInt16 Index = 0 ; Index < NumEmitters ; ++Index )
295  {
296  XML::Node EmitterNode = EmittersNode.AppendChild( "Emitter" );
297  if( EmitterNode.AppendAttribute("Version").SetValue("1") &&
298  EmitterNode.AppendAttribute("Index").SetValue( Index ) )
299  {
300  this->GetEmitter(Index)->ProtoSerialize(EmitterNode);
301  }else{
302  SerializeError("Create XML Attribute Values","Emitter",true);
303  }
304  }
305  }else{
306  SerializeError("Create XML Attribute Values",ParticleSystemProxy::GetSerializableName() + "Emitters",true);
307  }
308  }
309 
311  {
312  XML::Node AffectorsNode = SelfRoot.AppendChild( ParticleSystemProxy::GetSerializableName() + "Affectors" );
313 
314  if( AffectorsNode.AppendAttribute("Version").SetValue("1") )
315  {
316  const UInt16 NumAffectors = this->GetNumAffectors();
317  for( UInt16 Index = 0 ; Index < NumAffectors ; ++Index )
318  {
319  XML::Node AffectorNode = AffectorsNode.AppendChild( "Affector" );
320  if( AffectorNode.AppendAttribute("Version").SetValue("1") &&
321  AffectorNode.AppendAttribute("Index").SetValue( Index ) )
322  {
323  this->GetAffector(Index)->ProtoSerialize(AffectorNode);
324  }else{
325  SerializeError("Create XML Attribute Values","Affector",true);
326  }
327  }
328  }else{
329  SerializeError("Create XML Attribute Values",ParticleSystemProxy::GetSerializableName() + "Affectors",true);
330  }
331  }
332 
334  {
336 
337  XML::Node PropertiesNode = SelfRoot.AppendChild( ParticleSystemProxy::GetSerializableName() + "Properties" );
338 
339  if( PropertiesNode.AppendAttribute("Version").SetValue("1") &&
340  PropertiesNode.AppendAttribute("Paused").SetValue( this->IsParticleSystemPaused() ) &&
341  PropertiesNode.AppendAttribute("SpeedFactor").SetValue( this->GetSpeedFactor() ) )
342  {
343  return;
344  }else{
345  SerializeError("Create XML Attribute Values",ParticleSystemProxy::GetSerializableName() + "Properties",true);
346  }
347  }
348 
350  {
351  Boolean WasInWorld = false;
352  XML::Attribute InWorldAttrib = SelfRoot.GetAttribute("InWorld");
353  if( !InWorldAttrib.Empty() ) {
354  WasInWorld = StringTools::ConvertToBool( InWorldAttrib.AsString() );
355  }
356 
357  this->DestroyParticleSystem();
358  this->ProtoDeSerializeTemplate(SelfRoot);
359  this->ProtoDeSerializeCustomParameters(SelfRoot);
360  this->ProtoDeSerializeProperties(SelfRoot);
361  this->ProtoDeSerializeEmitters(SelfRoot);
362  this->ProtoDeSerializeAffectors(SelfRoot);
363 
364  if( WasInWorld ) {
365  this->AddToWorld();
366  }
367  }
368 
370  {
371  XML::Attribute CurrAttrib;
372  XML::Node ConstructionParamNode = SelfRoot.GetChild( ParticleSystemProxy::GetSerializableName() + "Mesh" );
373 
374  if( !ConstructionParamNode.Empty() ) {
375  if(ConstructionParamNode.GetAttribute("Version").AsInt() == 1) {
376  String TemplateName;
377 
378  CurrAttrib = ConstructionParamNode.GetAttribute("TemplateName");
379  if( !CurrAttrib.Empty() )
380  TemplateName = CurrAttrib.AsString();
381 
382  if( !TemplateName.empty() ) {
383  this->CreateParticleSystem(TemplateName);
384  }else{
385  MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Attempting to DeSerialize a ParticleSystemProxy with an empty name or template.");
386  }
387  }
388  }
389  }
390 
392  {
393  XML::Attribute CurrAttrib;
394  XML::Node CustomParametersNode = SelfRoot.GetChild( ParticleSystemProxy::GetSerializableName() + "CustomParameters" );
395 
396  if( !CustomParametersNode.Empty() ) {
397  if(CustomParametersNode.GetAttribute("Version").AsInt() == 1) {
398  String ParamName, ParamValue;
399 
400  for( XML::NodeIterator ParamIt = CustomParametersNode.begin() ; ParamIt != CustomParametersNode.end() ; ++ParamIt )
401  {
402  if( !(*ParamIt).Empty() ) {
403  if((*ParamIt).GetAttribute("Version").AsInt() == 1) {
404  CurrAttrib = (*ParamIt).GetAttribute("ParamName");
405  if( !CurrAttrib.Empty() )
406  ParamName = CurrAttrib.AsString();
407 
408  CurrAttrib = (*ParamIt).GetAttribute("ParamValue");
409  if( !CurrAttrib.Empty() )
410  ParamValue = CurrAttrib.AsString();
411 
412  if( !ParamName.empty() && !ParamValue.empty() ) {
413  this->SetCustomParam(ParamName,ParamValue);
414  }
415  }
416  }
417  }
418  }else{
419  MEZZ_EXCEPTION(Exception::INVALID_VERSION_EXCEPTION,"Incompatible XML Version for " + (ParticleSystemProxy::GetSerializableName() + "CustomParameters" ) + ": Not Version 1.");
420  }
421  }else{
422  MEZZ_EXCEPTION(Exception::II_IDENTITY_NOT_FOUND_EXCEPTION,ParticleSystemProxy::GetSerializableName() + "CustomParameters" + " was not found in the provided XML node, which was expected.");
423  }
424  }
425 
427  {
428  // Currently this assume the emitters were already created when deserializing the template.
429  // So just use what we have and call DeSerialize on them.
430  XML::Attribute CurrAttrib;
431  XML::Node EmittersNode = SelfRoot.GetChild( ParticleSystemProxy::GetSerializableName() + "Emitters" );
432 
433  if( !EmittersNode.Empty() ) {
434  if(EmittersNode.GetAttribute("Version").AsInt() == 1) {
435  UInt16 Index = 0;
436 
437  for( XML::NodeIterator EmitIt = EmittersNode.begin() ; EmitIt != EmittersNode.end() ; ++EmitIt )
438  {
439  CurrAttrib = (*EmitIt).GetAttribute("Index");
440  if( !CurrAttrib.Empty() ) {
441  Index = static_cast<UInt16>( CurrAttrib.AsWhole() );
442  }else{
443  MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Attempting to DeSerialize a ParticleEmitter without a valid Index.");
444  }
445 
446  XML::Node EmitterNode = (*EmitIt).GetFirstChild();
447  this->GetEmitter(Index)->ProtoDeSerialize(EmitterNode);
448  }
449  }
450  }
451  }
452 
454  {
455  // Currently this assume the emitters were already created when deserializing the template.
456  // So just use what we have and call DeSerialize on them.
457  XML::Attribute CurrAttrib;
458  XML::Node AffectorsNode = SelfRoot.GetChild( ParticleSystemProxy::GetSerializableName() + "Affectors" );
459 
460  if( !AffectorsNode.Empty() ) {
461  if(AffectorsNode.GetAttribute("Version").AsInt() == 1) {
462  UInt16 Index = 0;
463 
464  for( XML::NodeIterator AffectIt = AffectorsNode.begin() ; AffectIt != AffectorsNode.end() ; ++AffectIt )
465  {
466  CurrAttrib = (*AffectIt).GetAttribute("Index");
467  if( !CurrAttrib.Empty() ) {
468  Index = static_cast<UInt16>( CurrAttrib.AsWhole() );
469  }else{
470  MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Attempting to DeSerialize a ParticleAffector without a valid Index.");
471  }
472 
473  XML::Node AffectorNode = (*AffectIt).GetFirstChild();
474  this->GetAffector(Index)->ProtoDeSerialize(AffectorNode);
475  }
476  }
477  }
478  }
479 
481  {
483 
484  XML::Attribute CurrAttrib;
485  XML::Node PropertiesNode = SelfRoot.GetChild( ParticleSystemProxy::GetSerializableName() + "Properties" );
486 
487  if( !PropertiesNode.Empty() ) {
488  if(PropertiesNode.GetAttribute("Version").AsInt() == 1) {
489  CurrAttrib = PropertiesNode.GetAttribute("Paused");
490  if( !CurrAttrib.Empty() )
492 
493  CurrAttrib = PropertiesNode.GetAttribute("SpeedFactor");
494  if( !CurrAttrib.Empty() )
495  this->SetSpeedFactor( CurrAttrib.AsReal() );
496  }else{
497  MEZZ_EXCEPTION(Exception::INVALID_VERSION_EXCEPTION,"Incompatible XML Version for " + (ParticleSystemProxy::GetSerializableName() + "Properties" ) + ": Not Version 1.");
498  }
499  }else{
500  MEZZ_EXCEPTION(Exception::II_IDENTITY_NOT_FOUND_EXCEPTION,ParticleSystemProxy::GetSerializableName() + "Properties" + " was not found in the provided XML node, which was expected.");
501  }
502  }
503 
506 
508  { return "ParticleSystemProxy"; }
509 
510  ///////////////////////////////////////////////////////////////////////////////
511  // Internal Methods
512 
513  Ogre::ParticleSystem* ParticleSystemProxy::_GetGraphicsObject() const
514  { return this->GraphicsParticleSystem; }
515 
516  Ogre::MovableObject* ParticleSystemProxy::_GetBaseGraphicsObject() const
517  { return this->GraphicsParticleSystem; }
518  }//Graphics
519 }//Mezzanine
520 
521 #endif