15 Link(
Manager& mManager, EntityID mfromId, EntityID mtoId)
22 EntityID mfromId, EntityID mtoId,
23 EntityID m_fromPort, EntityID m_toPort,
24 int m_fromSlot,
int m_toSlot
36 glm::vec3 mfromPos, glm::vec3 mtoPos
53 void onCreation()
override {
55 if (type != ConnectionType::DIRECT_POSITIONS) {
61 void addToGroup(Group mGroup)
override {
62 Entity::addToGroup(mGroup);
63 manager.AddLinkToGroup(
this, mGroup);
66 void removeGroup(Group mGroup)
override {
67 Entity::removeGroup(mGroup);
68 manager.aboutTo_updateActiveEntities();
75 void update(
float deltaTime)
override
77 Entity::update(deltaTime);
82 void cellUpdate()
override {
85 if (!ownerCells.empty()) {
86 auto level =
manager.grid->getGridLevel();
90 const auto& fromCell =
manager.grid->getCell(*fromNode, level);
91 const auto& toCell =
manager.grid->getCell(*toNode, level);
93 const auto& ownerFront = ownerCells.front();
94 const auto& ownerBack = ownerCells.back();
96 if (fromCell != ownerFront
97 || toCell != ownerBack)
107 void updateArrowHeads()
override {
108 if (
children.contains(LinkChildren_ToString(ARROWHEAD))) {
111 if (!fromNode || !toNode)
114 Entity* fromPortEntity =
nullptr;
115 Entity* toPortEntity =
nullptr;
118 fromPortEntity = getManager()->getEntityFromId(fromNode->
children[
fromPort]);
119 if (toNode->
children.contains(toPort))
120 toPortEntity = getManager()->getEntityFromId(toNode->
children[toPort]);
122 if (!fromPortEntity || !toPortEntity)
126 if (fromSlotIndex >= fromPortEntity->
children.size() ||
127 toSlotIndex >= toPortEntity->
children.size())
130 Entity* fromSlotEntity = getManager()->getEntityFromId(fromPortEntity->
children[fromSlotIndex]);
131 Entity* toSlotEntity = getManager()->getEntityFromId(toPortEntity->
children[toSlotIndex]);
132 if (!fromSlotEntity || !toSlotEntity)
139 glm::vec3 fromConnectionPoint = fromTransform.getPosition();
140 glm::vec3 toConnectionPoint = toTransform.getPosition();
142 glm::vec3 direction = toConnectionPoint - fromConnectionPoint;
143 float distance = glm::length(direction);
145 if (distance < 0.001f) {
150 glm::vec3 unitDirection = direction / distance;
153 float offset = 10.0f;
154 glm::vec3 arrowHeadPos = toConnectionPoint - unitDirection * offset;
157 float angleRadians = -atan2(direction.y, direction.x);
160 getManager()->getEntityFromId(
children[LinkChildren_ToString(ARROWHEAD)])->GetComponent<
TransformComponent>().position = arrowHeadPos;
161 getManager()->getEntityFromId(
children[LinkChildren_ToString(ARROWHEAD)])->GetComponent<
TransformComponent>().setRotation(glm::vec3(0.0f, 0.0f, angleRadians + glm::half_pi<float>()));
164 getManager()->getEntityFromId(
children[LinkChildren_ToString(ARROWHEAD)])->update(0.0f);
168 void setConnectionType(ConnectionType setType)
override {
174 int findNextAvailableSlotIndex(
Entity* portEntity) {
175 if (!portEntity || portEntity->
children.empty()) {
181 for (
const auto& [slotIndex, entityId] : portEntity->
children) {
182 if (std::get<int>(slotIndex) > maxIndex) {
183 maxIndex = std::get<int>(slotIndex);
192 void removeSlotAndReindex(
Entity* portEntity,
int slotIndexToRemove) {
193 if (!portEntity)
return;
196 auto it = portEntity->
children.find(slotIndexToRemove);
197 if (it == portEntity->
children.end()) {
202 Entity* slotEntity = getManager()->getEntityFromId(it->second);
204 slotEntity->destroy();
211 std::map<EntityID, EntityID> updatedChildren;
213 for (
auto& [slotIndex, entityId] : portEntity->
children) {
214 Entity* slot = portEntity->getManager()->getEntityFromId(entityId);
216 if (std::get<int>(slotIndex) > slotIndexToRemove) {
218 int newIndex = std::get<int>(slotIndex) - 1;
224 updatedChildren[newIndex] = entityId;
228 updatedChildren[slotIndex] = entityId;
232 portEntity->
children = std::move(updatedChildren);
235 int assignSlotIndex(
NodeEntity* node, EntityID newPort, EntityID oldPort,
int oldSlotIndex) {
237 if (std::holds_alternative<std::string>(oldPort) &&
238 !std::get<std::string>(oldPort).empty() &&
239 oldPort != newPort) {
241 Entity* oldPortEntity = getManager()->getEntityFromId(node->
children[oldPort]);
243 if (oldPortEntity && oldPortEntity->hasComponent<
PortComponent>()) {
244 removeSlotAndReindex(oldPortEntity, oldSlotIndex);
245 updateLinksSlotIndices(node, oldPort, oldSlotIndex,
true);
246 updateLinksSlotIndices(node, oldPort, oldSlotIndex,
false);
251 if (oldPort != newPort) {
252 if (std::get<std::string>(newPort).empty() || !node->
children.contains(newPort)) {
256 Entity* newPortEntity = getManager()->getEntityFromId(node->
children[newPort]);
257 if (!newPortEntity || !newPortEntity->hasComponent<
PortComponent>()) {
262 int newSlotIndex = findNextAvailableSlotIndex(newPortEntity);
265 auto& newSlot = node->getManager()->addEntityFromParent<
Empty>(newPortEntity);
266 newSlot.addToGroup(Manager::groupPortSlots);
270 portTransform.position,
277 newSlot.setParentEntity(newPortEntity);
280 newPortEntity->
children[newSlotIndex] = newSlot.getId();
283 slotComp.index = newSlotIndex;
291 void updateConnection()
override {
293 if (type == ConnectionType::NODE_TO_NODE) {
297 else if (type == ConnectionType::PORT_TO_PORT) {
304 EntityID newFromPort = getBestPortForConnection(fromTR->getPosition(), toTR->getPosition());
305 EntityID newToPort = getBestPortForConnection(toTR->getPosition(), fromTR->getPosition());
307 fromSlotIndex = assignSlotIndex(from, newFromPort,
fromPort, fromSlotIndex);
308 toSlotIndex = assignSlotIndex(to, newToPort, toPort, toSlotIndex);
313 else if (type == ConnectionType::DIRECT_POSITIONS) {
316 else if (type == ConnectionType::GHOST_PORT_TO_PORT) {
318 InnerLink* iL = &GetComponent<InnerLink>();
326 fromSlotIndex = iL_1->toSlotIndex;
327 toSlotIndex = iL_2->fromSlotIndex;
330 TAZ_ERROR(
"type doesn't exist for link");
333 updateConnectionPositions();
336 void updatePortSlots()
override {
341 from_port->update(0.0f);
342 Entity* to_port = getManager()->getEntityFromId(to->
children[toPort]);
343 to_port->update(0.0f);
346 Entity* from_port_slot = getManager()->getEntityFromId(from_port->
children[fromSlotIndex]);
347 from_port_slot->update(0.0f);
348 Entity* to_port_slot = getManager()->getEntityFromId(to_port->
children[toSlotIndex]);
349 to_port_slot->update(0.0f);
353 void updateConnectionPositions() {
354 if (type == ConnectionType::NODE_TO_NODE) {
359 GetComponent<TransformComponent>()
362 GetComponent<TransformComponent>()
366 type == ConnectionType::PORT_TO_PORT ||
367 type == ConnectionType::GHOST_PORT_TO_PORT
373 Entity* toPortEntity = getManager()->getEntityFromId(to->
children[toPort]);
375 if (!fromPortEntity || !toPortEntity ||
376 fromSlotIndex >= fromPortEntity->
children.size() ||
377 toSlotIndex >= toPortEntity->
children.size()) {
378 TAZ_ERROR(type == ConnectionType::PORT_TO_PORT ?
379 "updateConnectionPositions port-port"
380 :
"updateConnectionPositions Ghost port-port");
383 fromPos = getManager()->getEntityFromId(fromPortEntity->
children[fromSlotIndex])
385 toPos = getManager()->getEntityFromId(toPortEntity->
children[toSlotIndex])
388 else if (type == ConnectionType::DIRECT_POSITIONS) {
393 void addArrowHead()
override {
399 Entity* toPortEntity = getManager()->getEntityFromId(toNode->
children[toPort]);
402 if ((fromSlotIndex >= fromPortEntity->
children.size()) ||
403 (toSlotIndex >= toPortEntity->
children.size())) {
404 TAZ_ERROR(
"Invalid slot indices!");
409 glm::vec3 fromConnectionPoint = getManager()->getEntityFromId(fromPortEntity->
children[fromSlotIndex])->GetComponent<
TransformComponent>().getPosition();
410 glm::vec3 toConnectionPoint = getManager()->getEntityFromId(toPortEntity->
children[toSlotIndex])->GetComponent<
TransformComponent>().getPosition();
412 glm::vec3 direction = toConnectionPoint - fromConnectionPoint;
413 glm::vec3 unitDirection = glm::normalize(direction);
415 float linkWidth = this->GetComponent<Line_w_Color>().width;
417 float arrowheadWidth = linkWidth * 2.0f;
418 float arrowheadHeight = arrowheadWidth * 2.0f;
421 float offset = arrowheadHeight * 0.6f;
422 glm::vec3 arrowHeadPos = toConnectionPoint - unitDirection * offset;
424 auto& temp_arrowHead = getManager()->addEntityFromParent<
Empty>(
this, LinkChildren_ToString(ARROWHEAD));
427 float angleRadians = -atan2(direction.y, direction.x);
428 glm::vec3 arrowSize(arrowheadWidth, arrowheadHeight, 0.0f);
435 temp_arrowHead.GetComponent<
TransformComponent>().setRotation(glm::vec3(0.0f, 0.0f, angleRadians + glm::half_pi<float>()));
437 temp_arrowHead.addToGroup(Manager::groupArrowHeads_0);
438 temp_arrowHead.setParentEntity(
this);
439 children[LinkChildren_ToString(ARROWHEAD)] = temp_arrowHead.getId();
442 void removeArrowHead()
override {
443 if (
children.contains(LinkChildren_ToString(ARROWHEAD))) {
444 getManager()->getEntityFromId(
children[LinkChildren_ToString(ARROWHEAD)])->removeFromCell();
445 getManager()->getEntityFromId(
children[LinkChildren_ToString(ARROWHEAD)])->destroy();
446 children.erase(LinkChildren_ToString(ARROWHEAD));
450 EntityID getBestPortForConnection(
const glm::vec3&
fromPos,
const glm::vec3& toPos) {
452 float deltaX = toPos.x -
fromPos.x;
453 float deltaY = toPos.y -
fromPos.y;
455 if (abs(deltaX) > abs(deltaY)) {
456 return deltaX > 0 ? NodePorts_ToString(RIGHT) : NodePorts_ToString(LEFT);
459 return deltaY > 0 ? NodePorts_ToString(BOTTOM) : NodePorts_ToString(TOP);
464 void updateLinksSlotIndices(
NodeEntity* node, EntityID portIndex,
int removedSlotIndex,
bool isFrom) {
468 for (
auto& linkEntityId : node->getOutLinks()) {
469 auto* linkEntity =
dynamic_cast<LinkEntity*
>(
manager.getEntityFromId(linkEntityId));
471 if (EntityIDUtils::areEqual(linkEntity->fromPort, portIndex) &&
472 linkEntity->fromSlotIndex > removedSlotIndex &&
473 linkEntity->type != ConnectionType::GHOST_PORT_TO_PORT) {
474 linkEntity->fromSlotIndex--;
479 for (
auto& linkEntityId : node->getInLinks()) {
480 auto* linkEntity =
dynamic_cast<LinkEntity*
>(
manager.getEntityFromId(linkEntityId));
482 if (EntityIDUtils::areEqual(linkEntity->toPort, portIndex) &&
483 linkEntity->toSlotIndex > removedSlotIndex &&
484 linkEntity->type != ConnectionType::GHOST_PORT_TO_PORT) {
485 linkEntity->toSlotIndex--;
491 void removeSlotFromNode(
NodeEntity* node, EntityID port,
int slotIndex,
bool isFrom) {
492 if (std::holds_alternative<int>(port) || slotIndex == -1)
return;
494 Entity* portEntity = getManager()->getEntityFromId(node->
children[port]);
495 if (portEntity && portEntity->hasComponent<
PortComponent>()) {
496 if (removeSlot(portEntity, slotIndex)) {
497 updateLinksSlotIndices(node, port, slotIndex, isFrom);
502 void imgui_print()
override {
508 glm::vec2 fromNodePosition = fromNode->GetComponent<
TransformComponent>().getPosition();
511 ImGui::Text(
"From Node TazPosition: (%.2f, %.2f)", fromNodePosition.x, fromNodePosition.y);
512 ImGui::Text(
"To Node TazPosition: (%.2f, %.2f)", toNodePosition.x, toNodePosition.y);
514 ImGui::Text(
"Bounding boxes of intercepted cells:");
516 for (
auto cell : ownerCells) {
517 ImGui::Text(
"- %.2f , %.2f , %.2f", cell->boundingBox_origin.x, cell->boundingBox_origin.y, cell->boundingBox_origin.z);
521 void imgui_display()
override {
522 ImGui::Text(
"Display Info Here Link");
533 from->removeOutLink(getId());
534 removeSlotFromNode(from,
fromPort, fromSlotIndex,
true);
537 to->removeInLink(getId());
538 removeSlotFromNode(to, toPort, toSlotIndex,
false);
542 setConnectionType(LinkEntity::ConnectionType::NODE_TO_NODE);
545 manager.aboutTo_updateActiveEntities();
548 std::vector<EntityID> getSlots(
Entity* portEntity)
const {
549 std::vector<EntityID> slots;
550 for (
const auto& [
id, child] : portEntity->
children) {
551 auto* ent = portEntity->getManager()->getEntityFromId(child);
554 slots.push_back(child);
561 bool removeSlot(
Entity* portEntity,
int index) {
562 for (
auto it = portEntity->
children.begin(); it != portEntity->
children.end(); ++it) {
563 EntityID child = it->second;
564 auto* childEnt = portEntity->getManager()->getEntityFromId(child);
577 size_t getSlotCount(
Entity* portEntity)
const {
579 for (
const auto& [
id, child] : portEntity->
children) {
580 auto* childEnt = portEntity->getManager()->getEntityFromId(child);