WorldScene.h 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. #pragma once
  2. #include "EntityViewDefinitions.h"
  3. #include "GameObject.h"
  4. #include "MetadataComponent.h"
  5. #include "ObjectMaterialComponent.h"
  6. #include "ObjectPool.h"
  7. #include "ObjectRegister.h"
  8. #include "System.h"
  9. #include "WorldTask.h"
  10. class WorldSystem;
  11. struct ComponentsConstructionInfo;
  12. struct WorldComponentsConstructionInfo
  13. {
  14. WorldComponentsConstructionInfo()
  15. {
  16. m_spatialConstructionInfo = nullptr;
  17. m_objectMaterialConstructionInfo = nullptr;
  18. }
  19. // Perform a complete copy, instantiating (with new) every member variable pointer, instead of just assigning the pointer to the same memory
  20. void completeCopy(const WorldComponentsConstructionInfo &p_other)
  21. {
  22. Utilities::performCopy<SpatialComponent::SpatialComponentConstructionInfo>(&m_spatialConstructionInfo, &p_other.m_spatialConstructionInfo);
  23. Utilities::performCopy<ObjectMaterialComponent::ObjectMaterialComponentConstructionInfo>(&m_objectMaterialConstructionInfo, &p_other.m_objectMaterialConstructionInfo);
  24. }
  25. void deleteConstructionInfo()
  26. {
  27. if(m_spatialConstructionInfo != nullptr)
  28. delete m_spatialConstructionInfo;
  29. m_spatialConstructionInfo = nullptr;
  30. if(m_objectMaterialConstructionInfo != nullptr)
  31. delete m_objectMaterialConstructionInfo;
  32. m_objectMaterialConstructionInfo = nullptr;
  33. }
  34. SpatialComponent::SpatialComponentConstructionInfo *m_spatialConstructionInfo;
  35. ObjectMaterialComponent::ObjectMaterialComponentConstructionInfo *m_objectMaterialConstructionInfo;
  36. };
  37. class WorldScene : public SystemScene
  38. {
  39. public:
  40. WorldScene(SystemBase *p_system, SceneLoader *p_sceneLoader);
  41. ~WorldScene()
  42. {
  43. // Delete all entities
  44. m_entityRegistry.clear();
  45. }
  46. ErrorCode init();
  47. ErrorCode setup(const PropertySet &p_properties);
  48. void exportSetup(PropertySet &p_propertySet);
  49. void update(const float p_deltaTime);
  50. ErrorCode preload() { return ErrorCode::Success; }
  51. void loadInBackground() { }
  52. // Get all the created components of the given entity that belong to this scene
  53. std::vector<SystemObject *> getComponents(const EntityID p_entityID);
  54. // Add a components to an existing entity. Fails if the entity doesn't exist
  55. ErrorCode addComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
  56. EntityID createEntity(const ComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
  57. void exportEntity(const EntityID p_entityID, ComponentsConstructionInfo &p_constructionInfo);
  58. std::vector<SystemObject*> createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
  59. std::vector<SystemObject*> createComponents(const EntityID p_entityID, const WorldComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
  60. void exportComponents(const EntityID p_entityID, ComponentsConstructionInfo &p_constructionInfo);
  61. void releaseObject(SystemObject *p_systemObject);
  62. ErrorCode destroyObject(SystemObject *p_systemObject);
  63. SystemObject *createComponent(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
  64. SystemObject *createComponent(const EntityID p_entityID, const ObjectMaterialComponent::ObjectMaterialComponentConstructionInfo &p_constructionInfo, const bool p_startLoading = true)
  65. {
  66. ObjectMaterialComponent *objectMaterialComponent = nullptr;
  67. objectMaterialComponent = &addComponent<ObjectMaterialComponent>(p_entityID, this, p_constructionInfo.m_name, p_entityID);
  68. objectMaterialComponent->setActive(p_constructionInfo.m_active);
  69. objectMaterialComponent->m_materialType = p_constructionInfo.m_materialType;
  70. objectMaterialComponent->init();
  71. return objectMaterialComponent;
  72. }
  73. SystemObject *createComponent(const EntityID p_entityID, const SpatialComponent::SpatialComponentConstructionInfo &p_constructionInfo, const bool p_startLoading = true)
  74. {
  75. SpatialComponent *spatialComponent = nullptr;
  76. spatialComponent = &addComponent<SpatialComponent>(p_entityID, this, p_constructionInfo.m_name, p_entityID);
  77. spatialComponent->setActive(p_constructionInfo.m_active);
  78. spatialComponent->m_spatialData.setLocalPosition(p_constructionInfo.m_localPosition);
  79. spatialComponent->m_spatialData.setLocalScale(p_constructionInfo.m_localScale);
  80. // If the rotation quaternion is empty, use the Euler angle rotation
  81. if(p_constructionInfo.m_localRotationQuaternion == glm::quat())
  82. spatialComponent->m_spatialData.setLocalRotation(p_constructionInfo.m_localRotationEuler);
  83. else
  84. spatialComponent->m_spatialData.setLocalRotation(p_constructionInfo.m_localRotationQuaternion);
  85. // Perform a spatial data update, so that all the transform matrices are calculated
  86. spatialComponent->m_spatialData.update();
  87. return spatialComponent;
  88. }
  89. void exportComponent(ObjectMaterialComponent::ObjectMaterialComponentConstructionInfo &p_constructionInfo, const ObjectMaterialComponent &p_component)
  90. {
  91. p_constructionInfo.m_active = p_component.isObjectActive();
  92. p_constructionInfo.m_name = p_component.getName();
  93. p_constructionInfo.m_materialType = p_component.getObjectMaterialType();
  94. }
  95. void exportComponent(SpatialComponent::SpatialComponentConstructionInfo &p_constructionInfo, SpatialComponent &p_component)
  96. {
  97. p_constructionInfo.m_active = p_component.isObjectActive();
  98. p_constructionInfo.m_name = p_component.getName();
  99. // Call update to make sure the spatial data is current
  100. p_component.m_spatialData.update();
  101. p_component.m_spatialData.calculateLocalRotationEuler();
  102. p_constructionInfo.m_localPosition = p_component.getSpatialDataChangeManager().getLocalSpaceData().m_spatialData.m_position;
  103. p_constructionInfo.m_localRotationEuler = p_component.getSpatialDataChangeManager().getLocalSpaceData().m_spatialData.m_rotationEuler;
  104. p_constructionInfo.m_localRotationQuaternion = p_component.getSpatialDataChangeManager().getLocalSpaceData().m_spatialData.m_rotationQuat;
  105. p_constructionInfo.m_localScale = p_component.getSpatialDataChangeManager().getLocalSpaceData().m_spatialData.m_scale;
  106. }
  107. void changeOccurred(ObservedSubject *p_subject, BitMask p_changeType);
  108. void receiveData(const DataType p_dataType, void *p_data, const bool p_deleteAfterReceiving);
  109. SystemTask *getSystemTask() { return m_worldTask; };
  110. Systems::TypeID getSystemType() { return Systems::TypeID::World; };
  111. BitMask getDesiredSystemChanges() { return Systems::Changes::Generic::CreateObject || Systems::Changes::Generic::DeleteObject; }
  112. BitMask getPotentialSystemChanges() { return Systems::Changes::None; }
  113. // Find and return an entity ID of an entity matching the given name
  114. // Returns NULL_ENTITY_ID if no entity was found
  115. inline EntityID getEntity(const std::string &p_name) const
  116. {
  117. // Iterate every entity and add its entity ID and name to the list
  118. for(auto entity : m_entityRegistry.view<EntityID>())
  119. {
  120. // Try to get the metadata component
  121. if(auto metadataComponent = m_entityRegistry.try_get<MetadataComponent>(entity); metadataComponent != nullptr)
  122. {
  123. if(metadataComponent->m_name == p_name)
  124. return entity;
  125. }
  126. }
  127. return NULL_ENTITY_ID;
  128. }
  129. // Adds a component with the given parameters and returns a reference to it
  130. template <class T_Component, class... T_Args>
  131. T_Component &addComponent(EntityID p_entity, T_Args&&... p_args)
  132. {
  133. return m_entityRegistry.emplace_or_replace<T_Component>(p_entity, std::forward<T_Args>(p_args)...);
  134. }
  135. // Removes a component from the given entity
  136. template <class T_Component>
  137. inline void removeComponent(const EntityID p_entity)
  138. {
  139. m_entityRegistry.remove<T_Component>(p_entity);
  140. }
  141. // Removes an entity with all its components
  142. inline void removeEntity(const EntityID p_entity)
  143. {
  144. m_entityRegistry.destroy(p_entity);
  145. }
  146. // Increases the size of the pool for a given component type
  147. // When multi-threading is enabled, creating views concurrently on a mostly empty registry can sometimes trigger an access violation error,
  148. // because a view of a non-existent component creates an empty pool for that component, hence creating views for the first time is not thread-safe.
  149. // As a solution, reserve must be called for every component type, to create its pool ahead of time
  150. template <class T_Component>
  151. void reserve(const size_t p_capacity)
  152. {
  153. m_entityRegistry.storage<T_Component>().reserve(p_capacity);
  154. }
  155. // Get the internal pool size of a given component
  156. template <class T_Component>
  157. size_t getPoolSize()
  158. {
  159. return m_entityRegistry.storage<T_Component>().size();
  160. }
  161. inline entt::basic_registry<EntityID> &getEntityRegistry() { return m_entityRegistry; }
  162. private:
  163. struct GameObjectAndParent
  164. {
  165. GameObjectAndParent()
  166. {
  167. m_gameObject = nullptr;
  168. m_parent = 0;
  169. }
  170. GameObjectAndParent(GameObject *p_gameObject, decltype(GameObject::m_GameObjectID) p_parent)
  171. {
  172. m_gameObject = p_gameObject;
  173. m_parent = p_parent;
  174. }
  175. GameObject *m_gameObject;
  176. decltype(GameObject::m_GameObjectID) m_parent;
  177. };
  178. struct GameObjectAndChildren
  179. {
  180. GameObjectAndChildren()
  181. {
  182. m_gameObject = nullptr;
  183. }
  184. GameObjectAndChildren(GameObject *p_gameObject)
  185. {
  186. m_gameObject = p_gameObject;
  187. }
  188. GameObject *m_gameObject;
  189. std::vector<decltype(GameObject::m_GameObjectID)> m_children;
  190. };
  191. inline EntityID addEntity()
  192. {
  193. return m_entityRegistry.create();
  194. }
  195. inline EntityID addEntity(EntityID p_entityID)
  196. {
  197. return m_entityRegistry.create(p_entityID);
  198. }
  199. entt::basic_registry<EntityID> m_entityRegistry;
  200. std::vector<GameObjectAndParent> m_unassignedParents;
  201. std::vector<GameObjectAndChildren> m_unassignedChildren;
  202. WorldTask *m_worldTask;
  203. ObjectRegisterConcurrent<GameObject*> m_objectRegister;
  204. };