CmGameObject.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #include "CmGameObject.h"
  2. #include "CmComponent.h"
  3. #include "CmException.h"
  4. #include "CmDebug.h"
  5. namespace CamelotEngine
  6. {
  7. GameObject::GameObject(const String& name)
  8. :mName(name), mPosition(Vector3::ZERO), mRotation(Quaternion::IDENTITY), mScale(Vector3::ZERO),
  9. mCachedLocalTfrm(Matrix4::IDENTITY), mIsCachedLocalTfrmUpToDate(false),
  10. mCachedWorldTfrm(Matrix4::IDENTITY), mIsCachedWorldTfrmUpToDate(false),
  11. mCustomWorldTfrm(Matrix4::IDENTITY), mIsCustomTfrmModeActive(false),
  12. mParent(nullptr), mIsDestroyed(false)
  13. { }
  14. GameObject::~GameObject()
  15. {
  16. if(!mIsDestroyed)
  17. destroy();
  18. }
  19. void GameObject::destroy()
  20. {
  21. mIsDestroyed = true;
  22. if(mParent != nullptr)
  23. mParent->removeChild(this);
  24. for(auto iter = mChildren.begin(); iter != mChildren.end(); ++iter)
  25. (*iter)->destroy();
  26. mChildren.clear();
  27. for(auto iter = mComponents.begin(); iter != mComponents.end(); ++iter)
  28. (*iter)->destroy();
  29. mComponents.clear();
  30. }
  31. /************************************************************************/
  32. /* Transform */
  33. /************************************************************************/
  34. void GameObject::setPosition(const Vector3& position)
  35. {
  36. mPosition = position;
  37. markTfrmDirty();
  38. }
  39. void GameObject::setRotation(const Quaternion& rotation)
  40. {
  41. mRotation = rotation;
  42. markTfrmDirty();
  43. }
  44. void GameObject::setScale(const Vector3& scale)
  45. {
  46. mScale = scale;
  47. markTfrmDirty();
  48. }
  49. const Matrix4& GameObject::getWorldTfrm()
  50. {
  51. if(!mIsCachedWorldTfrmUpToDate)
  52. updateWorldTfrm();
  53. return mCachedWorldTfrm;
  54. }
  55. const Matrix4& GameObject::getLocalTfrm()
  56. {
  57. if(!mIsCachedLocalTfrmUpToDate)
  58. updateLocalTfrm();
  59. return mCachedLocalTfrm;
  60. }
  61. void GameObject::markTfrmDirty()
  62. {
  63. mIsCachedLocalTfrmUpToDate = false;
  64. if(mIsCachedWorldTfrmUpToDate) // If it's already marked as dirty, no point is recursing the hierarchy again
  65. {
  66. mIsCachedWorldTfrmUpToDate = false;
  67. for(auto iter = mChildren.begin(); iter != mChildren.end(); ++iter)
  68. {
  69. (*iter)->markTfrmDirty();
  70. }
  71. }
  72. }
  73. void GameObject::updateWorldTfrm()
  74. {
  75. if(mParent != nullptr)
  76. mCachedWorldTfrm = getLocalTfrm() * mParent->getWorldTfrm();
  77. else
  78. mCachedWorldTfrm = getLocalTfrm();
  79. mIsCachedWorldTfrmUpToDate = true;
  80. }
  81. void GameObject::updateLocalTfrm()
  82. {
  83. mCachedLocalTfrm.makeTransform(mPosition, mScale, mRotation);
  84. mIsCachedLocalTfrmUpToDate = true;
  85. }
  86. /************************************************************************/
  87. /* Hierarchy */
  88. /************************************************************************/
  89. void GameObject::setParent(GameObjectPtr parent)
  90. {
  91. if(parent == nullptr)
  92. {
  93. CM_EXCEPT(InternalErrorException,
  94. "Parent is not allowed to be NULL.");
  95. }
  96. if(mParent != parent)
  97. {
  98. if(mParent != nullptr)
  99. mParent->removeChild(this);
  100. if(parent != nullptr)
  101. parent->addChild(this);
  102. mParent = parent;
  103. markTfrmDirty();
  104. }
  105. }
  106. GameObjectPtr GameObject::getChild(unsigned int idx) const
  107. {
  108. if(idx < 0 || idx >= mChildren.size())
  109. {
  110. CM_EXCEPT(InternalErrorException,
  111. "Child index out of range.");
  112. }
  113. return mChildren[idx];
  114. }
  115. int GameObject::indexOfChild(const GameObjectPtr child) const
  116. {
  117. for(int i = 0; i < (int)mChildren.size(); i++)
  118. {
  119. if(mChildren[i] == child)
  120. return i;
  121. }
  122. return -1;
  123. }
  124. void GameObject::addChild(GameObject* object)
  125. {
  126. //mChildren.push_back(object); // TODO - Not implemented. I'm not sure what's the best way to handle "this" ptr and smart ptrs
  127. }
  128. void GameObject::removeChild(GameObject* object)
  129. {
  130. //auto result = find(mChildren.begin(), mChildren.end(), object);
  131. //if(result != mChildren.end())
  132. // mChildren.erase(result);
  133. //else
  134. //{
  135. // CM_EXCEPT(InternalErrorException,
  136. // "Trying to remove a child but it's not a child of the transform.");
  137. //}
  138. }
  139. void GameObject::destroyComponent(ComponentPtr component)
  140. {
  141. if(component == nullptr)
  142. {
  143. LOGDBG("Trying to remove a null component");
  144. return;
  145. }
  146. auto iter = std::find(mComponents.begin(), mComponents.end(), component);
  147. if(iter != mComponents.end())
  148. {
  149. (*iter)->destroy();
  150. mComponents.erase(iter);
  151. }
  152. else
  153. LOGDBG("Trying to remove a component that doesn't exist on this GameObject.");
  154. }
  155. }