22 mutable std::shared_mutex entities_mtx;
23 std::mutex refresh_mtx;
27 int negativeEntityId = -1;
30 std::unordered_map<EntityID, std::unique_ptr<Entity>> entities;
32 std::array<std::vector<Entity*>, maxGroups> groupedEmptyEntities;
33 std::array<std::vector<Entity*>, maxGroups> groupedNodeEntities;
34 std::array<std::vector<Entity*>, maxGroups> groupedLinkEntities;
36 std::vector<Entity*> visible_emptyEntities;
37 std::vector<Entity*> visible_nodes;
38 std::vector<Entity*> visible_links;
40 std::array<std::vector<Entity*>, maxGroups> visible_groupedEmptyEntities;
41 std::array<std::vector<Entity*>, maxGroups> visible_groupedNodeEntities;
42 std::array<std::vector<Entity*>, maxGroups> visible_groupedLinkEntities;
44 bool _update_active_entities =
false;
47 std::list<SimulationStep> steps;
51 std::stack<std::unique_ptr<Command>> undoStack;
53 std::vector<EntityID> movedNodes;
54 std::mutex movedNodesMutex;
56 bool idTextEnabled =
false;
58 bool arrowheadsEnabled =
false;
59 bool last_arrowheadsEnabled =
false;
61 std::unordered_map<std::string, std::vector<std::string>> componentNames;
63 std::unique_ptr<Grid> grid;
69 void setThreader(
Threader& mthreader) {
70 _threader = &mthreader;
77 if (_threader && !_threader->t_queue.shuttingDown) {
82 for (
auto& e : movedNodes) {
83 auto* ent =
dynamic_cast<NodeEntity*
>(getEntityFromId(e));
85 for (
auto& linkId : ent->getInLinks()) {
86 auto* linkEntity =
dynamic_cast<LinkEntity*
>(getEntityFromId(linkId));
88 linkEntity->cellUpdate();
90 for (
auto& link : ent->getOutLinks()) {
91 auto* linkEntity =
dynamic_cast<LinkEntity*
>(getEntityFromId(link));
93 linkEntity->cellUpdate();
97 _threader->parallel(movedNodes.size(), [&](
int start,
int end) {
98 for (
int i = start; i < end; i++) {
99 auto* ent =
dynamic_cast<NodeEntity*
>(getEntityFromId(movedNodes[i]));
101 for (
auto& link : ent->getInLinks()) {
102 auto* linkEntity =
dynamic_cast<LinkEntity*
>(getEntityFromId(link));
104 linkEntity->updateConnection();
109 _threader->parallel(movedNodes.size(), [&](
int start,
int end) {
110 for (
int i = start; i < end; i++) {
111 auto* ent =
dynamic_cast<NodeEntity*
>(getEntityFromId(movedNodes[i]));
113 for (
auto& link : ent->getOutLinks()) {
114 auto* linkEntity =
dynamic_cast<LinkEntity*
>(getEntityFromId(link));
117 if (arrowheadsEnabled &&
118 linkEntity->type == LinkEntity::ConnectionType::GHOST_PORT_TO_PORT)
121 linkEntity->updateConnection();
126 _threader->parallel(movedNodes.size(), [&](
int start,
int end) {
127 for (
int i = start; i < end; i++) {
128 auto* ent =
dynamic_cast<NodeEntity*
>(getEntityFromId(movedNodes[i]));
130 if (arrowheadsEnabled) {
133 for (
auto& link : ent->getOutLinks()) {
134 auto* linkEntity =
dynamic_cast<LinkEntity*
>(getEntityFromId(link));
137 linkEntity->type == LinkEntity::ConnectionType::GHOST_PORT_TO_PORT)
139 linkEntity->updateConnection();
144 for (
auto& link : toNode->getOutLinks()) {
145 auto* adjacent_linkEntity =
dynamic_cast<LinkEntity*
>(getEntityFromId(link));
148 adjacent_linkEntity->type == LinkEntity::ConnectionType::GHOST_PORT_TO_PORT)
150 adjacent_linkEntity->updateConnection();
156 for (
auto& link : ent->getInLinks()) {
157 auto* linkEntity =
dynamic_cast<LinkEntity*
>(getEntityFromId(link));
160 linkEntity->type != LinkEntity::ConnectionType::GHOST_PORT_TO_PORT)
164 for (
auto& link : fromNode->getOutLinks()) {
165 auto* adjacent_linkEntity =
dynamic_cast<LinkEntity*
>(getEntityFromId(link));
168 adjacent_linkEntity->type == LinkEntity::ConnectionType::GHOST_PORT_TO_PORT)
170 adjacent_linkEntity->updateConnection();
182 _threader->parallel(visible_emptyEntities.size(), [&](
int start,
int end) {
183 for (
int i = start; i < end; i++) {
184 if (visible_emptyEntities[i]) {
185 visible_emptyEntities[i]->update(deltaTime);
191 _threader->parallel(visible_nodes.size(), [&](
int start,
int end) {
192 for (
int i = start; i < end; i++) {
193 if (visible_nodes[i]) {
194 visible_nodes[i]->update(deltaTime);
201 _threader->parallel(visible_links.size(), [&](
int start,
int end) {
203 for (
int i = start; i < end; i++) {
204 if (visible_links[i]) {
205 visible_links[i]->update(deltaTime);
214 for (
auto& e : visible_emptyEntities) {
215 if (!e->isActive())
continue;
217 e->update(deltaTime);
220 for (
auto& e : visible_nodes) {
221 if (!e->isActive())
continue;
223 e->update(deltaTime);
228 for (
auto& e : visible_links) {
229 if (!e->isActive())
continue;
231 e->update(deltaTime);
237 void updateFully(
float deltaTime = 1.0f)
240 for (
auto& e : entities) {
241 if (!e.second || !e.second->isActive())
continue;
243 e.second->update(deltaTime);
248 void refresh(
ICamera* camera =
nullptr)
251 if (grid && (camera->hasChanged() || grid->gridLevelChanged())) {
252 bool interceptedCellsChanged = grid->setIntersectedCameraCells(*camera);
254 if (interceptedCellsChanged) {
255 aboutTo_updateActiveEntities();
257 camera->refreshCamera();
260 if (_update_active_entities) {
261 std::scoped_lock lock(refresh_mtx);
263 _update_active_entities =
false;
265 updateVisibleEntities();
266 updateActiveEntities();
271 void aboutTo_updateActiveEntities() {
272 std::scoped_lock lock(refresh_mtx);
273 _update_active_entities =
true;
276 void updateActiveEntities();
278 void updateVisibleEntities();
280 void AddToGroup(
EmptyEntity* mEntity, Group mGroup)
282 groupedEmptyEntities[mGroup].emplace_back(mEntity);
283 aboutTo_updateActiveEntities();
286 void AddToGroup(
NodeEntity* mEntity, Group mGroup)
288 groupedNodeEntities[mGroup].emplace_back(mEntity);
289 aboutTo_updateActiveEntities();
292 void AddLinkToGroup(
LinkEntity* mEntity, Group mGroup)
294 groupedLinkEntities[mGroup].emplace_back(mEntity);
295 aboutTo_updateActiveEntities();
298 const std::unordered_map<EntityID, std::unique_ptr<Entity>>& getEntities()
const {
302 template <
typename T>
303 std::vector<Entity*> getVisible() {
304 if constexpr (std::is_same_v<T, EmptyEntity>) {
305 return visible_emptyEntities;
307 else if constexpr (std::is_same_v<T, NodeEntity>) {
308 return visible_nodes;
310 else if constexpr (std::is_same_v<T, LinkEntity>) {
311 return visible_links;
314 static_assert(
sizeof(T) == 0,
"Unsupported entity type.");
318 template <
typename T>
319 std::vector<Entity*>& getVisibleGroup(Group mGroup) {
320 if constexpr (std::is_same_v<T, EmptyEntity>) {
321 return visible_groupedEmptyEntities[mGroup];
323 else if constexpr (std::is_same_v<T, NodeEntity>) {
324 return visible_groupedNodeEntities[mGroup];
326 else if constexpr (std::is_same_v<T, LinkEntity>) {
327 return visible_groupedLinkEntities[mGroup];
330 static_assert(
sizeof(T) == 0,
"Unsupported entity type.");
334 template <
typename T>
335 void getAllTypeEntities(std::vector<Entity*>& output) {
338 if constexpr (std::is_same_v<T, EmptyEntity>) {
339 for (
auto& groupPair : groupedEmptyEntities) {
340 output.insert(output.end(), groupPair.begin(), groupPair.end());
343 else if constexpr (std::is_same_v<T, NodeEntity>) {
344 for (
auto& groupPair : groupedNodeEntities) {
345 output.insert(output.end(), groupPair.begin(), groupPair.end());
348 else if constexpr (std::is_same_v<T, LinkEntity>) {
349 for (
auto& groupPair : groupedLinkEntities) {
350 output.insert(output.end(), groupPair.begin(), groupPair.end());
354 static_assert(
sizeof(T) == 0,
"Unsupported entity type.");
358 template <
typename T>
359 std::vector<Entity*>& getGroup(Group mGroup) {
360 if constexpr (std::is_same_v<T, EmptyEntity>) {
361 return groupedEmptyEntities[mGroup];
363 else if constexpr (std::is_same_v<T, NodeEntity>) {
364 return groupedNodeEntities[mGroup];
366 else if constexpr (std::is_same_v<T, LinkEntity>) {
367 return groupedLinkEntities[mGroup];
369 else if constexpr (std::is_same_v<T, Entity>) {
370 return groupedLinkEntities[mGroup];
373 static_assert(
sizeof(T) == 0,
"Unsupported entity type.");
377 inline std::vector<Entity*> getGroup_All(Group mGroup) {
378 std::vector<Entity*> result;
380 auto& empties = groupedEmptyEntities[mGroup];
381 auto& nodes = groupedNodeEntities[mGroup];
382 auto& links = groupedLinkEntities[mGroup];
384 result.reserve(empties.size() + nodes.size() + links.size());
386 result.insert(result.end(), empties.begin(), empties.end());
387 result.insert(result.end(), nodes.begin(), nodes.end());
388 result.insert(result.end(), links.begin(), links.end());
393 template <
typename T,
typename... TArgs>
394 T& addEntityNoId(TArgs&&... mArgs)
396 T* e(
new T(*
this, std::forward<TArgs>(mArgs)...));
398 std::unique_lock lock(entities_mtx);
399 e->setId(negativeEntityId--);
400 std::unique_ptr<T> uPtr{ e };
401 entities.emplace(e->getId(), std::move(uPtr));
406 aboutTo_updateActiveEntities();
411 template <
typename T,
typename... TArgs>
412 T& addEntity(TArgs&&... mArgs)
414 T* e(
new T(*
this, std::forward<TArgs>(mArgs)...));
416 std::unique_lock lock(entities_mtx);
417 e->setId(lastEntityId++);
418 std::unique_ptr<T> uPtr{ e };
419 entities.emplace(e->getId(), std::move(uPtr));
424 aboutTo_updateActiveEntities();
429 template <
typename T,
typename... TArgs>
430 T& addEntityWithId(EntityID customId, TArgs&&... mArgs)
432 T* e(
new T(*
this, std::forward<TArgs>(mArgs)...));
435 std::unique_lock lock(entities_mtx);
437 std::unique_ptr<T> uPtr{ e };
438 entities.emplace(customId, std::move(uPtr));
443 aboutTo_updateActiveEntities();
447 template <
typename T,
typename... TArgs>
448 T& addEntityFromParent(
Entity* pEntity,
const char* newID =
"", TArgs&&... mArgs)
450 T* e(
new T(*
this, std::forward<TArgs>(mArgs)...));
452 std::unique_lock lock(entities_mtx);
454 if ((newID != NULL) && (newID[0] !=
'\0')) {
456 EntityIDUtils::toString(pEntity->getId())
463 EntityIDUtils::toString(pEntity->getId())
465 +
"-" + EntityIDUtils::toString(negativeEntityId--)
469 std::unique_ptr<T> uPtr{ e };
470 entities.emplace(e->getId(), std::move(uPtr));
473 aboutTo_updateActiveEntities();
478 void resetEntityId() {
482 void setNewLastEntityId() {
483 std::unique_lock lock(entities_mtx);
485 int maxIntId = std::numeric_limits<int>::min();
486 bool foundInt =
false;
488 for (
const auto& [
id, ptr] : entities)
490 if (std::holds_alternative<int>(
id)) {
491 int value = std::get<int>(
id);
492 if (value > maxIntId) {
500 lastEntityId = maxIntId + 1;
505 inline Entity* getEntityFromId(EntityID mId) {
506 std::shared_lock lock(entities_mtx);
507 return entities[mId].get();
510 inline std::vector<Entity*> getEntities_FromIds(std::vector<EntityID> mIds) {
511 std::shared_lock lock(entities_mtx);
513 std::vector<Entity*> result;
514 result.reserve(mIds.size());
516 for (EntityID
id : mIds) {
517 if (entities.contains(
id)) {
518 result.push_back(entities[
id].get());
539 bool hasEntity(EntityID mId) {
540 std::shared_lock lock(entities_mtx);
541 return entities.contains(mId);
544 void clearAllEntities() {
545 for (
auto& group : groupedNodeEntities) {
548 for (
auto& group : groupedLinkEntities) {
552 std::unique_lock lock(entities_mtx);
557 void removeAllEntites() {
558 for (
auto group : groupNames) {
559 removeAllEntitiesFromGroup(group.first);
560 removeAllEntitiesFromLinkGroup(group.first);
564 void removeAllEntitiesFromGroup(Group mGroup) {
565 auto& entitiesInGroup = groupedNodeEntities[mGroup];
567 for (
auto& entity : entitiesInGroup) {
572 void removeAllEntitiesFromEmptyGroup(Group mGroup) {
573 auto& entitiesInGroup = groupedEmptyEntities[mGroup];
575 for (
auto& entity : entitiesInGroup) {
580 void removeAllEntitiesFromLinkGroup(Group mGroup) {
581 auto& entitiesInGroup = groupedLinkEntities[mGroup];
583 for (
auto& entity : entitiesInGroup) {
588 std::vector<EntityID> adjacentEntities(
Entity* mainEntity, Group group) {
589 std::vector<EntityID> nearbyEntities;
591 auto adjacentCells = grid->getAdjacentCells(*mainEntity, grid->getGridLevel());
593 for (
Cell* adjCell : adjacentCells) {
594 for (
auto& neighbor : adjCell->nodes) {
595 if (getEntityFromId(neighbor)->hasGroup(group) && (getEntityFromId(neighbor) != mainEntity)) {
596 nearbyEntities.push_back(neighbor);
601 return nearbyEntities;
604 enum groupLabels : std::size_t
607 groupBackgroundLayer,
612 groupSelectedEntities,
614 groupDebugBoxEntities,
615 groupDebugRectangleEntities,
625 groupPathLinksHolder,
640 groupWireframeSphereEmpties,
653 std::unordered_map<Group, std::string> groupNames = {
654 {groupBackgroundLayer,
"groupBackgroundLayer" },
655 {panelBackground,
"panelBackground"},
657 { groupGridLinks,
"groupGridLinks" },
659 { groupSelectedEntities,
"groupSelectedEntities" },
661 {groupDebugBoxEntities,
"groupDebugBoxEntities"},
662 {groupDebugRectangleEntities,
"groupDebugRectangleEntities"},
664 { groupLinks_0,
"groupLinks_0" },
665 {groupGroupLinks_0,
"groupGroupLinks_0"},
666 {groupGroupLinks_1,
"groupGroupLinks_1"},
668 {groupPathLinks,
"groupPathLinks"},
670 {groupPathInnerLinks,
"groupPathInnerLinks"},
672 {groupPathLinksHolder,
"groupPathLinksHolder"},
674 {groupArrowHeads_0,
"groupArrowHeads_0"},
676 { groupNodes_0,
"groupNodes_0" },
677 { groupGroupNodes_0,
"groupGroupNodes_0"},
678 { groupGroupNodes_1,
"groupGroupNodes_1"},
680 { groupMinimapNodes,
"groupMinimapNodes" },
682 { groupEmpties,
"groupEmpties" },
683 { groupSphereEmpties,
"groupSphereEmpties" },
685 { groupWireframeSphereEmpties,
"groupWireframeSphereEmpties" },
687 { groupColliders,
"groupColliders" },
688 { groupRenderSprites,
"groupRenderSprites" },
689 { groupPorts,
"groupPorts" },
690 { groupPortSlots,
"groupPortSlots" },
693 { textLabels,
"textLabels" },
699 void addGroup(std::string groupName) {
701 groupNames.insert(std::make_pair(newGroup, groupName));
704 std::string getGroupName(Group mGroup)
const;
706 void scanComponentNames(
const std::string& folderPath);
708 void setComponentNames();
710 std::vector<Entity*> collectVisibleEntities(
711 std::initializer_list<Manager::groupLabels> groupNames,
712 Taz::EntityType type);
714 std::vector<Entity*> collectEntities(
715 std::initializer_list<Manager::groupLabels> groupNames,
716 Taz::EntityType type);
718 bool entities_AllSameType(std::vector<Entity*> entities);