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 +=
"Some of the non-installed nodes are Pro nodes. "
290 "%link to enable Pro nodes.";
291 linkUrl =
"https://vuo.org/buy";
292 linkText =
"Upgrade to Vuo Pro";
296 if (missingProNode && missingOldNode)
301 hint +=
"Some of the non-installed nodes were updated or removed in Vuo 0.9 or earlier. "
302 "To work with this composition in Vuo 1.0 or later, first make a "
303 "backup copy of the composition, then open the composition in Vuo 0.9 and save it. "
304 "This will automatically upgrade the composition so you can use it in Vuo 1.0 or later.";
308 string summary =
"Nodes not installed";
313 issue.
setLink(linkUrl, linkText);
327 map<string, set<string> > missingTypes;
330 if (! node->getNodeClass()->hasCompiler())
333 vector<VuoPort *> ports;
334 vector<VuoPort *> inputPorts = node->getInputPorts();
335 ports.insert(ports.end(), inputPorts.begin(), inputPorts.end());
336 vector<VuoPort *> outputPorts = node->getOutputPorts();
337 ports.insert(ports.end(), outputPorts.begin(), outputPorts.end());
341 VuoType *type = static_cast<VuoCompilerPort *>(port->getCompiler())->getDataVuoType();
342 if (type && ! type->
hasCompiler() && ! dynamic_cast<VuoGenericType *>(type))
343 missingTypes[type->
getModuleKey()].insert(node->getNodeClass()->getClassName());
347 if (! missingTypes.empty())
349 for (
auto i : missingTypes)
351 vector<string> nodeClassNames(i.second.begin(), i.second.end());
352 std::sort(nodeClassNames.begin(), nodeClassNames.end());
354 string summary =
"Data type not installed";
356 string hint =
"Check with the developer of the nodes that use this data type.";
388 if (! potentialCables.empty())
396 if (! potentialCables.empty())
403 set< set<VuoCompilerPort *> > VuoCompilerComposition::groupGenericPortsByType(
void)
405 set< set<VuoCompilerPort *> > setsOfConnectedGenericPorts;
408 set< pair< vector<VuoPort *>,
VuoNode *> > portsGroupedByNode;
410 for (set<VuoNode *>::iterator i = nodes.begin(); i != nodes.end(); ++i)
418 vector<VuoPort *> ports;
419 ports.insert(ports.end(), inputPorts.begin(), inputPorts.end());
420 ports.insert(ports.end(), outputPorts.begin(), outputPorts.end());
422 portsGroupedByNode.insert( make_pair(ports, node) );
426 vector<VuoPort *> publishedInputBasePorts( publishedInputPorts.begin(), publishedInputPorts.end() );
427 vector<VuoPort *> publishedOutputBasePorts( publishedOutputPorts.begin(), publishedOutputPorts.end() );
428 portsGroupedByNode.insert( make_pair(publishedInputBasePorts, static_cast<VuoNode *>(NULL)) );
429 portsGroupedByNode.insert( make_pair(publishedOutputBasePorts, static_cast<VuoNode *>(NULL)) );
432 for (set< pair< vector<VuoPort *>,
VuoNode* > >::iterator i = portsGroupedByNode.begin(); i != portsGroupedByNode.end(); ++i)
434 vector<VuoPort *> ports = i->first;
436 map<string, set<VuoCompilerPort *> > genericPortsForType;
437 for (vector<VuoPort *>::iterator j = ports.begin(); j != ports.end(); ++j)
439 VuoCompilerPort *port = static_cast<VuoCompilerPort *>((*j)->getCompiler());
445 genericPortsForType[innermostGenericTypeName].insert(port);
449 for (map<
string, set<VuoCompilerPort *> >::iterator j = genericPortsForType.begin(); j != genericPortsForType.end(); ++j)
451 set<VuoCompilerPort *> genericPorts = j->second;
452 setsOfConnectedGenericPorts.insert(genericPorts);
458 for (set<VuoCable *>::iterator i = cables.begin(); i != cables.end(); ++i)
469 set< set<VuoCompilerPort *> >::iterator fromSetIter = setsOfConnectedGenericPorts.end();
470 set< set<VuoCompilerPort *> >::iterator toSetIter = setsOfConnectedGenericPorts.end();
471 for (set< set<VuoCompilerPort *> >::iterator j = setsOfConnectedGenericPorts.begin(); j != setsOfConnectedGenericPorts.end(); ++j)
473 if (j->find(fromPort) != j->end())
475 if (j->find(toPort) != j->end())
478 if (fromSetIter != setsOfConnectedGenericPorts.end() && toSetIter != setsOfConnectedGenericPorts.end() &&
479 fromSetIter != toSetIter)
481 set<VuoCompilerPort *> mergedSet;
482 mergedSet.insert(fromSetIter->begin(), fromSetIter->end());
483 mergedSet.insert(toSetIter->begin(), toSetIter->end());
484 setsOfConnectedGenericPorts.insert(mergedSet);
485 setsOfConnectedGenericPorts.erase(fromSetIter);
486 setsOfConnectedGenericPorts.erase(toSetIter);
490 return setsOfConnectedGenericPorts;
501 set< set<VuoCompilerPort *> > setsOfConnectedGenericPorts = groupGenericPortsByType();
504 set<string> usedTypeNames;
505 for (set< set<VuoCompilerPort *> >::iterator i = setsOfConnectedGenericPorts.begin(); i != setsOfConnectedGenericPorts.end(); ++i)
507 set<VuoCompilerPort *> connectedGenericPorts = *i;
512 vector<string> sortedTypeNames;
513 for (set<VuoCompilerPort *>::iterator j = connectedGenericPorts.begin(); j != connectedGenericPorts.end(); ++j)
518 VuoGenericType *genericTypeFromPortClass = static_cast<VuoGenericType *>(portClass->getDataVuoType());
519 if (genericTypeFromPort != genericTypeFromPortClass)
522 sortedTypeNames.push_back(typeName);
527 string commonTypeName;
528 for (vector<string>::iterator j = sortedTypeNames.begin(); j != sortedTypeNames.end(); ++j)
530 string portType = *j;
531 if (usedTypeNames.find(portType) == usedTypeNames.end())
533 commonTypeName = portType;
538 if (commonTypeName.empty())
539 commonTypeName = createFreshGenericTypeName();
541 usedTypeNames.insert(commonTypeName);
545 vector<string> compatibleTypeNames;
546 for (set<VuoCompilerPort *>::iterator j = connectedGenericPorts.begin(); j != connectedGenericPorts.end(); ++j)
553 vector<string> innermostCompatibleTypeNamesForPort;
554 for (vector<string>::iterator k = compatibleTypeNamesForPort.begin(); k != compatibleTypeNamesForPort.end(); ++k)
557 if (! innermostCompatibleTypeNamesForPort.empty())
559 if (compatibleTypeNames.empty())
560 compatibleTypeNames = innermostCompatibleTypeNamesForPort;
563 for (
int k = compatibleTypeNames.size() - 1; k >= 0; --k)
564 if (find(innermostCompatibleTypeNamesForPort.begin(), innermostCompatibleTypeNamesForPort.end(), compatibleTypeNames[k]) ==
565 innermostCompatibleTypeNamesForPort.end())
566 compatibleTypeNames.erase(compatibleTypeNames.begin() + k);
572 for (set<VuoCompilerPort *>::iterator j = connectedGenericPorts.begin(); j != connectedGenericPorts.end(); ++j)
579 vector<string> compatibleTypeNamesForPort;
581 for (vector<string>::iterator k = compatibleTypeNames.begin(); k != compatibleTypeNames.end(); ++k)
582 compatibleTypeNamesForPort.push_back(prefix + *k);
590 for (map<unsigned int, bool>::iterator i = genericTypeSuffixUsed.begin(); i != genericTypeSuffixUsed.end(); ++i)
592 unsigned int suffix = i->first;
594 genericTypeSuffixUsed[suffix] = used;
601 string VuoCompilerComposition::createFreshGenericTypeName(
void)
603 for (
unsigned int i = 1; ; ++i)
605 if (! genericTypeSuffixUsed[i])
607 genericTypeSuffixUsed[i] =
true;
628 auto getGenericTypeName = [&useOriginalType] (
VuoNode *node,
VuoPort *port)
638 if (specializedNodeClass)
639 genericType = dynamic_cast<VuoGenericType *>(specializedNodeClass->
getOriginalPortType(port->getClass()));
644 VuoCompilerPort *compilerPort = static_cast<VuoCompilerPort *>(port->getCompiler());
645 genericType = dynamic_cast<VuoGenericType *>(compilerPort->
getDataVuoType());
651 set<VuoPort *> correlatedPorts;
652 set<VuoNode *> nodesEnqueuedOrVisited;
653 list< pair<VuoNode *, string> > nodesToVisit;
655 string entryGenericType = getGenericTypeName(entryNode, entryPort);
656 if (! entryGenericType.empty())
658 nodesToVisit.push_back( make_pair(entryNode, entryGenericType) );
659 nodesEnqueuedOrVisited.insert(entryNode);
662 while (! nodesToVisit.empty())
664 VuoNode *currNode = nodesToVisit.front().first;
665 string currGenericType = nodesToVisit.front().second;
666 nodesToVisit.pop_front();
670 list<VuoPort *> correlatedPortsOnNode;
672 if (getGenericTypeName(currNode, currPort) == currGenericType)
673 correlatedPortsOnNode.push_back(currPort);
675 if (getGenericTypeName(currNode, currPort) == currGenericType)
676 correlatedPortsOnNode.push_back(currPort);
678 correlatedPorts.insert(correlatedPortsOnNode.begin(), correlatedPortsOnNode.end());
682 for (
VuoPort *port : correlatedPortsOnNode)
684 for (
VuoCable *cable : port->getConnectedCables())
705 if (nodesEnqueuedOrVisited.find(otherNode) == nodesEnqueuedOrVisited.end())
707 string otherGenericType = getGenericTypeName(otherNode, otherPort);
708 if (! otherGenericType.empty())
710 nodesToVisit.push_back( make_pair(otherNode, otherGenericType) );
711 nodesEnqueuedOrVisited.insert(otherNode);
718 return correlatedPorts;
728 return trigger ? trigger->
getBase() : NULL;
736 this->module = module;
744 Module *takenModule = module;
762 nodeGraphvizIdentifierUsed[ currNode->getCompiler()->getGraphvizIdentifier() ] = currNode;
764 auto isIdentifierAvailable = [
this, node] (
const string &identifier)
766 auto it = nodeGraphvizIdentifierUsed.find(identifier);
767 if (it == nodeGraphvizIdentifierUsed.end())
770 return it->second == node;
778 nodeGraphvizIdentifierUsed[uniqueIdentifier] = node;
787 nodeGraphvizIdentifierUsed.clear();
802 if (currComment != comment && currComment->
hasCompiler())
803 commentGraphvizIdentifierUsed[ currComment->getCompiler()->getGraphvizIdentifier() ] = currComment;
805 auto isIdentifierAvailable = [
this, comment] (
const string &identifier)
807 auto it = commentGraphvizIdentifierUsed.find(identifier);
808 if (it == commentGraphvizIdentifierUsed.end())
811 return it->second == comment;
817 commentGraphvizIdentifierUsed[uniqueIdentifier] = comment;
826 commentGraphvizIdentifierUsed.clear();
838 this->manuallyFirableInputNode = nodeContainingPort;
839 this->manuallyFirableInputPort = portFiredInto;
847 return manuallyFirableInputNode;
855 return manuallyFirableInputPort;
866 getBase()->getProtocolAwarePublishedPortOrder(activeProtocol,
true),
867 getBase()->getProtocolAwarePublishedPortOrder(activeProtocol,
false),
876 set<VuoCable *> cableSet,
877 set<VuoComment *> commentSet,
878 vector<VuoPublishedPort *> publishedInputPorts,
879 vector<VuoPublishedPort *> publishedOutputPorts,
880 string header,
string footer,
double xPositionOffset,
double yPositionOffset)
883 vector<VuoNode *> nodes;
884 for (set<VuoNode *>::iterator i = nodeSet.begin(); i != nodeSet.end(); ++i)
887 sort(nodes.begin(), nodes.end(), compareGraphvizIdentifiersOfNodes);
890 vector<VuoCable *> cables;
891 for (set<VuoCable *>::iterator i = cableSet.begin(); i != cableSet.end(); ++i)
892 cables.push_back(*i);
894 sort(cables.begin(), cables.end(), compareGraphvizIdentifiersOfCables);
897 vector<VuoComment *> comments;
898 for (set<VuoComment *>::iterator i = commentSet.begin(); i != commentSet.end(); ++i)
899 comments.push_back(*i);
901 sort(comments.begin(), comments.end(), compareGraphvizIdentifiersOfComments);
904 string compositionFooter = (! footer.empty()? footer :
"\n");
906 ostringstream output;
907 string nodeCommentSectionDivider =
"\n";
908 if ((nodes.empty() && publishedInputPorts.empty() && publishedOutputPorts.empty()) ||
909 (comments.empty() && cables.empty()))
910 nodeCommentSectionDivider =
"";
912 string commentCableSectionDivider =
"\n";
913 if (comments.empty() || cables.empty())
914 commentCableSectionDivider =
"";
917 output << compositionHeader;
918 output <<
"{" << endl;
921 for (vector<VuoNode *>::iterator i = nodes.begin(); i != nodes.end(); ++i)
923 string nodeDeclaration = ((*i)->hasCompiler() ?
924 (*i)->getCompiler()->getGraphvizDeclaration(
true, xPositionOffset, yPositionOffset,
925 manuallyFirableInputNode == *i ? manuallyFirableInputPort :
nullptr) :
926 (*i)->getRawGraphvizDeclaration());
927 output << nodeDeclaration << endl;
931 if (! publishedInputPorts.empty())
934 for (vector<VuoPublishedPort *>::iterator i = publishedInputPorts.begin(); i != publishedInputPorts.end(); ++i)
935 output <<
"|<" << (*i)->getClass()->getName() <<
">" << (*i)->getClass()->getName() <<
"\\r";
937 for (vector<VuoPublishedPort *>::iterator i = publishedInputPorts.begin(); i != publishedInputPorts.end(); ++i)
938 output << static_cast<VuoCompilerPublishedPort *>((*i)->getCompiler())->getGraphvizAttributes();
939 output <<
"];" << endl;
941 if (! publishedOutputPorts.empty())
944 for (vector<VuoPublishedPort *>::iterator i = publishedOutputPorts.begin(); i != publishedOutputPorts.end(); ++i)
945 output <<
"|<" << (*i)->getClass()->getName() <<
">" << (*i)->getClass()->getName() <<
"\\l";
948 for (vector<VuoPublishedPort *>::iterator i = publishedOutputPorts.begin(); i != publishedOutputPorts.end(); ++i)
949 output << static_cast<VuoCompilerPublishedPort *>((*i)->getCompiler())->getGraphvizAttributes();
951 output <<
"];" << endl;
954 output << nodeCommentSectionDivider;
957 for (vector<VuoComment *>::iterator i = comments.begin(); i != comments.end(); ++i)
959 string commentDeclaration = ((*i)->hasCompiler() ?
960 (*i)->getCompiler()->getGraphvizDeclaration(xPositionOffset, yPositionOffset) :
"");
961 output << commentDeclaration << endl;
964 output << commentCableSectionDivider;
967 for (vector<VuoCable *>::iterator i = cables.begin(); i != cables.end(); ++i)
974 output << compositionFooter;
985 for (
auto node :
getBase()->getNodes())
987 return compositeTarget;
993 bool VuoCompilerComposition::compareGraphvizIdentifiersOfNodes(
VuoNode *lhs,
VuoNode *rhs)
997 return lhsIdentifier.compare(rhsIdentifier) < 0;
1003 bool VuoCompilerComposition::compareGraphvizIdentifiersOfCables(
VuoCable *lhs,
VuoCable *rhs)
1007 return lhsIdentifier.compare(rhsIdentifier) < 0;
1013 bool VuoCompilerComposition::compareGraphvizIdentifiersOfComments(
VuoComment *lhs,
VuoComment *rhs)
1017 return lhsIdentifier.compare(rhsIdentifier) < 0;
1026 if (! oldPort || ! newPort)
1031 if (oldPortName == newPortName)
1035 VuoType *oldType = static_cast<VuoCompilerPort *>( oldPort->
getCompiler() )->getDataVuoType();
1036 VuoType *newType = static_cast<VuoCompilerPort *>( newPort->
getCompiler() )->getDataVuoType();
1037 if (oldType == newType)
1053 if (! oldPortClass || ! newPortClass)
1056 string oldPortName = oldPortClass->
getName();
1057 string newPortName = newPortClass->
getName();
1058 if (oldPortName == newPortName)
1062 VuoType *oldType = static_cast<VuoCompilerPortClass *>( oldPortClass->
getCompiler() )->getDataVuoType();
1063 VuoType *newType = static_cast<VuoCompilerPortClass *>( newPortClass->
getCompiler() )->getDataVuoType();
1064 if (oldType == newType)