std::vector<NodeAnimPtr > AnimationModule::getChildrenNodes(const NodeAnimPtr& node) const { std::vector<NodeAnimPtr > children; AnimatedItemTypeEnum nodeType = node->getItemType(); if (nodeType == eAnimatedItemTypeGroup) { // If the node is a group, make all its children to be a child in the tree view NodeGroupPtr nodeGroup = node->getInternalNode()->isEffectNodeGroup(); assert(nodeGroup); NodesList nodes = nodeGroup->getNodes(); for (NodesList::const_iterator it = nodes.begin(); it != nodes.end(); ++it) { NodePtr childNode = (*it); NodeAnimPtr isInDopeSheet = findNodeAnim( childNode ); if (isInDopeSheet) { children.push_back(isInDopeSheet); } } } else if ( node->isTimeNode() ) { // If the node is a time node, all input nodes recursively are considered to be a child std::list<NodePtr> markedNodes; _imp->getInputs_recursive(node->getInternalNode(), markedNodes, &children); } return children; }
bool GuiAppInstance::checkAllReadersModificationDate(bool errorAndWarn) { NodesList allNodes; SequenceTime time = getProject()->getCurrentTime(); getProject()->getNodes_recursive(allNodes, true); bool changed = false; for (NodesList::iterator it = allNodes.begin(); it != allNodes.end(); ++it) { if ( (*it)->getEffectInstance()->isReader() ) { KnobPtr fileKnobI = (*it)->getKnobByName(kOfxImageEffectFileParamName); if (!fileKnobI) { continue; } boost::shared_ptr<KnobGuiI> knobUi_i = fileKnobI->getKnobGuiPointer(); KnobGuiFile* isFileKnob = dynamic_cast<KnobGuiFile*>( knobUi_i.get() ); if (!isFileKnob) { continue; } changed |= isFileKnob->checkFileModificationAndWarn(time, errorAndWarn); } } return changed; }
void ViewerNodePrivate::getAllViewerNodes(bool inGroupOnly, std::list<ViewerNodePtr>& viewerNodes) const { NodeCollectionPtr collection; if (inGroupOnly) { collection = _publicInterface->getNode()->getGroup(); } else { collection = _publicInterface->getApp()->getProject(); } NodesList nodes; if (inGroupOnly) { nodes = collection->getNodes(); } else { collection->getNodes_recursive(nodes, false); } for (NodesList::iterator it = nodes.begin(); it != nodes.end(); ++it) { if (!(*it)->isActivated()) { continue; } ViewerNodePtr isViewer = (*it)->isEffectViewerNode(); if (isViewer) { viewerNodes.push_back(isViewer); } } }
static KnobPtr findMaster(const KnobPtr & knob, const NodesList & allNodes, const std::string& masterKnobName, const std::string& masterNodeName, const std::string& masterTrackName, const std::map<std::string,std::string>& oldNewScriptNamesMapping) { ///we need to cycle through all the nodes of the project to find the real master NodePtr masterNode; std::string masterNodeNameToFind = masterNodeName; /* When copy pasting, the new node copied has a script-name different from what is inside the serialization because 2 nodes cannot co-exist with the same script-name. We keep in the map the script-names mapping */ std::map<std::string,std::string>::const_iterator foundMapping = oldNewScriptNamesMapping.find(masterNodeName); if (foundMapping != oldNewScriptNamesMapping.end()) { masterNodeNameToFind = foundMapping->second; } for (NodesList::const_iterator it2 = allNodes.begin(); it2 != allNodes.end(); ++it2) { if ((*it2)->getScriptName() == masterNodeNameToFind) { masterNode = *it2; break; } } if (!masterNode) { qDebug() << "Link slave/master for " << knob->getName().c_str() << " failed to restore the following linkage: " << masterNodeNameToFind.c_str(); return KnobPtr(); } if (!masterTrackName.empty()) { boost::shared_ptr<TrackerContext> context = masterNode->getTrackerContext(); if (context) { TrackMarkerPtr marker = context->getMarkerByName(masterTrackName); if (marker) { return marker->getKnobByName(masterKnobName); } } } else { ///now that we have the master node, find the corresponding knob const std::vector< KnobPtr > & otherKnobs = masterNode->getKnobs(); for (std::size_t j = 0; j < otherKnobs.size(); ++j) { if ( (otherKnobs[j]->getName() == masterKnobName) && otherKnobs[j]->getIsPersistant() ) { return otherKnobs[j]; break; } } } qDebug() << "Link slave/master for " << knob->getName().c_str() << " failed to restore the following linkage: " << masterNodeNameToFind.c_str(); return KnobPtr(); }
void Gui::renderViewersAndRefreshKnobsAfterTimelineTimeChange(SequenceTime time, int reason) { TimeLine* timeline = qobject_cast<TimeLine*>( sender() ); if ( timeline != getApp()->getTimeLine().get() ) { return; } assert( QThread::currentThread() == qApp->thread() ); if ( (reason == eTimelineChangeReasonUserSeek) || ( reason == eTimelineChangeReasonDopeSheetEditorSeek) || ( reason == eTimelineChangeReasonCurveEditorSeek) ) { if ( getApp()->checkAllReadersModificationDate(true) ) { return; } } boost::shared_ptr<Project> project = getApp()->getProject(); bool isPlayback = reason == eTimelineChangeReasonPlaybackSeek; ///Refresh all visible knobs at the current time if ( !getApp()->isGuiFrozen() ) { for (std::list<DockablePanel*>::const_iterator it = _imp->openedPanels.begin(); it != _imp->openedPanels.end(); ++it) { NodeSettingsPanel* nodePanel = dynamic_cast<NodeSettingsPanel*>(*it); if (nodePanel) { NodePtr node = nodePanel->getNode()->getNode(); node->getEffectInstance()->refreshAfterTimeChange(isPlayback, time); NodesList children; node->getChildrenMultiInstance(&children); for (NodesList::iterator it2 = children.begin(); it2 != children.end(); ++it2) { (*it2)->getEffectInstance()->refreshAfterTimeChange(isPlayback, time); } } } } ViewerInstance* leadViewer = getApp()->getLastViewerUsingTimeline(); const std::list<ViewerTab*>& viewers = getViewersList(); ///Syncrhronize viewers for (std::list<ViewerTab*>::const_iterator it = viewers.begin(); it != viewers.end(); ++it) { if ( ( (*it)->getInternalNode() == leadViewer ) && isPlayback ) { continue; } if ( (*it)->getInternalNode()->isDoingPartialUpdates() ) { //When tracking, we handle rendering separatly continue; } (*it)->getInternalNode()->renderCurrentFrame(!isPlayback); } } // Gui::renderViewersAndRefreshKnobsAfterTimelineTimeChange
void Document::loadFromCurrenttDir( const String& fileName_ ) { FRL_EXCEPT_GUARD(); String currDir = io::fs::getCurrentDirectory(); io::fs::addSlashToEndPath( currDir ); fileName = currDir + fileName_; String buffer; loadFileToString( fileName, buffer ); buffer.erase( std::remove_if( buffer.begin(), buffer.end(), private_::isCRLF ), buffer.end() ); // remove CRLF parseHeader( buffer ); NodesList tmpMap = Parser::getSubNodes( buffer ); if( tmpMap.size() > 1 ) FRL_THROW_S_CLASS( Document::BrokenXML ); // must be one root node root = (*tmpMap.begin()); }
bool CCPathFinderNetwork::findPath(CCCollideable *objectToPath, Path &pathResult, const PathNode *fromNode, const PathNode *toNode) { if( fromNode != NULL && toNode != NULL ) { NodesList<const PathNode, 50> previousNodes; previousNodes.add( fromNode ); pathTargetNode = toNode; path.distance = 0.0f; pathingFrom = fromNode; if( followPath( objectToPath, path, 0, 0.0f, previousNodes, fromNode, toNode ) ) { pathResult = path; return true; } } return false; }
std::list<Effect*> Group::getChildren() const { std::list<Effect*> ret; if ( !_collection.lock() ) { PythonSetNullError(); return ret; } NodesList nodes = _collection.lock()->getNodes(); for (NodesList::iterator it = nodes.begin(); it != nodes.end(); ++it) { if ( (*it)->isActivated() ) { Effect* effect = App::createEffectFromNodeWrapper(*it); assert(effect); ret.push_back(effect); } } return ret; }
void moveGroupNode(DopeSheetEditor* model, const NodePtr& node, double dt) { NodeGroupPtr group = node->isEffectNodeGroup(); assert(group); NodesList nodes; group->getNodes_recursive(nodes, true); for (NodesList::iterator it = nodes.begin(); it != nodes.end(); ++it) { NodeGuiPtr nodeGui = boost::dynamic_pointer_cast<NodeGui>( (*it)->getNodeGui() ); assert(nodeGui); std::string pluginID = (*it)->getPluginID(); NodeGroupPtr isChildGroup = (*it)->isEffectNodeGroup(); // Move readers #ifndef NATRON_ENABLE_IO_META_NODES if ( ReadNode::isBundledReader( pluginID, node->getApp()->wasProjectCreatedWithLowerCaseIDs() ) ) { #else if (pluginID == PLUGINID_NATRON_READ) { #endif moveReader(*it, dt); } else if (pluginID == PLUGINID_OFX_TIMEOFFSET) { moveTimeOffset(*it, dt); } else if (pluginID == PLUGINID_OFX_FRAMERANGE) { moveFrameRange(*it, dt); } else if (isChildGroup) { moveGroupNode(model, *it, dt); } // Move keyframes const KnobsVec &knobs = (*it)->getKnobs(); for (KnobsVec::const_iterator knobIt = knobs.begin(); knobIt != knobs.end(); ++knobIt) { const KnobIPtr& knob = *knobIt; if ( !knob->hasAnimation() ) { continue; } for (int dim = 0; dim < knob->getDimension(); ++dim) { if ( !knob->isAnimated( dim, ViewIdx(0) ) ) { continue; } KeyFrameSet keyframes = knob->getCurve(ViewIdx(0), dim)->getKeyFrames_mt_safe(); for (KeyFrameSet::iterator kfIt = keyframes.begin(); kfIt != keyframes.end(); ++kfIt) { KeyFrame kf = (*kfIt); KeyFrame fake; knob->moveValueAtTime(eCurveChangeReasonDopeSheet, kf.getTime(), ViewSpec::all(), dim, dt, 0, &fake); } } } } } // moveGroupNode NATRON_NAMESPACE_ANONYMOUS_EXIT ////////////////////////// DSMoveKeysCommand ////////////////////////// DSMoveKeysAndNodesCommand::DSMoveKeysAndNodesCommand(const DSKeyPtrList &keys, const std::vector<DSNodePtr >& nodes, double dt, DopeSheetEditor *model, QUndoCommand *parent) : QUndoCommand(parent), _keys(keys), _nodes(), _dt(dt), _model(model) { setText( tr("Move selected keys") ); std::set<NodePtr > nodesSet; for (std::vector<DSNodePtr >::const_iterator it = nodes.begin(); it != nodes.end(); ++it) { DopeSheetItemType type = (*it)->getItemType(); if ( (type != eDopeSheetItemTypeReader) && ( type != eDopeSheetItemTypeGroup) && ( type != eDopeSheetItemTypeTimeOffset) && ( type != eDopeSheetItemTypeFrameRange) ) { //Note that Retime nodes cannot be moved continue; } _nodes.push_back(*it); nodesSet.insert( (*it)->getInternalNode() ); NodeGroupPtr isGroup = (*it)->getInternalNode()->isEffectNodeGroup(); if (isGroup) { NodesList recurseNodes; isGroup->getNodes_recursive(recurseNodes, true); for (NodesList::iterator it = recurseNodes.begin(); it != recurseNodes.end(); ++it) { nodesSet.insert(*it); } } } for (DSKeyPtrList::iterator it = _keys.begin(); it != _keys.end(); ++it) { KnobHolderPtr holder = (*it)->getContext()->getInternalKnob()->getHolder(); assert(holder); EffectInstancePtr isEffect = toEffectInstance(holder); if (isEffect) { nodesSet.insert( isEffect->getNode() ); } } for (std::set<NodePtr >::iterator it = nodesSet.begin(); it != nodesSet.end(); ++it) { _allDifferentNodes.push_back(*it); } } void DSMoveKeysAndNodesCommand::undo() { moveSelection(-_dt); }
void ViewerNode::loadSubGraph(const SERIALIZATION_NAMESPACE::NodeSerialization* projectSerialization, const SERIALIZATION_NAMESPACE::NodeSerialization* pyPlugSerialization) { if (getNode()->isPyPlug()) { assert(pyPlugSerialization); // Handle the pyplug case on NodeGroup implementation NodeGroup::loadSubGraph(projectSerialization, pyPlugSerialization); } else if (projectSerialization) { // If there's a project serialization load it. There will be children only if the user edited the Viewer group if (!projectSerialization->_children.empty()) { // The subgraph was not initialized in this case assert(getNodes().empty()); EffectInstancePtr thisShared = shared_from_this(); // Clear nodes that were created if any clearGroupWithoutViewerProcess(); // Restore group createNodesFromSerialization(projectSerialization->_children, eCreateNodesFromSerializationFlagsNone, 0); setSubGraphEditedByUser(true); } else { // We are loading a non edited default viewer, just ensure the initial setup was done if (!_imp->internalViewerProcessNode[0].lock()) { setupGraph(true); } setSubGraphEditedByUser(false); } } // Ensure the internal viewer process node exists if (!_imp->internalViewerProcessNode[0].lock()) { NodePtr internalViewerNode[2]; NodesList nodes = getNodes(); int viewerProcessNode_i = 0; for (NodesList::iterator it = nodes.begin(); it != nodes.end(); ++it) { if ((*it)->isEffectViewerInstance()) { internalViewerNode[viewerProcessNode_i] = *it; ++viewerProcessNode_i; if (viewerProcessNode_i == 2) { break; } } } assert(internalViewerNode[0] && internalViewerNode[1]); if (!internalViewerNode[0] || !internalViewerNode[1]) { throw std::invalid_argument("Viewer: No internal viewer process!"); } _imp->internalViewerProcessNode[0] = internalViewerNode[0]; _imp->internalViewerProcessNode[1] = internalViewerNode[1]; Q_EMIT internalViewerCreated(); } assert(getViewerProcessNode(0)); assert(getViewerProcessNode(1)); _imp->refreshInputChoices(true); refreshInputFromChoiceMenu(0); refreshInputFromChoiceMenu(1); }
void ProjectGuiSerialization::initialize(const ProjectGui* projectGui) { NodesList activeNodes; projectGui->getInternalProject()->getActiveNodesExpandGroups(&activeNodes); _serializedNodes.clear(); for (NodesList::iterator it = activeNodes.begin(); it != activeNodes.end(); ++it) { boost::shared_ptr<NodeGuiI> nodegui_i = (*it)->getNodeGui(); if (!nodegui_i) { continue; } NodeGuiPtr nodegui = boost::dynamic_pointer_cast<NodeGui>(nodegui_i); if ( nodegui->isVisible() ) { boost::shared_ptr<NodeCollection> isInCollection = (*it)->getGroup(); NodeGroup* isCollectionAGroup = dynamic_cast<NodeGroup*>( isInCollection.get() ); if (!isCollectionAGroup) { ///Nodes within a group will be serialized recursively in the node group serialization NodeGuiSerialization state; nodegui->serialize(&state); _serializedNodes.push_back(state); } ViewerInstance* viewer = (*it)->isEffectViewer(); if (viewer) { ViewerTab* tab = projectGui->getGui()->getViewerTabForInstance(viewer); assert(tab); ViewerData viewerData; double zoompar; tab->getViewer()->getProjection(&viewerData.zoomLeft, &viewerData.zoomBottom, &viewerData.zoomFactor, &zoompar); viewerData.userRoI = tab->getViewer()->getUserRegionOfInterest(); viewerData.userRoIenabled = tab->getViewer()->isUserRegionOfInterestEnabled(); viewerData.isClippedToProject = tab->isClippedToProject(); viewerData.autoContrastEnabled = tab->isAutoContrastEnabled(); viewerData.gain = tab->getGain(); viewerData.gamma = tab->getGamma(); viewerData.colorSpace = tab->getColorSpace(); viewerData.channels = tab->getChannelsString(); viewerData.renderScaleActivated = tab->getRenderScaleActivated(); viewerData.mipMapLevel = tab->getMipMapLevel(); viewerData.zoomOrPanSinceLastFit = tab->getZoomOrPannedSinceLastFit(); viewerData.wipeCompositingOp = (int)tab->getCompositingOperator(); viewerData.leftToolbarVisible = tab->isLeftToolbarVisible(); viewerData.rightToolbarVisible = tab->isRightToolbarVisible(); viewerData.topToolbarVisible = tab->isTopToolbarVisible(); viewerData.infobarVisible = tab->isInfobarVisible(); viewerData.playerVisible = tab->isPlayerVisible(); viewerData.timelineVisible = tab->isTimelineVisible(); viewerData.checkerboardEnabled = tab->isCheckerboardEnabled(); viewerData.fps = tab->getDesiredFps(); viewerData.fpsLocked = tab->isFPSLocked(); viewerData.isPauseEnabled[0] = tab->isViewerPaused(0); viewerData.isPauseEnabled[1] = tab->isViewerPaused(1); viewerData.layerName = tab->getCurrentLayerName().toStdString(); viewerData.alphaLayerName = tab->getCurrentAlphaLayerName().toStdString(); tab->getTimelineBounds(&viewerData.leftBound, &viewerData.rightBound); tab->getActiveInputs(&viewerData.aChoice, &viewerData.bChoice); viewerData.version = VIEWER_DATA_SERIALIZATION_VERSION; _viewersData.insert( std::make_pair(viewer->getNode()->getScriptName_mt_safe(), viewerData) ); } } } ///Init windows _layoutSerialization.initialize( projectGui->getGui() ); ///save histograms std::list<Histogram*> histograms = projectGui->getGui()->getHistograms_mt_safe(); for (std::list<Histogram*>::const_iterator it = histograms.begin(); it != histograms.end(); ++it) { _histograms.push_back( (*it)->objectName().toStdString() ); } ///save opened panels by order std::list<DockablePanel*> panels = projectGui->getGui()->getVisiblePanels_mt_safe(); for (std::list<DockablePanel*>::iterator it = panels.begin(); it != panels.end(); ++it) { if ( (*it)->isVisible() ) { KnobHolder* holder = (*it)->getHolder(); assert(holder); EffectInstance* isEffect = dynamic_cast<EffectInstance*>(holder); Project* isProject = dynamic_cast<Project*>(holder); if (isProject) { _openedPanelsOrdered.push_back(kNatronProjectSettingsPanelSerializationName); } else if (isEffect) { _openedPanelsOrdered.push_back( isEffect->getNode()->getFullyQualifiedName() ); } } } _scriptEditorInput = projectGui->getGui()->getScriptEditor()->getAutoSavedScript().toStdString(); std::map<NATRON_PYTHON_NAMESPACE::PyPanel*, std::string> pythonPanels = projectGui->getGui()->getPythonPanels(); for (std::map<NATRON_PYTHON_NAMESPACE::PyPanel*, std::string>::iterator it = pythonPanels.begin(); it != pythonPanels.end(); ++it) { boost::shared_ptr<PythonPanelSerialization> s(new PythonPanelSerialization); s->initialize(it->first, it->second); _pythonPanels.push_back(s); } } // initialize
bool CCPathFinderNetwork::followPath(CCCollideable *objectToPath, Path &path, const int currentDirection, const float currentDistance, NodesList<const PathNode, 50> &previousNodes, const PathNode *fromNode, const PathNode *toNode) { // Node found if( fromNode == toNode ) { path.endDirection = currentDirection; path.distance = currentDistance; return true; } const int nextDirection = currentDirection+1; if( nextDirection >= 50 ) { // Give up return false; } pathFromNode = fromNode; const CCList<PathNode::PathConnection> &connections = fromNode->connections; int *values = new int[connections.length]; for( int i=0; i<connections.length; ++i ) { values[i] = i; } qsort( values, connections.length, sizeof( int ), compare ); for( int i=0; i<connections.length; ++i ) { const PathNode::PathConnection *nextConnection = connections.list[values[i]]; const PathNode *targetNode = nextConnection->node; // Previously followed? if( previousNodes.find( targetNode ) != -1 ) { continue; } CCCollideable *collidedWith = CCOctreeMovementCollisionCheck( objectToPath, fromNode->point, targetNode->point ); if( collidedWith != NULL ) { continue; } const float pathDistance = currentDistance + nextConnection->distance; if( previousNodes.add( targetNode ) == false ) { delete[] values; return false; } if( followPath( objectToPath, path, nextDirection, pathDistance, previousNodes, targetNode, toNode ) ) { path.directions[currentDirection] = values[i]; delete[] values; return true; } } delete[] values; return false; }
NodeSerialization::NodeSerialization(const NodePtr & n, bool serializeInputs) : _isNull(true) , _nbKnobs(0) , _knobsValues() , _knobsAge(0) , _nodeLabel() , _nodeScriptName() , _pluginID() , _pluginMajorVersion(-1) , _pluginMinorVersion(-1) , _hasRotoContext(false) , _hasTrackerContext(false) , _node() , _pythonModuleVersion(0) { if (n) { _node = n; ///All this code is MT-safe _knobsValues.clear(); _inputs.clear(); if ( n->isOpenFXNode() ) { OfxEffectInstance* effect = dynamic_cast<OfxEffectInstance*>( n->getEffectInstance().get() ); assert(effect); if (effect) { effect->syncPrivateData_other_thread(); } } std::vector< KnobPtr > knobs = n->getEffectInstance()->getKnobs_mt_safe(); std::list<KnobPtr > userPages; for (U32 i = 0; i < knobs.size(); ++i) { KnobGroup* isGroup = dynamic_cast<KnobGroup*>( knobs[i].get() ); KnobPage* isPage = dynamic_cast<KnobPage*>( knobs[i].get() ); if (isPage) { _pagesIndexes.push_back( knobs[i]->getName() ); if ( knobs[i]->isUserKnob() ) { userPages.push_back(knobs[i]); } } if ( !knobs[i]->isUserKnob() && knobs[i]->getIsPersistant() && !isGroup && !isPage && knobs[i]->hasModificationsForSerialization() ) { ///For choice do a deepclone because we need entries //bool doCopyKnobs = isChoice ? true : copyKnobs; boost::shared_ptr<KnobSerialization> newKnobSer( new KnobSerialization(knobs[i]) ); _knobsValues.push_back(newKnobSer); } } _nbKnobs = (int)_knobsValues.size(); for (std::list<KnobPtr >::const_iterator it = userPages.begin(); it != userPages.end(); ++it) { boost::shared_ptr<GroupKnobSerialization> s( new GroupKnobSerialization(*it) ); _userPages.push_back(s); } _knobsAge = n->getKnobsAge(); _nodeLabel = n->getLabel_mt_safe(); _nodeScriptName = n->getScriptName_mt_safe(); _cacheID = n->getCacheID(); _pluginID = n->getPluginID(); if ( !n->hasPyPlugBeenEdited() ) { _pythonModule = n->getPluginPythonModule(); _pythonModuleVersion = n->getMajorVersion(); } _pluginMajorVersion = n->getMajorVersion(); _pluginMinorVersion = n->getMinorVersion(); if (serializeInputs) { n->getInputNames(_inputs); } NodePtr masterNode = n->getMasterNode(); if (masterNode) { _masterNodeName = masterNode->getFullyQualifiedName(); } boost::shared_ptr<RotoContext> roto = n->getRotoContext(); if ( roto && !roto->isEmpty() ) { _hasRotoContext = true; roto->save(&_rotoContext); } else { _hasRotoContext = false; } boost::shared_ptr<TrackerContext> tracker = n->getTrackerContext(); if (tracker) { _hasTrackerContext = true; tracker->save(&_trackerContext); } else { _hasTrackerContext = false; } NodeGroup* isGrp = n->isEffectGroup(); if (isGrp) { NodesList nodes; isGrp->getActiveNodes(&nodes); _children.clear(); for (NodesList::iterator it = nodes.begin(); it != nodes.end(); ++it) { if ( (*it)->isPartOfProject() ) { boost::shared_ptr<NodeSerialization> state( new NodeSerialization(*it) ); _children.push_back(state); } } } _multiInstanceParentName = n->getParentMultiInstanceName(); NodesList childrenMultiInstance; _node->getChildrenMultiInstance(&childrenMultiInstance); if ( !childrenMultiInstance.empty() ) { assert(!isGrp); for (NodesList::iterator it = childrenMultiInstance.begin(); it != childrenMultiInstance.end(); ++it) { assert( (*it)->getParentMultiInstance() ); if ( (*it)->isActivated() ) { boost::shared_ptr<NodeSerialization> state( new NodeSerialization(*it) ); _children.push_back(state); } } } n->getUserCreatedComponents(&_userComponents); _isNull = false; } }
PickKnobDialog::PickKnobDialog(DockablePanel* panel, QWidget* parent) : QDialog(parent) , _imp( new PickKnobDialogPrivate(panel) ) { NodeSettingsPanel* nodePanel = dynamic_cast<NodeSettingsPanel*>(panel); assert(nodePanel); if (!nodePanel) { throw std::logic_error("PickKnobDialog::PickKnobDialog()"); } NodeGuiPtr nodeGui = nodePanel->getNodeGui(); NodePtr node = nodeGui->getNode(); NodeGroupPtr isGroup = node->isEffectNodeGroup(); NodeCollectionPtr collec = node->getGroup(); NodeGroupPtr isCollecGroup = toNodeGroup(collec); NodesList collectNodes = collec->getNodes(); for (NodesList::iterator it = collectNodes.begin(); it != collectNodes.end(); ++it) { if ((*it)->isActivated() && (*it)->getNodeGui() && ( (*it)->getKnobs().size() > 0 ) ) { _imp->allNodes.push_back(*it); } } if (isCollecGroup) { _imp->allNodes.push_back( isCollecGroup->getNode() ); } if (isGroup) { NodesList groupnodes = isGroup->getNodes(); for (NodesList::iterator it = groupnodes.begin(); it != groupnodes.end(); ++it) { if ( (*it)->getNodeGui() && (*it)->isActivated() && ( (*it)->getKnobs().size() > 0 ) ) { _imp->allNodes.push_back(*it); } } } QStringList nodeNames; for (NodesList::iterator it = _imp->allNodes.begin(); it != _imp->allNodes.end(); ++it) { QString name = QString::fromUtf8( (*it)->getLabel().c_str() ); nodeNames.push_back(name); } nodeNames.sort(); _imp->mainLayout = new QGridLayout(this); _imp->selectNodeLabel = new Label( tr("Node:") ); _imp->nodeSelectionCombo = new CompleterLineEdit(nodeNames, nodeNames, false, this); _imp->nodeSelectionCombo->setToolTip( NATRON_NAMESPACE::convertFromPlainText(tr("Input the name of a node in the current project."), NATRON_NAMESPACE::WhiteSpaceNormal) ); _imp->nodeSelectionCombo->setFocus(Qt::PopupFocusReason); _imp->knobSelectionCombo = new ComboBox(this); QObject::connect( _imp->knobSelectionCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onKnobComboIndexChanged(int)) ); QString useAliasTt = NATRON_NAMESPACE::convertFromPlainText(tr("If checked, an alias of the selected parameter will be created, coyping entirely its state. " "Only the script-name, label and tooltip will be editable.\n" "For choice parameters this will also " "dynamically refresh the menu entries when the original parameter's menu is changed.\n" "When unchecked, a simple expression will be set linking the two parameters, but things such as dynamic menus " "will be disabled."), NATRON_NAMESPACE::WhiteSpaceNormal); _imp->useAliasLabel = new Label(tr("Make Alias:"), this); _imp->useAliasLabel->setToolTip(useAliasTt); _imp->useAliasCheckBox = new QCheckBox(this); _imp->useAliasCheckBox->setToolTip(useAliasTt); _imp->useAliasCheckBox->setChecked(true); QObject::connect( _imp->nodeSelectionCombo, SIGNAL(itemCompletionChosen()), this, SLOT(onNodeComboEditingFinished()) ); _imp->destPageLabel = new Label(tr("Page:"), this); QString pagett = NATRON_NAMESPACE::convertFromPlainText(tr("Select the page into which the parameter will be created."), NATRON_NAMESPACE::WhiteSpaceNormal); _imp->destPageLabel->setToolTip(pagett); _imp->destPageCombo = new ComboBox(this); _imp->destPageCombo->setToolTip(pagett); QObject::connect( _imp->destPageCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onPageComboIndexChanged(int)) ); const KnobsVec& knobs = node->getKnobs(); for (std::size_t i = 0; i < knobs.size(); ++i) { if ( knobs[i]->isUserKnob() ) { KnobPagePtr isPage = toKnobPage(knobs[i]); if (isPage) { _imp->pages.push_back(isPage); _imp->destPageCombo->addItem( QString::fromUtf8( isPage->getName().c_str() ) ); } else { KnobGroupPtr isGrp = toKnobGroup(knobs[i]); if (isGrp) { _imp->groups.push_back(isGrp); } } } } if (_imp->destPageCombo->count() == 0) { _imp->destPageLabel->hide(); _imp->destPageCombo->hide(); } _imp->groupLabel = new Label(tr("Group:"), this); QString grouptt = NATRON_NAMESPACE::convertFromPlainText(tr("Select the group into which the parameter will be created."), NATRON_NAMESPACE::WhiteSpaceNormal); _imp->groupCombo = new ComboBox(this); _imp->groupLabel->setToolTip(grouptt); _imp->groupCombo->setToolTip(grouptt); onPageComboIndexChanged(0); _imp->buttons = new DialogButtonBox(QDialogButtonBox::StandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel), Qt::Horizontal, this); QObject::connect( _imp->buttons, SIGNAL(accepted()), this, SLOT(accept()) ); QObject::connect( _imp->buttons, SIGNAL(rejected()), this, SLOT(reject()) ); _imp->mainLayout->addWidget(_imp->selectNodeLabel, 0, 0, 1, 1); _imp->mainLayout->addWidget(_imp->nodeSelectionCombo, 0, 1, 1, 1); _imp->mainLayout->addWidget(_imp->knobSelectionCombo, 0, 2, 1, 1); _imp->mainLayout->addWidget(_imp->useAliasLabel, 1, 0, 1, 1); _imp->mainLayout->addWidget(_imp->useAliasCheckBox, 1, 1, 1, 1); _imp->mainLayout->addWidget(_imp->destPageLabel, 2, 0, 1, 1); _imp->mainLayout->addWidget(_imp->destPageCombo, 2, 1, 1, 1); _imp->mainLayout->addWidget(_imp->groupLabel, 2, 2, 1, 1); _imp->mainLayout->addWidget(_imp->groupCombo, 2, 3, 1, 1); _imp->mainLayout->addWidget(_imp->buttons, 3, 0, 1, 3); QTimer::singleShot( 25, _imp->nodeSelectionCombo, SLOT(showCompleter()) ); }
void NodeAnimPrivate::computeGroupRange() { NodeGuiPtr nodeUI = nodeGui.lock(); NodePtr node = nodeUI->getNode(); if (!node) { return; } AnimationModulePtr isAnimModel = toAnimationModule(model.lock()); if (!isAnimModel) { return; } NodeGroupPtr nodegroup = node->isEffectNodeGroup(); assert(nodegroup); if (!nodegroup) { return; } AnimationModuleTreeView* treeView = isAnimModel->getEditor()->getTreeView(); NodesList nodes = nodegroup->getNodes(); std::set<double> times; for (NodesList::const_iterator it = nodes.begin(); it != nodes.end(); ++it) { NodeAnimPtr childAnim = isAnimModel->findNodeAnim(*it); if (!childAnim) { continue; } if (!treeView->isItemVisibleRecursive(childAnim->getTreeItem())) { continue; } childAnim->refreshFrameRange(); RangeD childRange = childAnim->getFrameRange(); times.insert(childRange.min); times.insert(childRange.max); // Also check the child knobs keyframes NodeGuiPtr childGui = childAnim->getNodeGui(); const KnobsVec &knobs = childGui->getNode()->getKnobs(); for (KnobsVec::const_iterator it2 = knobs.begin(); it2 != knobs.end(); ++it2) { if ( !(*it2)->isAnimationEnabled() || !(*it2)->hasAnimation() ) { continue; } else { // For each dimension and for each split view get the first/last keyframe (if any) int nDims = (*it2)->getNDimensions(); std::list<ViewIdx> views = (*it2)->getViewsList(); for (std::list<ViewIdx>::const_iterator it3 = views.begin(); it3 != views.end(); ++it3) { for (int i = 0; i < nDims; ++i) { CurvePtr curve = (*it2)->getCurve(*it3, DimIdx(i)); if (!curve) { continue; } int nKeys = curve->getKeyFramesCount(); if (nKeys > 0) { KeyFrame k; if (curve->getKeyFrameWithIndex(0, &k)) { times.insert( k.getTime() ); } if (curve->getKeyFrameWithIndex(nKeys - 1, &k)) { times.insert( k.getTime() ); } } } } } } // for all knobs } // for all children nodes if (times.size() <= 1) { frameRange.min = 0; frameRange.max = 0; } else { frameRange.min = *times.begin(); frameRange.max = *times.rbegin(); } } // computeGroupRange
void Gui::removeViewerTab(ViewerTab* tab, bool initiatedFromNode, bool deleteData) { assert(tab); unregisterTab(tab); if (tab == _imp->_activeViewer) { _imp->_activeViewer = 0; } NodeGraph* graph = 0; NodeGroupPtr isGrp; NodeCollectionPtr collection; if ( tab->getInternalNode() && tab->getInternalNode()->getNode() ) { NodeCollectionPtr collection = tab->getInternalNode()->getNode()->getGroup(); isGrp = toNodeGroup(collection); } if (isGrp) { NodeGraphI* graph_i = isGrp->getNodeGraph(); assert(graph_i); graph = dynamic_cast<NodeGraph*>(graph_i); } else { graph = getNodeGraph(); } assert(graph); if (!graph) { throw std::logic_error(""); } ViewerTab* lastSelectedViewer = graph->getLastSelectedViewer(); if (lastSelectedViewer == tab) { bool foundOne = false; NodesList nodes; if (collection) { nodes = collection->getNodes(); } for (NodesList::iterator it = nodes.begin(); it != nodes.end(); ++it) { ViewerNodePtr isViewer = (*it)->isEffectViewerNode(); if ( !isViewer || ( isViewer == tab->getInternalNode() ) || !(*it)->isActivated() ) { continue; } OpenGLViewerI* viewerI = isViewer->getUiContext(); assert(viewerI); ViewerGL* glViewer = dynamic_cast<ViewerGL*>(viewerI); assert(glViewer); if (glViewer) { graph->setLastSelectedViewer( glViewer->getViewerTab() ); } foundOne = true; break; } if (!foundOne) { graph->setLastSelectedViewer(0); } } ViewerNodePtr viewerNode = tab->getInternalNode(); ViewerInstancePtr internalViewer; if (viewerNode) { internalViewer = viewerNode->getInternalViewerNode(); } if (internalViewer) { internalViewer->abortAnyEvaluation(); if (getApp()->getLastViewerUsingTimeline() == internalViewer) { getApp()->discardLastViewerUsingTimeline(); } } if (!initiatedFromNode) { assert(_imp->_nodeGraphArea); ///call the deleteNode which will call this function again when the node will be deactivated. NodePtr internalNode = tab->getInternalNode()->getNode(); NodeGuiIPtr guiI = internalNode->getNodeGui(); NodeGuiPtr gui = boost::dynamic_pointer_cast<NodeGui>(guiI); assert(gui); NodeGraphI* graph_i = internalNode->getGroup()->getNodeGraph(); assert(graph_i); NodeGraph* graph = dynamic_cast<NodeGraph*>(graph_i); assert(graph); if (graph) { graph->removeNode(gui); } } else { tab->hide(); TabWidget* container = dynamic_cast<TabWidget*>( tab->parentWidget() ); if (container) { container->removeTab(tab, false); } if (deleteData) { QMutexLocker l(&_imp->_viewerTabsMutex); std::list<ViewerTab*>::iterator it = std::find(_imp->_viewerTabs.begin(), _imp->_viewerTabs.end(), tab); if ( it != _imp->_viewerTabs.end() ) { _imp->_viewerTabs.erase(it); } tab->notifyGuiClosingPublic(); tab->deleteLater(); } } Q_EMIT viewersChanged(); } // Gui::removeViewerTab