ActorFactory.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. //========================================================================
  2. // ActorFactory.cpp : Creates actors from components
  3. //
  4. // Part of the GameCode4 Application
  5. //
  6. // GameCode4 is the sample application that encapsulates much of the source code
  7. // discussed in "Game Coding Complete - 4th Edition" by Mike McShaffry and David
  8. // "Rez" Graham, published by Charles River Media.
  9. // ISBN-10: 1133776574 | ISBN-13: 978-1133776574
  10. //
  11. // If this source code has found it's way to you, and you think it has helped you
  12. // in any way, do the authors a favor and buy a new copy of the book - there are
  13. // detailed explanations in it that compliment this code well. Buy a copy at Amazon.com
  14. // by clicking here:
  15. // http://www.amazon.com/gp/product/1133776574/ref=olp_product_details?ie=UTF8&me=&seller=
  16. //
  17. // There's a companion web site at http://www.mcshaffry.com/GameCode/
  18. //
  19. // The source code is managed and maintained through Google Code:
  20. // http://code.google.com/p/gamecode4/
  21. //
  22. // (c) Copyright 2012 Michael L. McShaffry and David Graham
  23. //
  24. // This program is free software; you can redistribute it and/or
  25. // modify it under the terms of the GNU Lesser GPL v3
  26. // as published by the Free Software Foundation.
  27. //
  28. // This program is distributed in the hope that it will be useful,
  29. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  30. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  31. // http://www.gnu.org/licenses/lgpl-3.0.txt for more details.
  32. //
  33. // You should have received a copy of the GNU Lesser GPL v3
  34. // along with this program; if not, write to the Free Software
  35. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  36. //
  37. //========================================================================
  38. #include "../Unix/GameCodeStd.h"
  39. #include "ActorFactory.h"
  40. #include "../ResourceCache/XmlResource.h"
  41. #include "AudioComponent.h"
  42. #include "RenderComponent.h"
  43. #include "TransformComponent.h"
  44. #include "BaseScriptComponent.h"
  45. //---------------------------------------------------------------------------------------------------------------------
  46. // Factory class definition
  47. // Chapter 6, page 161
  48. //---------------------------------------------------------------------------------------------------------------------
  49. ActorFactory::ActorFactory(void)
  50. {
  51. m_lastActorId = INVALID_ACTOR_ID;
  52. m_componentFactory.Register<TransformComponent>(ActorComponent::GetIdFromName(TransformComponent::g_Name));
  53. // m_componentFactory.Register<MeshRenderComponent>(ActorComponent::GetIdFromName(MeshRenderComponent::g_Name));
  54. // m_componentFactory.Register<SphereRenderComponent>(ActorComponent::GetIdFromName(SphereRenderComponent::g_Name));
  55. // m_componentFactory.Register<PhysicsComponent>(ActorComponent::GetIdFromName(PhysicsComponent::g_Name));
  56. m_componentFactory.Register<TeapotRenderComponent>(ActorComponent::GetIdFromName(TeapotRenderComponent::g_Name));
  57. m_componentFactory.Register<GridRenderComponent>(ActorComponent::GetIdFromName(GridRenderComponent::g_Name));
  58. m_componentFactory.Register<LightRenderComponent>(ActorComponent::GetIdFromName(LightRenderComponent::g_Name));
  59. m_componentFactory.Register<SkyRenderComponent>(ActorComponent::GetIdFromName(SkyRenderComponent::g_Name));
  60. m_componentFactory.Register<AudioComponent>(ActorComponent::GetIdFromName(AudioComponent::g_Name));
  61. // // FUTURE WORK - certainly don't need to do this now, but the following stuff should be in a TeapotWarsActorFactory, eh?
  62. // m_componentFactory.Register<AmmoPickup>(ActorComponent::GetIdFromName(AmmoPickup::g_Name));
  63. // m_componentFactory.Register<HealthPickup>(ActorComponent::GetIdFromName(HealthPickup::g_Name));
  64. m_componentFactory.Register<BaseScriptComponent>(ActorComponent::GetIdFromName(BaseScriptComponent::g_Name));
  65. }
  66. StrongActorPtr ActorFactory::CreateActor(
  67. const char* actorResource,
  68. TiXmlElement *overrides,
  69. std::optional<const glm::mat4> pInitialTransform,
  70. const ActorId serversActorId
  71. ) {
  72. TiXmlElement* pRoot = XmlResourceLoader::LoadAndReturnRootXmlElement(actorResource);
  73. if (!pRoot)
  74. {
  75. GCC_ERROR("Failed to create actor from resource: " + std::string(actorResource));
  76. return StrongActorPtr();
  77. }
  78. // create the actor instance
  79. ActorId nextActorId = serversActorId;
  80. if (nextActorId == INVALID_ACTOR_ID)
  81. {
  82. nextActorId = GetNextActorId();
  83. }
  84. StrongActorPtr pActor(GCC_NEW Actor(nextActorId));
  85. if (!pActor->Init(pRoot))
  86. {
  87. GCC_ERROR("Failed to initialize actor: " + std::string(actorResource));
  88. return StrongActorPtr();
  89. }
  90. bool initialTransformSet = false;
  91. // Loop through each child element and load the componet
  92. for (TiXmlElement* pNode = pRoot->FirstChildElement(); pNode; pNode = pNode->NextSiblingElement())
  93. {
  94. StrongActorComponentPtr pComponent(VCreateComponent(pNode));
  95. if (pComponent)
  96. {
  97. pActor->AddComponent(pComponent);
  98. pComponent->SetOwner(pActor);
  99. }
  100. else
  101. {
  102. // If an error occurs, we kill the actor and bail. We could keep going, but the actor is will only be
  103. // partially complete so it's not worth it. Note that the pActor instance will be destroyed because it
  104. // will fall out of scope with nothing else pointing to it.
  105. // [munnellg] I'm pretty sure this leaks because you need to call Actor::Destroy before actor is destructed
  106. return StrongActorPtr();
  107. }
  108. }
  109. if (overrides)
  110. {
  111. ModifyActor(pActor, overrides);
  112. }
  113. // This is a bit of a hack to get the initial transform of the transform component set before the
  114. // other components (like PhysicsComponent) read it.
  115. std::shared_ptr<TransformComponent> pTransformComponent = MakeStrongPtr(pActor->GetComponent<TransformComponent>(TransformComponent::g_Name));
  116. if (pInitialTransform && pTransformComponent)
  117. {
  118. pTransformComponent->SetPosition(geometry::GetPosition(pInitialTransform.value()));
  119. }
  120. // Now that the actor has been fully created, run the post init phase
  121. pActor->PostInit();
  122. return pActor;
  123. }
  124. StrongActorComponentPtr ActorFactory::VCreateComponent(TiXmlElement* pData)
  125. {
  126. const char* name = pData->Value();
  127. StrongActorComponentPtr pComponent(m_componentFactory.Create(ActorComponent::GetIdFromName(name)));
  128. // initialize the component if we found one
  129. if (pComponent)
  130. {
  131. if (!pComponent->VInit(pData))
  132. {
  133. GCC_ERROR("Component failed to initialize: " + std::string(name));
  134. return StrongActorComponentPtr();
  135. }
  136. }
  137. else
  138. {
  139. GCC_ERROR("Couldn't find ActorComponent named " + std::string(name));
  140. return StrongActorComponentPtr(); // fail
  141. }
  142. // pComponent will be NULL if the component wasn't found. This isn't necessarily an error since you might have a
  143. // custom CreateComponent() function in a sub class.
  144. return pComponent;
  145. }
  146. void ActorFactory::ModifyActor(StrongActorPtr pActor, TiXmlElement* overrides)
  147. {
  148. // Loop through each child element and load the element
  149. for (TiXmlElement* pNode = overrides->FirstChildElement(); pNode; pNode = pNode->NextSiblingElement())
  150. {
  151. ComponentId componentId = ActorComponent::GetIdFromName(pNode->Value());
  152. StrongActorComponentPtr pComponent = MakeStrongPtr(pActor->GetComponent<ActorComponent>(componentId));
  153. if (pComponent)
  154. {
  155. pComponent->VInit(pNode);
  156. // [mrmike] - added post press to ensure that components that need it have
  157. // Events generated that can notify subsystems when changes happen.
  158. // This was done to have SceneNode derived classes respond to RenderComponent
  159. // changes.
  160. pComponent->VOnChanged();
  161. }
  162. else
  163. {
  164. pComponent = VCreateComponent(pNode);
  165. if (pComponent)
  166. {
  167. pActor->AddComponent(pComponent);
  168. pComponent->SetOwner(pActor);
  169. }
  170. }
  171. }
  172. }