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);
323 map<string, set<string> > missingTypes;
326 if (! node->getNodeClass()->hasCompiler())
329 vector<VuoPort *> ports;
330 vector<VuoPort *> inputPorts = node->getInputPorts();
331 ports.insert(ports.end(), inputPorts.begin(), inputPorts.end());
332 vector<VuoPort *> outputPorts = node->getOutputPorts();
333 ports.insert(ports.end(), outputPorts.begin(), outputPorts.end());
339 missingTypes[type->
getModuleKey()].insert(node->getNodeClass()->getClassName());
343 if (! missingTypes.empty())
345 for (
auto i : missingTypes)
347 vector<string> nodeClassNames(i.second.begin(), i.second.end());
348 std::sort(nodeClassNames.begin(), nodeClassNames.end());
350 string summary =
"Data type not installed";
352 string hint =
"Check with the developer of the nodes that use this data type.";
384 if (! potentialCables.empty())
392 if (! potentialCables.empty())
399 set< set<VuoCompilerPort *> > VuoCompilerComposition::groupGenericPortsByType(
void)
401 set< set<VuoCompilerPort *> > setsOfConnectedGenericPorts;
404 set< pair< vector<VuoPort *>,
VuoNode *> > portsGroupedByNode;
406 for (set<VuoNode *>::iterator i = nodes.begin(); i != nodes.end(); ++i)
414 vector<VuoPort *> ports;
415 ports.insert(ports.end(), inputPorts.begin(), inputPorts.end());
416 ports.insert(ports.end(), outputPorts.begin(), outputPorts.end());
418 portsGroupedByNode.insert( make_pair(ports, node) );
422 vector<VuoPort *> publishedInputBasePorts( publishedInputPorts.begin(), publishedInputPorts.end() );
423 vector<VuoPort *> publishedOutputBasePorts( publishedOutputPorts.begin(), publishedOutputPorts.end() );
424 portsGroupedByNode.insert( make_pair(publishedInputBasePorts,
static_cast<VuoNode *
>(NULL)) );
425 portsGroupedByNode.insert( make_pair(publishedOutputBasePorts,
static_cast<VuoNode *
>(NULL)) );
428 for (set< pair< vector<VuoPort *>,
VuoNode* > >::iterator i = portsGroupedByNode.begin(); i != portsGroupedByNode.end(); ++i)
430 vector<VuoPort *> ports = i->first;
432 map<string, set<VuoCompilerPort *> > genericPortsForType;
433 for (vector<VuoPort *>::iterator j = ports.begin(); j != ports.end(); ++j)
441 genericPortsForType[innermostGenericTypeName].insert(port);
445 for (map<
string, set<VuoCompilerPort *> >::iterator j = genericPortsForType.begin(); j != genericPortsForType.end(); ++j)
447 set<VuoCompilerPort *> genericPorts = j->second;
448 setsOfConnectedGenericPorts.insert(genericPorts);
454 for (set<VuoCable *>::iterator i = cables.begin(); i != cables.end(); ++i)
465 set< set<VuoCompilerPort *> >::iterator fromSetIter = setsOfConnectedGenericPorts.end();
466 set< set<VuoCompilerPort *> >::iterator toSetIter = setsOfConnectedGenericPorts.end();
467 for (set< set<VuoCompilerPort *> >::iterator j = setsOfConnectedGenericPorts.begin(); j != setsOfConnectedGenericPorts.end(); ++j)
469 if (j->find(fromPort) != j->end())
471 if (j->find(toPort) != j->end())
474 if (fromSetIter != setsOfConnectedGenericPorts.end() && toSetIter != setsOfConnectedGenericPorts.end() &&
475 fromSetIter != toSetIter)
477 set<VuoCompilerPort *> mergedSet;
478 mergedSet.insert(fromSetIter->begin(), fromSetIter->end());
479 mergedSet.insert(toSetIter->begin(), toSetIter->end());
480 setsOfConnectedGenericPorts.insert(mergedSet);
481 setsOfConnectedGenericPorts.erase(fromSetIter);
482 setsOfConnectedGenericPorts.erase(toSetIter);
486 return setsOfConnectedGenericPorts;
497 set< set<VuoCompilerPort *> > setsOfConnectedGenericPorts = groupGenericPortsByType();
500 set<string> usedTypeNames;
501 for (set< set<VuoCompilerPort *> >::iterator i = setsOfConnectedGenericPorts.begin(); i != setsOfConnectedGenericPorts.end(); ++i)
503 set<VuoCompilerPort *> connectedGenericPorts = *i;
508 vector<string> sortedTypeNames;
509 for (set<VuoCompilerPort *>::iterator j = connectedGenericPorts.begin(); j != connectedGenericPorts.end(); ++j)
515 if (genericTypeFromPort != genericTypeFromPortClass)
518 sortedTypeNames.push_back(typeName);
523 string commonTypeName;
524 for (vector<string>::iterator j = sortedTypeNames.begin(); j != sortedTypeNames.end(); ++j)
526 string portType = *j;
527 if (usedTypeNames.find(portType) == usedTypeNames.end())
529 commonTypeName = portType;
534 if (commonTypeName.empty())
535 commonTypeName = createFreshGenericTypeName();
537 usedTypeNames.insert(commonTypeName);
541 vector<string> compatibleTypeNames;
542 for (set<VuoCompilerPort *>::iterator j = connectedGenericPorts.begin(); j != connectedGenericPorts.end(); ++j)
549 vector<string> innermostCompatibleTypeNamesForPort;
550 for (vector<string>::iterator k = compatibleTypeNamesForPort.begin(); k != compatibleTypeNamesForPort.end(); ++k)
553 if (! innermostCompatibleTypeNamesForPort.empty())
555 if (compatibleTypeNames.empty())
556 compatibleTypeNames = innermostCompatibleTypeNamesForPort;
559 for (
int k = compatibleTypeNames.size() - 1; k >= 0; --k)
560 if (find(innermostCompatibleTypeNamesForPort.begin(), innermostCompatibleTypeNamesForPort.end(), compatibleTypeNames[k]) ==
561 innermostCompatibleTypeNamesForPort.end())
562 compatibleTypeNames.erase(compatibleTypeNames.begin() + k);
568 for (set<VuoCompilerPort *>::iterator j = connectedGenericPorts.begin(); j != connectedGenericPorts.end(); ++j)
575 vector<string> compatibleTypeNamesForPort;
577 for (vector<string>::iterator k = compatibleTypeNames.begin(); k != compatibleTypeNames.end(); ++k)
578 compatibleTypeNamesForPort.push_back(prefix + *k);
586 for (map<unsigned int, bool>::iterator i = genericTypeSuffixUsed.begin(); i != genericTypeSuffixUsed.end(); ++i)
588 unsigned int suffix = i->first;
590 genericTypeSuffixUsed[suffix] = used;
597 string VuoCompilerComposition::createFreshGenericTypeName(
void)
599 for (
unsigned int i = 1; ; ++i)
601 if (! genericTypeSuffixUsed[i])
603 genericTypeSuffixUsed[i] =
true;
624 auto getGenericTypeName = [&useOriginalType] (
VuoNode *node,
VuoPort *port)
634 if (specializedNodeClass)
647 set<VuoPort *> correlatedPorts;
648 set<VuoNode *> nodesEnqueuedOrVisited;
649 list< pair<VuoNode *, string> > nodesToVisit;
651 string entryGenericType = getGenericTypeName(entryNode, entryPort);
652 if (! entryGenericType.empty())
654 nodesToVisit.push_back( make_pair(entryNode, entryGenericType) );
655 nodesEnqueuedOrVisited.insert(entryNode);
658 while (! nodesToVisit.empty())
660 VuoNode *currNode = nodesToVisit.front().first;
661 string currGenericType = nodesToVisit.front().second;
662 nodesToVisit.pop_front();
666 list<VuoPort *> correlatedPortsOnNode;
668 if (getGenericTypeName(currNode, currPort) == currGenericType)
669 correlatedPortsOnNode.push_back(currPort);
671 if (getGenericTypeName(currNode, currPort) == currGenericType)
672 correlatedPortsOnNode.push_back(currPort);
674 correlatedPorts.insert(correlatedPortsOnNode.begin(), correlatedPortsOnNode.end());
678 for (
VuoPort *port : correlatedPortsOnNode)
680 for (
VuoCable *cable : port->getConnectedCables())
701 if (nodesEnqueuedOrVisited.find(otherNode) == nodesEnqueuedOrVisited.end())
703 string otherGenericType = getGenericTypeName(otherNode, otherPort);
704 if (! otherGenericType.empty())
706 nodesToVisit.push_back( make_pair(otherNode, otherGenericType) );
707 nodesEnqueuedOrVisited.insert(otherNode);
714 return correlatedPorts;
724 return trigger ? trigger->
getBase() : NULL;
732 this->module = module;
740 Module *takenModule = module;
758 nodeGraphvizIdentifierUsed[ currNode->getCompiler()->getGraphvizIdentifier() ] = currNode;
760 auto isIdentifierAvailable = [
this, node] (
const string &identifier)
762 auto it = nodeGraphvizIdentifierUsed.find(identifier);
763 if (it == nodeGraphvizIdentifierUsed.end())
766 return it->second == node;
774 nodeGraphvizIdentifierUsed[uniqueIdentifier] = node;
783 nodeGraphvizIdentifierUsed.clear();
798 if (currComment != comment && currComment->
hasCompiler())
799 commentGraphvizIdentifierUsed[ currComment->getCompiler()->getGraphvizIdentifier() ] = currComment;
801 auto isIdentifierAvailable = [
this, comment] (
const string &identifier)
803 auto it = commentGraphvizIdentifierUsed.find(identifier);
804 if (it == commentGraphvizIdentifierUsed.end())
807 return it->second == comment;
813 commentGraphvizIdentifierUsed[uniqueIdentifier] = comment;
822 commentGraphvizIdentifierUsed.clear();
834 this->manuallyFirableInputNode = nodeContainingPort;
835 this->manuallyFirableInputPort = portFiredInto;
843 return manuallyFirableInputNode;
851 return manuallyFirableInputPort;
862 getBase()->getProtocolAwarePublishedPortOrder(activeProtocol,
true),
863 getBase()->getProtocolAwarePublishedPortOrder(activeProtocol,
false),
872 set<VuoCable *> cableSet,
873 set<VuoComment *> commentSet,
874 vector<VuoPublishedPort *> publishedInputPorts,
875 vector<VuoPublishedPort *> publishedOutputPorts,
876 string header,
string footer,
double xPositionOffset,
double yPositionOffset)
879 vector<VuoNode *> nodes;
880 for (set<VuoNode *>::iterator i = nodeSet.begin(); i != nodeSet.end(); ++i)
883 sort(nodes.begin(), nodes.end(), compareGraphvizIdentifiersOfNodes);
886 vector<VuoCable *> cables;
887 for (set<VuoCable *>::iterator i = cableSet.begin(); i != cableSet.end(); ++i)
888 cables.push_back(*i);
890 sort(cables.begin(), cables.end(), compareGraphvizIdentifiersOfCables);
893 vector<VuoComment *> comments;
894 for (set<VuoComment *>::iterator i = commentSet.begin(); i != commentSet.end(); ++i)
895 comments.push_back(*i);
897 sort(comments.begin(), comments.end(), compareGraphvizIdentifiersOfComments);
900 string compositionFooter = (! footer.empty()? footer :
"\n");
902 ostringstream output;
903 string nodeCommentSectionDivider =
"\n";
904 if ((nodes.empty() && publishedInputPorts.empty() && publishedOutputPorts.empty()) ||
905 (comments.empty() && cables.empty()))
906 nodeCommentSectionDivider =
"";
908 string commentCableSectionDivider =
"\n";
909 if (comments.empty() || cables.empty())
910 commentCableSectionDivider =
"";
913 output << compositionHeader;
914 output <<
"{" << endl;
917 for (vector<VuoNode *>::iterator i = nodes.begin(); i != nodes.end(); ++i)
919 string nodeDeclaration = ((*i)->hasCompiler() ?
920 (*i)->getCompiler()->getGraphvizDeclaration(
true, xPositionOffset, yPositionOffset,
921 manuallyFirableInputNode == *i ? manuallyFirableInputPort :
nullptr) :
922 (*i)->getRawGraphvizDeclaration());
923 output << nodeDeclaration << endl;
927 if (! publishedInputPorts.empty())
930 for (vector<VuoPublishedPort *>::iterator i = publishedInputPorts.begin(); i != publishedInputPorts.end(); ++i)
931 output <<
"|<" << (*i)->getClass()->getName() <<
">" << (*i)->getClass()->getName() <<
"\\r";
933 for (vector<VuoPublishedPort *>::iterator i = publishedInputPorts.begin(); i != publishedInputPorts.end(); ++i)
935 output <<
"];" << endl;
937 if (! publishedOutputPorts.empty())
940 for (vector<VuoPublishedPort *>::iterator i = publishedOutputPorts.begin(); i != publishedOutputPorts.end(); ++i)
941 output <<
"|<" << (*i)->getClass()->getName() <<
">" << (*i)->getClass()->getName() <<
"\\l";
944 for (vector<VuoPublishedPort *>::iterator i = publishedOutputPorts.begin(); i != publishedOutputPorts.end(); ++i)
947 output <<
"];" << endl;
950 output << nodeCommentSectionDivider;
953 for (vector<VuoComment *>::iterator i = comments.begin(); i != comments.end(); ++i)
955 string commentDeclaration = ((*i)->hasCompiler() ?
956 (*i)->getCompiler()->getGraphvizDeclaration(xPositionOffset, yPositionOffset) :
"");
957 output << commentDeclaration << endl;
960 output << commentCableSectionDivider;
963 for (vector<VuoCable *>::iterator i = cables.begin(); i != cables.end(); ++i)
970 output << compositionFooter;
981 for (
auto node :
getBase()->getNodes())
983 return compositeTarget;
989 bool VuoCompilerComposition::compareGraphvizIdentifiersOfNodes(
VuoNode *lhs,
VuoNode *rhs)
993 return lhsIdentifier.compare(rhsIdentifier) < 0;
999 bool VuoCompilerComposition::compareGraphvizIdentifiersOfCables(
VuoCable *lhs,
VuoCable *rhs)
1003 return lhsIdentifier.compare(rhsIdentifier) < 0;
1009 bool VuoCompilerComposition::compareGraphvizIdentifiersOfComments(
VuoComment *lhs,
VuoComment *rhs)
1013 return lhsIdentifier.compare(rhsIdentifier) < 0;
1022 if (! oldPort || ! newPort)
1027 if (oldPortName == newPortName)
1033 if (oldType == newType)
1049 if (! oldPortClass || ! newPortClass)
1052 string oldPortName = oldPortClass->
getName();
1053 string newPortName = newPortClass->
getName();
1054 if (oldPortName == newPortName)
1060 if (oldType == newType)