34 set<VuoModuleManager *> VuoModuleManager::allModuleManagers;
43 this->compiler = compiler;
46 composition =
nullptr;
48 nodeLibrary =
nullptr;
50 updateGroup = dispatch_group_create();
52 allModuleManagers.insert(
this);
61 dispatch_release(updateGroup);
69 composition =
nullptr;
71 nodeLibrary =
nullptr;
73 for (
auto callbackIter : callbackForNodeClass)
74 Block_release(callbackIter.second.first);
75 callbackForNodeClass.clear();
77 allModuleManagers.erase(
this);
79 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
82 dispatch_group_wait(updateGroup, DISPATCH_TIME_FOREVER);
93 this->composition = composition;
101 this->codeWindow = codeWindow;
109 this->nodeLibrary = nodeLibrary;
127 map<pair<VuoType *, VuoType *>, vector<string> >::iterator iter = loadedTypecastClasses.find( make_pair(inType, outType) );
128 if (iter != loadedTypecastClasses.end())
131 return vector<string>();
146 return loadedTypesForNodeSet;
158 callbackForNodeClass[nodeClassName] = make_pair(callbackOnHeap,
false);
170 callbackForNodeClass[nodeClassName] = make_pair(callbackOnHeap,
true);
178 auto callbackIter = callbackForNodeClass.find(nodeClassName);
179 if (callbackIter != callbackForNodeClass.end())
181 Block_release(callbackIter->second.first);
182 callbackForNodeClass.erase(callbackIter);
197 set<string> compositionIdentifiers;
202 list< pair<string, VuoCompilerNodeClass *> > nodesToVisit;
206 if (node->hasCompiler())
209 node->getCompiler()->getIdentifier());
210 nodesToVisit.push_back(make_pair(fullyQualifiedNodeIdentifier, node->getNodeClass()->getCompiler()));
214 while (! nodesToVisit.empty())
216 pair<string, VuoCompilerNodeClass *> v = nodesToVisit.front();
217 string currNodeIdentifier = v.first;
219 nodesToVisit.pop_front();
221 if (currNodeClass == nodeClass)
222 compositionIdentifiers.insert(currNodeIdentifier);
228 if (containedNodeClass)
231 nodesToVisit.push_back(make_pair(fullyQualifiedNodeIdentifier, containedNodeClass));
238 return compositionIdentifiers;
245 const map<
string, pair<VuoCompilerModule *, VuoCompilerModule *> > &modulesModified,
246 const map<string, VuoCompilerModule *> &modulesRemoved,
VuoCompilerIssues *issues)
255 vector<VuoCompilerModule *> modulesAddedOrModified;
256 for (
auto m : modulesAdded)
257 modulesAddedOrModified.push_back(m.second);
258 for (
auto m : modulesModified)
259 modulesAddedOrModified.push_back(m.second.second);
261 vector<VuoCompilerModule *> modulesRemovedOrModified;
262 for (
auto m : modulesRemoved)
263 modulesRemovedOrModified.push_back(m.second);
264 for (
auto m : modulesModified)
265 modulesRemovedOrModified.push_back(m.second.first);
267 vector<VuoCompilerNodeClass *> nodeClassesAddedOrModified;
268 vector<VuoCompilerType *> typesAddedOrModified;
273 nodeClassesAddedOrModified.push_back(nodeClass);
278 typesAddedOrModified.push_back(type);
282 vector<string> nodeClassesRemovedOrModified;
283 vector<string> typesRemovedOrModified;
284 vector<string> librariesRemovedorModified;
290 nodeClassesRemovedOrModified.push_back(moduleKey);
295 typesRemovedOrModified.push_back(moduleKey);
297 librariesRemovedorModified.push_back(moduleKey);
301 set< pair<VuoCompilerModule *, VuoCompilerModule *> > modulesModifiedSet;
302 for (
auto m : modulesModified)
303 modulesModifiedSet.insert(m.second);
305 dispatch_group_async(updateGroup, dispatch_get_main_queue(), ^{
306 update(nodeClassesRemovedOrModified, nodeClassesAddedOrModified, typesRemovedOrModified, typesAddedOrModified,
307 librariesRemovedorModified, modulesModifiedSet, issues);
317 map<string, VuoCompilerNodeClass *> nodeClassesMap = compiler->
getNodeClasses();
318 map<string, VuoCompilerType *> typesMap = compiler->
getTypes();
320 vector<VuoCompilerNodeClass *> nodeClasses;
321 for (map<string, VuoCompilerNodeClass *>::iterator i = nodeClassesMap.begin(); i != nodeClassesMap.end(); ++i)
322 nodeClasses.push_back(i->second);
324 vector<VuoCompilerType *> types;
325 for (map<string, VuoCompilerType *>::iterator i = typesMap.begin(); i != typesMap.end(); ++i)
326 types.push_back(i->second);
329 update(vector<string>(), nodeClasses, vector<string>(), types, vector<string>(), set< pair<VuoCompilerModule *, VuoCompilerModule *> >(), &issues);
341 void VuoModuleManager::update(
const vector<string> &nodeClassesToRemove,
const vector<VuoCompilerNodeClass *> &nodeClassesToAdd,
342 const vector<string> &typesToRemove,
const vector<VuoCompilerType *> &typesToAdd,
343 const vector<string> &librariesToRemove,
344 const set< pair<VuoCompilerModule *, VuoCompilerModule *> > &modulesModified,
349 updateLoadedTypecastClasses(nodeClassesToRemove, nodeClassesToAdd, typesToRemove, typesToAdd);
350 updateLoadedTypesByNodeSet(typesToRemove, typesToAdd);
356 map<string, VuoCompilerNodeClass *> dependenciesInvalidated;
357 set<string> dependenciesLost;
358 map<string, string> originalGenericNodeClassName;
359 if (! (nodeClassesToRemove.empty() && typesToRemove.empty() && librariesToRemove.empty()) )
363 set<string> dependencies = compiler->getDependenciesForComposition(composition->
getBase()->
getCompiler());
365 vector<string> sortedDependencies(dependencies.begin(), dependencies.end());
366 std::sort(sortedDependencies.begin(), sortedDependencies.end());
368 vector<string> sortedNodeClassesToRemove(nodeClassesToRemove.begin(), nodeClassesToRemove.end());
369 std::sort(sortedNodeClassesToRemove.begin(), sortedNodeClassesToRemove.end());
371 vector<string> sortedTypesToRemove(typesToRemove.begin(), typesToRemove.end());
372 std::sort(sortedTypesToRemove.begin(), sortedTypesToRemove.end());
374 vector<string> sortedLibrariesToRemove(librariesToRemove.begin(), librariesToRemove.end());
375 std::sort(sortedLibrariesToRemove.begin(), sortedLibrariesToRemove.end());
377 set<string> dependenciesInvalidatedSet;
378 std::set_intersection(sortedNodeClassesToRemove.begin(), sortedNodeClassesToRemove.end(),
379 sortedDependencies.begin(), sortedDependencies.end(),
380 std::inserter(dependenciesInvalidatedSet, dependenciesInvalidatedSet.end()));
381 std::set_intersection(sortedTypesToRemove.begin(), sortedTypesToRemove.end(),
382 sortedDependencies.begin(), sortedDependencies.end(),
383 std::inserter(dependenciesInvalidatedSet, dependenciesInvalidatedSet.end()));
384 std::set_intersection(sortedLibrariesToRemove.begin(), sortedLibrariesToRemove.end(),
385 sortedDependencies.begin(), sortedDependencies.end(),
386 std::inserter(dependenciesInvalidatedSet, dependenciesInvalidatedSet.end()));
392 if (node->getNodeClass()->hasCompiler())
394 set<string> nodeClassDependencies = node->getNodeClass()->getCompiler()->getDependencies();
395 set<string> nodeClassDependenciesInvalidated;
396 std::set_intersection(nodeClassDependencies.begin(), nodeClassDependencies.end(),
397 typesToRemove.begin(), typesToRemove.end(),
398 std::inserter(nodeClassDependenciesInvalidated, nodeClassDependenciesInvalidated.end()));
400 if (! nodeClassDependenciesInvalidated.empty())
401 dependenciesInvalidatedSet.insert(node->getNodeClass()->getClassName());
409 if (node->getNodeClass()->hasCompiler())
412 if (specializedNodeClass)
415 if (find(nodeClassesToRemove.begin(), nodeClassesToRemove.end(), genericNodeClassName) != nodeClassesToRemove.end())
417 dependenciesInvalidatedSet.insert(genericNodeClassName);
418 originalGenericNodeClassName[ specializedNodeClass->
getBase()->
getClassName() ] = genericNodeClassName;
426 for (set<string>::iterator i = dependenciesInvalidatedSet.begin(); i != dependenciesInvalidatedSet.end(); ++i)
428 string dependency = *i;
430 bool foundReplacement =
false;
431 for (set< pair<VuoCompilerModule *, VuoCompilerModule *> >::const_iterator j = modulesModified.begin(); j != modulesModified.end(); ++j)
433 if (j->first->getPseudoBase()->getModuleKey() == dependency)
436 if (replacementNodeClass)
437 dependenciesInvalidated[dependency] = replacementNodeClass;
439 foundReplacement =
true;
444 if (! foundReplacement)
445 dependenciesLost.insert(dependency);
451 map<string, VuoCompilerNodeClass *> dependenciesAdded;
452 if (! nodeClassesToAdd.empty())
461 string addedNodeClassName = addedNodeClass->getBase()->getClassName();
462 if (addedNodeClassName == nodeClassName)
464 dependenciesAdded[nodeClassName] = addedNodeClass;
468 dependenciesAdded[addedNodeClassName] = addedNodeClass;
469 originalGenericNodeClassName[nodeClassName] = addedNodeClassName;
477 if (! (dependenciesInvalidated.empty() && dependenciesLost.empty() && dependenciesAdded.empty()) )
488 auto nameIter = originalGenericNodeClassName.find(nodeClassName);
489 bool isSpecializedNodeClass = (nameIter != originalGenericNodeClassName.end());
490 if (isSpecializedNodeClass)
491 nodeClassName = nameIter->second;
494 map<string, VuoCompilerNodeClass *>::const_iterator invIter = dependenciesInvalidated.find(nodeClassName);
495 if (invIter != dependenciesInvalidated.end())
497 replacementNodeClass = invIter->second;
501 map<string, VuoCompilerNodeClass *>::const_iterator addIter = dependenciesAdded.find(nodeClassName);
502 if (addIter != dependenciesAdded.end())
504 replacementNodeClass = addIter->second;
508 VuoNode *replacementNode =
nullptr;
509 if (replacementNodeClass)
511 if (isSpecializedNodeClass)
514 replacementNode = composition->
createBaseNode(replacementNodeClass, node);
516 else if (dependenciesLost.find(nodeClassName) != dependenciesLost.end())
537 for (set< pair<VuoCompilerModule *, VuoCompilerModule *> >::const_iterator i = modulesModified.begin(); i != modulesModified.end(); ++i)
542 if (oldNodeClass && newNodeClass)
548 string snapshotWithNewModules = composition->
takeSnapshot();
565 for (vector<VuoCompilerNodeClass *>::const_iterator i = nodeClassesToAdd.begin(); i != nodeClassesToAdd.end(); ++i)
567 string nodeClassName = (*i)->getBase()->getClassName();
568 auto callbackIter = callbackForNodeClass.find(nodeClassName);
569 if (callbackIter != callbackForNodeClass.end())
574 if (! callbackIter->second.second)
582 if (isResponsibleForReportingErrors(
this, errors, nodeClassesToAdd))
589 showErrorDialog(errors);
607 const vector<VuoCompilerNodeClass *> &nodeClassesToAdd)
620 string nodeClassName;
627 else if (! nodeClassesToAdd.empty())
630 nodeClassName = nodeClassesToAdd.front()->getBase()->getClassName();
637 if (! nodeClassName.empty())
639 if (m->codeWindow->getNodeClassName() == nodeClassName)
640 managerWithCodeEditor = m;
643 else if (m->composition)
645 if (! issuePath.empty())
647 string issueDir, file, ext;
650 managerWithCompositionLocal = m;
659 VuoModuleManager *responsibleManager = (managerWithCodeEditor ? managerWithCodeEditor :
660 (managerWithCompositionLocal ? managerWithCompositionLocal :
662 return responsibleManager == currManager;
670 QString errorSummary = VuoEditor::tr(
"There was a problem loading one or more nodes into your library.");
671 QString errorDisclosureDetails = QString::fromStdString(errors->
getLongDescription(
false));
673 QStringList brokenModulePaths;
675 brokenModulePaths.append(QString::fromStdString(issue.
getFilePath()));
676 brokenModulePaths.removeDuplicates();
678 QMessageBox messageBox;
681 messageBox.setWindowFlags(Qt::Window | Qt::WindowTitleHint | Qt::CustomizeWindowHint | Qt::WindowMaximizeButtonHint);
685 messageBox.setTextFormat(Qt::RichText);
686 messageBox.setStandardButtons(QMessageBox::Discard | QMessageBox::Cancel);
687 messageBox.setButtonText(QMessageBox::Discard, VuoEditor::tr(
"Move Broken Nodes to Trash"));
688 messageBox.setButtonText(QMessageBox::Cancel, VuoEditor::tr(
"Not Now"));
689 messageBox.setDefaultButton(QMessageBox::Discard);
690 messageBox.setText(errorSummary);
691 messageBox.setStyleSheet(
"#qt_msgbox_informativelabel, QMessageBoxDetailsText {" + fonts->
getCSS(fonts->
dialogBodyFont()) +
"}");
692 messageBox.setDetailedText(errorDisclosureDetails);
695 static_cast<QPushButton *
>(messageBox.button(QMessageBox::Cancel))->setAutoDefault(
false);
696 messageBox.button(QMessageBox::Cancel)->setFocus();
700 if (messageBox.exec() == QMessageBox::Discard)
705 foreach (QString path, brokenModulePaths)
718 void VuoModuleManager::updateLoadedTypecastClasses(
const vector<string> &nodeClassesToRemove,
719 const vector<VuoCompilerNodeClass *> &nodeClassesToAdd,
720 const vector<string> &typesToRemove,
721 const vector<VuoCompilerType *> &typesToAdd)
724 for (map<pair<VuoType *, VuoType *>, vector<string> >::iterator i = loadedTypecastClasses.begin(); i != loadedTypecastClasses.end(); )
726 if (find(typesToRemove.begin(), typesToRemove.end(), i->first.first->getModuleKey()) != typesToRemove.end() ||
727 find(typesToRemove.begin(), typesToRemove.end(), i->first.second->getModuleKey()) != typesToRemove.end())
728 loadedTypecastClasses.erase(i++);
734 for (map<pair<VuoType *, VuoType *>, vector<string> >::iterator i = loadedTypecastClasses.begin(); i != loadedTypecastClasses.end(); ++i)
736 vector<string> stillLoaded;
737 std::set_difference(i->second.begin(), i->second.end(),
738 nodeClassesToRemove.begin(), nodeClassesToRemove.end(),
739 std::back_inserter(stillLoaded));
740 i->second = stillLoaded;
744 for (vector<VuoCompilerNodeClass *>::const_iterator i = nodeClassesToAdd.begin(); i != nodeClassesToAdd.end(); ++i)
756 pair<VuoType *, VuoType *> inTypeOutType = make_pair
761 loadedTypecastClasses[inTypeOutType].push_back(nodeClass->
getClassName());
768 map<string, VuoCompilerType *> loadedTypes = compiler->
getTypes();
769 for (vector<VuoCompilerType *>::const_iterator i = typesToAdd.begin(); i != typesToAdd.end(); ++i)
771 VuoType *type = (*i)->getBase();
776 map<string, VuoCompilerType *>::iterator listTypeIter = loadedTypes.find(
"VuoList_" + typeName);
777 if (listTypeIter != loadedTypes.end())
779 VuoType *listType = listTypeIter->second->getBase();
781 string nodeClassNamePrefix[3] = {
"vuo.list.get.first.",
"vuo.list.get.last.",
"vuo.list.get.random."};
782 for (
int p = 0; p < 3; ++p)
784 string nodeClassName = nodeClassNamePrefix[p] + typeName;
785 pair<VuoType *, VuoType *> inTypeOutType = make_pair(listType, type);
787 if (std::find(loadedTypecastClasses[inTypeOutType].begin(), loadedTypecastClasses[inTypeOutType].end(), nodeClassName) == loadedTypecastClasses[inTypeOutType].end())
788 loadedTypecastClasses[inTypeOutType].push_back(nodeClassName);
792 string nodeClassName =
"vuo.list.count." + typeName;
793 pair<VuoType *, VuoType *> inTypeOutType = make_pair(listType, loadedTypes[
"VuoInteger"]->getBase());
795 if (std::find(loadedTypecastClasses[inTypeOutType].begin(), loadedTypecastClasses[inTypeOutType].end(), nodeClassName) == loadedTypecastClasses[inTypeOutType].end())
796 loadedTypecastClasses[inTypeOutType].push_back(nodeClassName);
800 string nodeClassName =
"vuo.list.populated." + typeName;
801 pair<VuoType *, VuoType *> inTypeOutType = make_pair(listType, loadedTypes[
"VuoBoolean"]->getBase());
803 if (std::find(loadedTypecastClasses[inTypeOutType].begin(), loadedTypecastClasses[inTypeOutType].end(), nodeClassName) == loadedTypecastClasses[inTypeOutType].end())
804 loadedTypecastClasses[inTypeOutType].push_back(nodeClassName);
808 string nodeClassName =
"vuo.data.summarize." + typeName;
809 pair<VuoType *, VuoType *> inTypeOutType = make_pair(type, loadedTypes[
"VuoText"]->getBase());
811 if (std::find(loadedTypecastClasses[inTypeOutType].begin(), loadedTypecastClasses[inTypeOutType].end(), nodeClassName) == loadedTypecastClasses[inTypeOutType].end() &&
812 typeName !=
"VuoData")
813 loadedTypecastClasses[inTypeOutType].push_back(nodeClassName);
817 string nodeClassName =
"vuo.type.tree.value." + typeName;
818 pair<VuoType *, VuoType *> inTypeOutType = make_pair(loadedTypes[
"VuoTree"]->getBase(), type);
820 if (std::find(loadedTypecastClasses[inTypeOutType].begin(), loadedTypecastClasses[inTypeOutType].end(), nodeClassName) == loadedTypecastClasses[inTypeOutType].end())
821 loadedTypecastClasses[inTypeOutType].push_back(nodeClassName);
826 string nodeClassName =
"vuo.point.length." + typeName;
827 pair<VuoType *, VuoType *> inTypeOutType = make_pair(type, loadedTypes[
"VuoReal"]->getBase());
829 if (std::find(loadedTypecastClasses[inTypeOutType].begin(), loadedTypecastClasses[inTypeOutType].end(), nodeClassName) == loadedTypecastClasses[inTypeOutType].end())
830 loadedTypecastClasses[inTypeOutType].push_back(nodeClassName);
841 for (vector<VuoCompilerType *>::const_iterator i = typesToAdd.begin(); i != typesToAdd.end(); ++i)
843 VuoType *type = (*i)->getBase();
848 string nodeClassName =
"vuo.type.real.enum." + typeName;
849 pair<VuoType *, VuoType *> inTypeOutType = make_pair(loadedTypes[
"VuoReal"]->getBase(), type);
851 if (std::find(loadedTypecastClasses[inTypeOutType].begin(), loadedTypecastClasses[inTypeOutType].end(), nodeClassName) == loadedTypecastClasses[inTypeOutType].end())
852 loadedTypecastClasses[inTypeOutType].push_back(nodeClassName);
860 void VuoModuleManager::updateLoadedTypesByNodeSet(
const vector<string> &typesToRemove,
const vector<VuoCompilerType *> &typesToAdd)
862 set<string> explicitCoreTypes;
863 explicitCoreTypes.insert(
"VuoLayer");
866 for (map<
string, set<VuoCompilerType *> >::iterator i = loadedTypesForNodeSet.begin(); i != loadedTypesForNodeSet.end(); ++i)
868 for (set<VuoCompilerType *>::iterator j = i->second.begin(); j != i->second.end(); )
870 if (find(typesToRemove.begin(), typesToRemove.end(), (*j)->getBase()->getModuleKey()) != typesToRemove.end())
871 i->second.erase(j++);
878 map<string, VuoCompilerType *> loadedTypes = compiler->
getTypes();
879 for (vector<VuoCompilerType *>::const_iterator i = typesToAdd.begin(); i != typesToAdd.end(); ++i)
885 string nodeSetName = (explicitCoreTypes.find(typeName) != explicitCoreTypes.end()?
"" :
887 getPrimaryAffiliatedNodeSetForType(typeName)));
891 loadedTypesForNodeSet[nodeSetName].insert(type);
894 if (listTypeIter != loadedTypes.end())
895 loadedTypesForNodeSet[nodeSetName].insert(listTypeIter->second);
904 string VuoModuleManager::getPrimaryAffiliatedNodeSetForType(
const string &typeName)
906 map<string, string> nodeSetForType;
907 nodeSetForType[
"VuoAnchor"] =
"vuo.layer";
908 nodeSetForType[
"VuoAudioSamples"] =
"vuo.audio";
909 nodeSetForType[
"VuoBlendMode"] =
"vuo.image";
910 nodeSetForType[
"VuoCoordinateUnit"] =
"vuo.window";
911 nodeSetForType[
"VuoCubemap"] =
"vuo.image";
912 nodeSetForType[
"VuoCursor"] =
"vuo.window";
913 nodeSetForType[
"VuoCurve"] =
"vuo.motion";
914 nodeSetForType[
"VuoCurveEasing"] =
"vuo.motion";
915 nodeSetForType[
"VuoDiode"] =
"vuo.math";
916 nodeSetForType[
"VuoFont"] =
"vuo.font";
917 nodeSetForType[
"VuoHorizontalAlignment"] =
"vuo.layer";
918 nodeSetForType[
"VuoImageColorDepth"] =
"vuo.image";
919 nodeSetForType[
"VuoImageWrapMode"] =
"vuo.image";
920 nodeSetForType[
"VuoIntegerRange"] =
"vuo.math";
921 nodeSetForType[
"VuoInteraction"] =
"vuo.ui";
922 nodeSetForType[
"VuoInteractionType"] =
"vuo.ui";
923 nodeSetForType[
"VuoListPosition"] =
"vuo.list";
924 nodeSetForType[
"VuoLoopType"] =
"vuo.motion";
925 nodeSetForType[
"VuoMathExpressionList"] =
"vuo.math";
926 nodeSetForType[
"VuoMesh"] =
"vuo.mesh";
927 nodeSetForType[
"VuoModifierKey"] =
"vuo.keyboard";
928 nodeSetForType[
"VuoOrientation"] =
"vuo.ui";
929 nodeSetForType[
"VuoRange"] =
"vuo.math";
930 nodeSetForType[
"VuoRectangle"] =
"vuo.image";
931 nodeSetForType[
"VuoRenderedLayers"] =
"vuo.ui";
932 nodeSetForType[
"VuoScreen"] =
"vuo.screen";
933 nodeSetForType[
"VuoShader"] =
"vuo.shader";
934 nodeSetForType[
"VuoSortOrder"] =
"vuo.list";
935 nodeSetForType[
"VuoTextCase"] =
"vuo.text";
936 nodeSetForType[
"VuoTextComparison"] =
"vuo.text";
937 nodeSetForType[
"VuoTextSort"] =
"vuo.text";
938 nodeSetForType[
"VuoTransform"] =
"vuo.transform";
939 nodeSetForType[
"VuoTransform2d"] =
"vuo.transform";
940 nodeSetForType[
"VuoTree"] =
"vuo.tree";
941 nodeSetForType[
"VuoUrl"] =
"vuo.url";
942 nodeSetForType[
"VuoUuid"] =
"vuo.ui";
943 nodeSetForType[
"VuoVerticalAlignment"] =
"vuo.layer";
944 nodeSetForType[
"VuoWave"] =
"vuo.motion";
945 nodeSetForType[
"VuoWindowDescription"] =
"vuo.window";
946 nodeSetForType[
"VuoWindowProperty"] =
"vuo.window";
947 nodeSetForType[
"VuoWindowReference"] =
"vuo.window";
948 nodeSetForType[
"VuoWrapMode"] =
"vuo.math";
950 map<string, string>::iterator i = nodeSetForType.find(typeName);
951 if (i != nodeSetForType.end())