47 manuallyFirableInputNode =
nullptr;
48 manuallyFirableInputPort =
nullptr;
53 vector<VuoNode *> nodes = parser->
getNodes();
54 for (vector<VuoNode *>::iterator node = nodes.begin(); node != nodes.end(); ++node)
57 vector<VuoCable *> cables = parser->
getCables();
58 for (vector<VuoCable *>::iterator cable = cables.begin(); cable != cables.end(); ++cable)
62 for (
int index = 0; index < publishedInputPorts.size(); ++index)
66 for (
int index = 0; index < publishedOutputPorts.size(); ++index)
69 vector<VuoComment *> comments = parser->
getComments();
70 for (vector<VuoComment *>::iterator comment = comments.begin(); comment != comments.end(); ++comment)
80 for (vector<VuoNode *>::iterator node = nodes.begin(); node != nodes.end(); ++node)
81 if ((*node)->hasCompiler())
82 nodeGraphvizIdentifierUsed[ (*node)->getCompiler()->getGraphvizIdentifier() ] = *node;
113 map<VuoCable *, VuoPort *> &cablesToTransferFromPort,
114 map<VuoCable *, VuoPort *> &cablesToTransferToPort,
115 set<VuoCable *> &cablesToRemove)
const
118 for (set<VuoCable *>::iterator i = cables.begin(); i != cables.end(); ++i)
122 bool foundMismatch =
false;
129 cablesToTransferFromPort[cable] = newPort;
131 foundMismatch =
true;
139 cablesToTransferToPort[cable] = newPort;
141 foundMismatch =
true;
146 cablesToRemove.insert(cable);
148 map<VuoCable *, VuoPort *>::iterator fromIter = cablesToTransferFromPort.find(cable);
149 if (fromIter != cablesToTransferFromPort.end())
150 cablesToTransferFromPort.erase(fromIter);
152 map<VuoCable *, VuoPort *>::iterator toIter = cablesToTransferToPort.find(cable);
153 if (toIter != cablesToTransferToPort.end())
154 cablesToTransferToPort.erase(toIter);
168 map<VuoCable *, VuoPort *> cablesToTransferFromPort;
169 map<VuoCable *, VuoPort *> cablesToTransferToPort;
170 set<VuoCable *> cablesToRemove;
177 for (map<VuoCable *, VuoPort *>::iterator i = cablesToTransferFromPort.begin(); i != cablesToTransferFromPort.end(); ++i)
178 i->first->setFrom(newNode, i->second);
179 for (map<VuoCable *, VuoPort *>::iterator i = cablesToTransferToPort.begin(); i != cablesToTransferToPort.end(); ++i)
180 i->first->setTo(newNode, i->second);
181 for (set<VuoCable *>::iterator i = cablesToRemove.begin(); i != cablesToRemove.end(); ++i)
191 bool compositionChanged = (currentHash != graphHash);
193 bool shouldAddPublishedNodeImplementations =
false;
194 if (! compositionChanged && compiler)
198 shouldAddPublishedNodeImplementations =
true;
201 if (compositionChanged || shouldAddPublishedNodeImplementations)
205 graphHash = currentHash;
230 checkForMissingTypes(issues);
242 set<VuoNode *> missingNodes;
244 for (set<VuoNode *>::iterator i = nodes.begin(); i != nodes.end(); ++i)
248 missingNodes.insert(node);
251 if (! missingNodes.empty())
254 vector<string> uniqueNodeDetails;
255 bool missingProNode =
false;
256 bool missingOldNode =
false;
257 for (set<VuoNode *>::iterator i = missingNodes.begin(); i != missingNodes.end(); ++i)
261 string nodeDetail = node->
getTitle() +
" (" + (*i)->getNodeClass()->getClassName() +
")";
266 nodeDetail +=
" [Vuo Pro]";
267 missingProNode =
true;
273 nodeDetail +=
" [Vuo 0.9 or earlier]";
274 missingOldNode =
true;
277 if (find(uniqueNodeDetails.begin(), uniqueNodeDetails.end(), nodeDetail) == uniqueNodeDetails.end())
278 uniqueNodeDetails.push_back(nodeDetail);
280 sort(uniqueNodeDetails.begin(), uniqueNodeDetails.end());
289 hint +=
"<p>Some of the non-installed nodes are Pro nodes. "
290 "%link to enable Pro nodes.</p>";
291 linkUrl =
"https://vuo.org/buy";
292 linkText =
"Upgrade to Vuo Pro";
297 hint +=
"<p>Some of the non-installed nodes were updated or removed in Vuo 0.9 or earlier. "
298 "To work with this composition in Vuo 1.0 or later, first make a "
299 "backup copy of the composition, then open the composition in Vuo 0.9 and save it. "
300 "This will automatically upgrade the composition so you can use it in Vuo 1.0 or later.</p>";
304 string summary =
"Nodes not installed";
309 issue.
setLink(linkUrl, linkText);
328 map<string, set<string> > missingTypes;
331 if (! node->getNodeClass()->hasCompiler())
334 vector<VuoPort *> ports;
335 vector<VuoPort *> inputPorts = node->getInputPorts();
336 ports.insert(ports.end(), inputPorts.begin(), inputPorts.end());
337 vector<VuoPort *> outputPorts = node->getOutputPorts();
338 ports.insert(ports.end(), outputPorts.begin(), outputPorts.end());
344 missingTypes[type->
getModuleKey()].insert(node->getNodeClass()->getClassName());
348 if (! missingTypes.empty())
351 for (
auto i : missingTypes)
353 vector<string> nodeClassNames(i.second.begin(), i.second.end());
354 std::sort(nodeClassNames.begin(), nodeClassNames.end());
356 string summary =
"Data type not installed";
358 string hint =
"Check with the developer of the nodes that use this data type.";
362 exceptionIssues->append(issue);
392 if (! potentialCables.empty())
400 if (! potentialCables.empty())
407 set< set<VuoCompilerPort *> > VuoCompilerComposition::groupGenericPortsByType(
void)
409 set< set<VuoCompilerPort *> > setsOfConnectedGenericPorts;
412 set< pair< vector<VuoPort *>,
VuoNode *> > portsGroupedByNode;
414 for (set<VuoNode *>::iterator i = nodes.begin(); i != nodes.end(); ++i)
422 vector<VuoPort *> ports;
423 ports.insert(ports.end(), inputPorts.begin(), inputPorts.end());
424 ports.insert(ports.end(), outputPorts.begin(), outputPorts.end());
426 portsGroupedByNode.insert( make_pair(ports, node) );
430 vector<VuoPort *> publishedInputBasePorts( publishedInputPorts.begin(), publishedInputPorts.end() );
431 vector<VuoPort *> publishedOutputBasePorts( publishedOutputPorts.begin(), publishedOutputPorts.end() );
432 portsGroupedByNode.insert( make_pair(publishedInputBasePorts,
static_cast<VuoNode *
>(NULL)) );
433 portsGroupedByNode.insert( make_pair(publishedOutputBasePorts,
static_cast<VuoNode *
>(NULL)) );
436 for (set< pair< vector<VuoPort *>,
VuoNode* > >::iterator i = portsGroupedByNode.begin(); i != portsGroupedByNode.end(); ++i)
438 vector<VuoPort *> ports = i->first;
440 map<string, set<VuoCompilerPort *> > genericPortsForType;
441 for (vector<VuoPort *>::iterator j = ports.begin(); j != ports.end(); ++j)
449 genericPortsForType[innermostGenericTypeName].insert(port);
453 for (map<
string, set<VuoCompilerPort *> >::iterator j = genericPortsForType.begin(); j != genericPortsForType.end(); ++j)
455 set<VuoCompilerPort *> genericPorts = j->second;
456 setsOfConnectedGenericPorts.insert(genericPorts);
462 for (set<VuoCable *>::iterator i = cables.begin(); i != cables.end(); ++i)
473 set< set<VuoCompilerPort *> >::iterator fromSetIter = setsOfConnectedGenericPorts.end();
474 set< set<VuoCompilerPort *> >::iterator toSetIter = setsOfConnectedGenericPorts.end();
475 for (set< set<VuoCompilerPort *> >::iterator j = setsOfConnectedGenericPorts.begin(); j != setsOfConnectedGenericPorts.end(); ++j)
477 if (j->find(fromPort) != j->end())
479 if (j->find(toPort) != j->end())
482 if (fromSetIter != setsOfConnectedGenericPorts.end() && toSetIter != setsOfConnectedGenericPorts.end() &&
483 fromSetIter != toSetIter)
485 set<VuoCompilerPort *> mergedSet;
486 mergedSet.insert(fromSetIter->begin(), fromSetIter->end());
487 mergedSet.insert(toSetIter->begin(), toSetIter->end());
488 setsOfConnectedGenericPorts.insert(mergedSet);
489 setsOfConnectedGenericPorts.erase(fromSetIter);
490 setsOfConnectedGenericPorts.erase(toSetIter);
494 return setsOfConnectedGenericPorts;
505 set< set<VuoCompilerPort *> > setsOfConnectedGenericPorts = groupGenericPortsByType();
508 set<string> usedTypeNames;
509 for (set< set<VuoCompilerPort *> >::iterator i = setsOfConnectedGenericPorts.begin(); i != setsOfConnectedGenericPorts.end(); ++i)
511 set<VuoCompilerPort *> connectedGenericPorts = *i;
516 vector<string> sortedTypeNames;
517 for (set<VuoCompilerPort *>::iterator j = connectedGenericPorts.begin(); j != connectedGenericPorts.end(); ++j)
523 if (genericTypeFromPort != genericTypeFromPortClass)
526 sortedTypeNames.push_back(typeName);
531 string commonTypeName;
532 for (vector<string>::iterator j = sortedTypeNames.begin(); j != sortedTypeNames.end(); ++j)
534 string portType = *j;
535 if (usedTypeNames.find(portType) == usedTypeNames.end())
537 commonTypeName = portType;
542 if (commonTypeName.empty())
543 commonTypeName = createFreshGenericTypeName();
545 usedTypeNames.insert(commonTypeName);
549 vector<string> compatibleTypeNames;
550 for (set<VuoCompilerPort *>::iterator j = connectedGenericPorts.begin(); j != connectedGenericPorts.end(); ++j)
557 vector<string> innermostCompatibleTypeNamesForPort;
558 for (vector<string>::iterator k = compatibleTypeNamesForPort.begin(); k != compatibleTypeNamesForPort.end(); ++k)
561 if (! innermostCompatibleTypeNamesForPort.empty())
563 if (compatibleTypeNames.empty())
564 compatibleTypeNames = innermostCompatibleTypeNamesForPort;
567 for (
int k = compatibleTypeNames.size() - 1; k >= 0; --k)
568 if (find(innermostCompatibleTypeNamesForPort.begin(), innermostCompatibleTypeNamesForPort.end(), compatibleTypeNames[k]) ==
569 innermostCompatibleTypeNamesForPort.end())
570 compatibleTypeNames.erase(compatibleTypeNames.begin() + k);
576 for (set<VuoCompilerPort *>::iterator j = connectedGenericPorts.begin(); j != connectedGenericPorts.end(); ++j)
583 vector<string> compatibleTypeNamesForPort;
585 for (vector<string>::iterator k = compatibleTypeNames.begin(); k != compatibleTypeNames.end(); ++k)
586 compatibleTypeNamesForPort.push_back(prefix + *k);
594 for (map<unsigned int, bool>::iterator i = genericTypeSuffixUsed.begin(); i != genericTypeSuffixUsed.end(); ++i)
596 unsigned int suffix = i->first;
598 genericTypeSuffixUsed[suffix] = used;
605 string VuoCompilerComposition::createFreshGenericTypeName(
void)
607 for (
unsigned int i = 1; ; ++i)
609 if (! genericTypeSuffixUsed[i])
611 genericTypeSuffixUsed[i] =
true;
632 auto getGenericTypeName = [&useOriginalType] (
VuoNode *node,
VuoPort *port)
642 if (specializedNodeClass)
655 set<VuoPort *> correlatedPorts;
656 set<VuoNode *> nodesEnqueuedOrVisited;
657 list< pair<VuoNode *, string> > nodesToVisit;
659 string entryGenericType = getGenericTypeName(entryNode, entryPort);
660 if (! entryGenericType.empty())
662 nodesToVisit.push_back( make_pair(entryNode, entryGenericType) );
663 nodesEnqueuedOrVisited.insert(entryNode);
666 while (! nodesToVisit.empty())
668 VuoNode *currNode = nodesToVisit.front().first;
669 string currGenericType = nodesToVisit.front().second;
670 nodesToVisit.pop_front();
674 list<VuoPort *> correlatedPortsOnNode;
676 if (getGenericTypeName(currNode, currPort) == currGenericType)
677 correlatedPortsOnNode.push_back(currPort);
679 if (getGenericTypeName(currNode, currPort) == currGenericType)
680 correlatedPortsOnNode.push_back(currPort);
682 correlatedPorts.insert(correlatedPortsOnNode.begin(), correlatedPortsOnNode.end());
686 for (
VuoPort *port : correlatedPortsOnNode)
688 for (
VuoCable *cable : port->getConnectedCables())
709 if (nodesEnqueuedOrVisited.find(otherNode) == nodesEnqueuedOrVisited.end())
711 string otherGenericType = getGenericTypeName(otherNode, otherPort);
712 if (! otherGenericType.empty())
714 nodesToVisit.push_back( make_pair(otherNode, otherGenericType) );
715 nodesEnqueuedOrVisited.insert(otherNode);
722 return correlatedPorts;
732 return trigger ? trigger->
getBase() : NULL;
740 this->module = module;
748 Module *takenModule = module;
766 nodeGraphvizIdentifierUsed[ currNode->getCompiler()->getGraphvizIdentifier() ] = currNode;
768 auto isIdentifierAvailable = [
this, node] (
const string &identifier)
770 auto it = nodeGraphvizIdentifierUsed.find(identifier);
771 if (it == nodeGraphvizIdentifierUsed.end())
774 return it->second == node;
782 nodeGraphvizIdentifierUsed[uniqueIdentifier] = node;
791 nodeGraphvizIdentifierUsed.clear();
806 if (currComment != comment && currComment->
hasCompiler())
807 commentGraphvizIdentifierUsed[ currComment->getCompiler()->getGraphvizIdentifier() ] = currComment;
809 auto isIdentifierAvailable = [
this, comment] (
const string &identifier)
811 auto it = commentGraphvizIdentifierUsed.find(identifier);
812 if (it == commentGraphvizIdentifierUsed.end())
815 return it->second == comment;
821 commentGraphvizIdentifierUsed[uniqueIdentifier] = comment;
830 commentGraphvizIdentifierUsed.clear();
842 this->manuallyFirableInputNode = nodeContainingPort;
843 this->manuallyFirableInputPort = portFiredInto;
851 return manuallyFirableInputNode;
859 return manuallyFirableInputPort;
870 getBase()->getProtocolAwarePublishedPortOrder(activeProtocol,
true),
871 getBase()->getProtocolAwarePublishedPortOrder(activeProtocol,
false),
880 set<VuoCable *> cableSet,
881 set<VuoComment *> commentSet,
882 vector<VuoPublishedPort *> publishedInputPorts,
883 vector<VuoPublishedPort *> publishedOutputPorts,
884 string header,
string footer,
double xPositionOffset,
double yPositionOffset)
887 vector<VuoNode *> nodes;
888 for (set<VuoNode *>::iterator i = nodeSet.begin(); i != nodeSet.end(); ++i)
891 sort(nodes.begin(), nodes.end(), compareGraphvizIdentifiersOfNodes);
894 vector<VuoCable *> cables;
895 for (set<VuoCable *>::iterator i = cableSet.begin(); i != cableSet.end(); ++i)
896 cables.push_back(*i);
898 sort(cables.begin(), cables.end(), compareGraphvizIdentifiersOfCables);
901 vector<VuoComment *> comments;
902 for (set<VuoComment *>::iterator i = commentSet.begin(); i != commentSet.end(); ++i)
903 comments.push_back(*i);
905 sort(comments.begin(), comments.end(), compareGraphvizIdentifiersOfComments);
908 string compositionFooter = (! footer.empty()? footer :
"\n");
910 ostringstream output;
911 string nodeCommentSectionDivider =
"\n";
912 if ((nodes.empty() && publishedInputPorts.empty() && publishedOutputPorts.empty()) ||
913 (comments.empty() && cables.empty()))
914 nodeCommentSectionDivider =
"";
916 string commentCableSectionDivider =
"\n";
917 if (comments.empty() || cables.empty())
918 commentCableSectionDivider =
"";
921 output << compositionHeader;
922 output <<
"{" << endl;
925 for (vector<VuoNode *>::iterator i = nodes.begin(); i != nodes.end(); ++i)
927 string nodeDeclaration = ((*i)->hasCompiler() ?
928 (*i)->getCompiler()->getGraphvizDeclaration(
true, xPositionOffset, yPositionOffset,
929 manuallyFirableInputNode == *i ? manuallyFirableInputPort :
nullptr) :
930 (*i)->getRawGraphvizDeclaration());
931 output << nodeDeclaration << endl;
935 if (! publishedInputPorts.empty())
938 for (vector<VuoPublishedPort *>::iterator i = publishedInputPorts.begin(); i != publishedInputPorts.end(); ++i)
939 output <<
"|<" << (*i)->getClass()->getName() <<
">" << (*i)->getClass()->getName() <<
"\\r";
941 for (vector<VuoPublishedPort *>::iterator i = publishedInputPorts.begin(); i != publishedInputPorts.end(); ++i)
943 output <<
"];" << endl;
945 if (! publishedOutputPorts.empty())
948 for (vector<VuoPublishedPort *>::iterator i = publishedOutputPorts.begin(); i != publishedOutputPorts.end(); ++i)
949 output <<
"|<" << (*i)->getClass()->getName() <<
">" << (*i)->getClass()->getName() <<
"\\l";
952 for (vector<VuoPublishedPort *>::iterator i = publishedOutputPorts.begin(); i != publishedOutputPorts.end(); ++i)
955 output <<
"];" << endl;
958 output << nodeCommentSectionDivider;
961 for (vector<VuoComment *>::iterator i = comments.begin(); i != comments.end(); ++i)
963 string commentDeclaration = ((*i)->hasCompiler() ?
964 (*i)->getCompiler()->getGraphvizDeclaration(xPositionOffset, yPositionOffset) :
"");
965 output << commentDeclaration << endl;
968 output << commentCableSectionDivider;
971 for (vector<VuoCable *>::iterator i = cables.begin(); i != cables.end(); ++i)
978 output << compositionFooter;
994 for (
auto node :
getBase()->getNodes())
997 return compositeTarget;
1003 bool VuoCompilerComposition::compareGraphvizIdentifiersOfNodes(
VuoNode *lhs,
VuoNode *rhs)
1007 return lhsIdentifier.compare(rhsIdentifier) < 0;
1013 bool VuoCompilerComposition::compareGraphvizIdentifiersOfCables(
VuoCable *lhs,
VuoCable *rhs)
1017 return lhsIdentifier.compare(rhsIdentifier) < 0;
1023 bool VuoCompilerComposition::compareGraphvizIdentifiersOfComments(
VuoComment *lhs,
VuoComment *rhs)
1027 return lhsIdentifier.compare(rhsIdentifier) < 0;
1036 if (! oldPort || ! newPort)
1041 if (oldPortName == newPortName)
1047 if (oldType == newType)
1063 if (! oldPortClass || ! newPortClass)
1066 string oldPortName = oldPortClass->
getName();
1067 string newPortName = newPortClass->
getName();
1068 if (oldPortName == newPortName)
1074 if (oldType == newType)