void NodeGraph::setNodeToDefaultPosition(const NodeGuiPtr& node, const NodesGuiList& selectedNodes, const CreateNodeArgs& args) { NodePtr internalNode = node->getNode(); // Serializatino, don't do anything SERIALIZATION_NAMESPACE::NodeSerializationPtr serialization = args.getPropertyUnsafe<SERIALIZATION_NAMESPACE::NodeSerializationPtr >(kCreateNodeArgsPropNodeSerialization); if (serialization) { return; } bool hasPositionnedNode = false; // Try to autoconnect if there is a selection bool autoConnect = args.getPropertyUnsafe<bool>(kCreateNodeArgsPropAutoConnect); if ( selectedNodes.empty() || serialization) { autoConnect = false; } if (autoConnect) { BackdropGuiPtr isBd = toBackdropGui(node); if (!isBd) { NodeGuiPtr selectedNode; if ( !serialization && (selectedNodes.size() == 1) ) { selectedNode = selectedNodes.front(); BackdropGuiPtr isBdGui = toBackdropGui(selectedNode); if (isBdGui) { selectedNode.reset(); } } if (selectedNode && node->getNode()->autoConnect(selectedNode->getNode())) { hasPositionnedNode = true; } } } if (!hasPositionnedNode) { // If there's a position hint, use it to position the node double xPosHint = args.getPropertyUnsafe<double>(kCreateNodeArgsPropNodeInitialPosition, 0); double yPosHint = args.getPropertyUnsafe<double>(kCreateNodeArgsPropNodeInitialPosition, 1); if ((xPosHint != INT_MIN) && (yPosHint != INT_MIN)) { QPointF pos = node->mapToParent( node->mapFromScene( QPointF(xPosHint, yPosHint) ) ); node->refreshPosition( pos.x(), pos.y(), true ); hasPositionnedNode = true; } } // Ok fallback with the node in the middle of the node graph if (!hasPositionnedNode) { moveNodeToCenterOfVisiblePortion(node); } }
void GuiAppInstance::onGroupCreationFinished(const NodePtr& node, CreateNodeReason reason) { if (reason == eCreateNodeReasonUserCreate) { NodeGraph* graph = 0; boost::shared_ptr<NodeCollection> collection = node->getGroup(); assert(collection); NodeGroup* isGrp = dynamic_cast<NodeGroup*>( collection.get() ); if (isGrp) { NodeGraphI* graph_i = isGrp->getNodeGraph(); assert(graph_i); graph = dynamic_cast<NodeGraph*>(graph_i); } else { graph = _imp->_gui->getNodeGraph(); } assert(graph); if (!graph) { throw std::logic_error(""); } NodesGuiList selectedNodes = graph->getSelectedNodes(); NodeGuiPtr selectedNode; if ( !selectedNodes.empty() ) { selectedNode = selectedNodes.front(); if ( dynamic_cast<BackdropGui*>( selectedNode.get() ) ) { selectedNode.reset(); } } boost::shared_ptr<NodeGuiI> node_gui_i = node->getNodeGui(); assert(node_gui_i); NodeGuiPtr nodeGui = boost::dynamic_pointer_cast<NodeGui>(node_gui_i); graph->moveNodesForIdealPosition(nodeGui, selectedNode, true); } AppInstance::onGroupCreationFinished(node, reason); /*std::list<ViewerInstance* > viewers; node->hasViewersConnected(&viewers); for (std::list<ViewerInstance* >::iterator it2 = viewers.begin(); it2 != viewers.end(); ++it2) { (*it2)->renderCurrentFrame(false); }*/ }
void GuiAppInstance::onGroupCreationFinished(const NodePtr& node, const NodeSerializationPtr& serialization, bool autoConnect) { NodeGuiIPtr node_gui_i = node->getNodeGui(); if (autoConnect && !serialization && node_gui_i) { NodeGraph* graph = 0; NodeCollectionPtr collection = node->getGroup(); assert(collection); NodeGroupPtr isGrp = toNodeGroup(collection); if (isGrp) { NodeGraphI* graph_i = isGrp->getNodeGraph(); assert(graph_i); graph = dynamic_cast<NodeGraph*>(graph_i); } else { graph = _imp->_gui->getNodeGraph(); } assert(graph); if (!graph) { throw std::logic_error(""); } NodesGuiList selectedNodes = graph->getSelectedNodes(); NodeGuiPtr selectedNode; if ( !selectedNodes.empty() ) { selectedNode = selectedNodes.front(); if (toBackdropGui(selectedNode) ) { selectedNode.reset(); } } NodeGuiPtr nodeGui = boost::dynamic_pointer_cast<NodeGui>(node_gui_i); graph->moveNodesForIdealPosition(nodeGui, selectedNode, true); } AppInstance::onGroupCreationFinished(node, serialization, autoConnect); /*std::list<ViewerInstancePtr> viewers; node->hasViewersConnected(&viewers); for (std::list<ViewerInstancePtr>::iterator it2 = viewers.begin(); it2 != viewers.end(); ++it2) { (*it2)->renderCurrentFrame(false); }*/ }
void NodeGraph::showMenu(const QPoint & pos) { _imp->_menu->clear(); QAction* findAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphFindNode, kShortcutActionGraphFindNodeLabel, _imp->_menu); _imp->_menu->addAction(findAction); _imp->_menu->addSeparator(); //QFont font(appFont,appFontSize); Menu* editMenu = new Menu(tr("Edit"), _imp->_menu); //editMenu->setFont(font); _imp->_menu->addAction( editMenu->menuAction() ); QAction* copyAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphCopy, kShortcutActionGraphCopyLabel, editMenu); QObject::connect( copyAction, SIGNAL(triggered()), this, SLOT(copySelectedNodes()) ); editMenu->addAction(copyAction); QAction* cutAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphCut, kShortcutActionGraphCutLabel, editMenu); QObject::connect( cutAction, SIGNAL(triggered()), this, SLOT(cutSelectedNodes()) ); editMenu->addAction(cutAction); QAction* pasteAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphPaste, kShortcutActionGraphPasteLabel, editMenu); bool cbEnabled = false; { QClipboard* clipboard = QApplication::clipboard(); const QMimeData* data = clipboard->mimeData(); if (data && data->hasFormat(QLatin1String("text/plain"))) { cbEnabled = true; } } pasteAction->setEnabled(cbEnabled); editMenu->addAction(pasteAction); QAction* deleteAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphRemoveNodes, kShortcutActionGraphRemoveNodesLabel, editMenu); QObject::connect( deleteAction, SIGNAL(triggered()), this, SLOT(deleteSelection()) ); editMenu->addAction(deleteAction); QAction* renameAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphRenameNode, kShortcutActionGraphRenameNodeLabel, editMenu); QObject::connect( renameAction, SIGNAL(triggered()), this, SLOT(renameNode()) ); editMenu->addAction(renameAction); QAction* duplicateAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphDuplicate, kShortcutActionGraphDuplicateLabel, editMenu); editMenu->addAction(duplicateAction); QAction* cloneAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphClone, kShortcutActionGraphCloneLabel, editMenu); editMenu->addAction(cloneAction); QAction* decloneAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphDeclone, kShortcutActionGraphDecloneLabel, editMenu); QObject::connect( decloneAction, SIGNAL(triggered()), this, SLOT(decloneSelectedNodes()) ); editMenu->addAction(decloneAction); QAction* switchInputs = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphExtractNode, kShortcutActionGraphExtractNodeLabel, editMenu); QObject::connect( switchInputs, SIGNAL(triggered()), this, SLOT(extractSelectedNode()) ); editMenu->addAction(switchInputs); QAction* extractNode = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphSwitchInputs, kShortcutActionGraphSwitchInputsLabel, editMenu); QObject::connect( extractNode, SIGNAL(triggered()), this, SLOT(switchInputs1and2ForSelectedNodes()) ); editMenu->addAction(extractNode); QAction* disableNodes = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphDisableNodes, kShortcutActionGraphDisableNodesLabel, editMenu); QObject::connect( disableNodes, SIGNAL(triggered()), this, SLOT(toggleSelectedNodesEnabled()) ); editMenu->addAction(disableNodes); QAction* groupFromSel = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphMakeGroup, kShortcutActionGraphMakeGroupLabel, editMenu); QObject::connect( groupFromSel, SIGNAL(triggered()), this, SLOT(createGroupFromSelection()) ); editMenu->addAction(groupFromSel); QAction* expandGroup = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphExpandGroup, kShortcutActionGraphExpandGroupLabel, editMenu); QObject::connect( expandGroup, SIGNAL(triggered()), this, SLOT(expandSelectedGroups()) ); editMenu->addAction(expandGroup); QAction* displayCacheInfoAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphShowCacheSize, kShortcutActionGraphShowCacheSizeLabel, _imp->_menu); displayCacheInfoAction->setCheckable(true); displayCacheInfoAction->setChecked( _imp->_cacheSizeText->isVisible() ); QObject::connect( displayCacheInfoAction, SIGNAL(triggered()), this, SLOT(toggleCacheInfo()) ); _imp->_menu->addAction(displayCacheInfoAction); NodesGuiList selectedNodes = getSelectedNodes(); if ( !selectedNodes.empty() ) { QAction* turnOffPreviewAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphTogglePreview, kShortcutActionGraphTogglePreviewLabel, _imp->_menu); turnOffPreviewAction->setCheckable(true); turnOffPreviewAction->setChecked(false); QObject::connect( turnOffPreviewAction, SIGNAL(triggered()), this, SLOT(togglePreviewsForSelectedNodes()) ); _imp->_menu->addAction(turnOffPreviewAction); if (selectedNodes.size() == 1) { QAction* openNodePanelAction = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphOpenNodePanel, kShortcutActionGraphOpenNodePanelLabel, _imp->_menu); openNodePanelAction->setCheckable(true); openNodePanelAction->setChecked(false); QObject::connect( openNodePanelAction, SIGNAL(triggered()), this, SLOT(showSelectedNodeSettingsPanel()) ); _imp->_menu->addAction(openNodePanelAction); } } QAction* autoHideInputs = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphAutoHideInputs, kShortcutActionGraphAutoHideInputsLabel, _imp->_menu); autoHideInputs->setCheckable(true); autoHideInputs->setChecked( appPTR->getCurrentSettings()->areOptionalInputsAutoHidden() ); QObject::connect( autoHideInputs, SIGNAL(triggered()), this, SLOT(toggleAutoHideInputs()) ); _imp->_menu->addAction(autoHideInputs); QAction* hideInputs = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphHideInputs, kShortcutActionGraphHideInputsLabel, _imp->_menu); hideInputs->setCheckable(true); bool hideInputsVal = false; if ( !selectedNodes.empty() ) { hideInputsVal = selectedNodes.front()->getNode()->getEffectInstance()->getHideInputsKnobValue(); } hideInputs->setChecked(hideInputsVal); QObject::connect( hideInputs, SIGNAL(triggered()), this, SLOT(toggleHideInputs()) ); _imp->_menu->addAction(hideInputs); QAction* knobLinks = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphShowExpressions, kShortcutActionGraphShowExpressionsLabel, _imp->_menu); knobLinks->setCheckable(true); knobLinks->setChecked( areKnobLinksVisible() ); QObject::connect( knobLinks, SIGNAL(triggered()), this, SLOT(toggleKnobLinksVisible()) ); _imp->_menu->addAction(knobLinks); QAction* autoPreview = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphToggleAutoPreview, kShortcutActionGraphToggleAutoPreviewLabel, _imp->_menu); autoPreview->setCheckable(true); autoPreview->setChecked( getGui()->getApp()->getProject()->isAutoPreviewEnabled() ); QObject::connect( autoPreview, SIGNAL(triggered()), this, SLOT(toggleAutoPreview()) ); QObject::connect( getGui()->getApp()->getProject().get(), SIGNAL(autoPreviewChanged(bool)), autoPreview, SLOT(setChecked(bool)) ); _imp->_menu->addAction(autoPreview); QAction* autoTurbo = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphToggleAutoTurbo, kShortcutActionGraphToggleAutoTurboLabel, _imp->_menu); autoTurbo->setCheckable(true); autoTurbo->setChecked( appPTR->getCurrentSettings()->isAutoTurboEnabled() ); QObject::connect( autoTurbo, SIGNAL(triggered()), this, SLOT(toggleAutoTurbo()) ); _imp->_menu->addAction(autoTurbo); QAction* forceRefreshPreviews = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphForcePreview, kShortcutActionGraphForcePreviewLabel, _imp->_menu); QObject::connect( forceRefreshPreviews, SIGNAL(triggered()), this, SLOT(forceRefreshAllPreviews()) ); _imp->_menu->addAction(forceRefreshPreviews); QAction* frameAllNodes = new ActionWithShortcut(kShortcutGroupNodegraph, kShortcutActionGraphFrameNodes, kShortcutActionGraphFrameNodesLabel, _imp->_menu); QObject::connect( frameAllNodes, SIGNAL(triggered()), this, SLOT(centerOnAllNodes()) ); _imp->_menu->addAction(frameAllNodes); _imp->_menu->addSeparator(); std::list<ToolButton*> orederedToolButtons = getGui()->getToolButtonsOrdered(); for (std::list<ToolButton*>::iterator it = orederedToolButtons.begin(); it != orederedToolButtons.end(); ++it) { (*it)->getMenu()->setIcon( (*it)->getMenuIcon() ); _imp->_menu->addAction( (*it)->getMenu()->menuAction() ); } QAction* ret = _imp->_menu->exec(pos); if (ret == findAction) { popFindDialog(); } else if (ret == duplicateAction) { QRectF rect = visibleSceneRect(); duplicateSelectedNodes( rect.center() ); } else if (ret == cloneAction) { QRectF rect = visibleSceneRect(); cloneSelectedNodes( rect.center() ); } else if (ret == pasteAction) { QRectF rect = visibleSceneRect(); pasteClipboard( rect.center() ); } } // NodeGraph::showMenu
void Gui::renderSelectedNode() { NodeGraph* graph = getLastSelectedGraph(); if (!graph) { return; } NodesGuiList selectedNodes = graph->getSelectedNodes(); if ( selectedNodes.empty() ) { Dialogs::warningDialog( tr("Render").toStdString(), tr("You must select a node to render first!").toStdString() ); return; } std::list<AppInstance::RenderWork> workList; bool useStats = getApp()->isRenderStatsActionChecked(); for (NodesGuiList::const_iterator it = selectedNodes.begin(); it != selectedNodes.end(); ++it) { NodePtr internalNode = (*it)->getNode(); if (!internalNode) { continue; } EffectInstPtr effect = internalNode->getEffectInstance(); if (!effect) { continue; } if ( effect->isWriter() ) { if ( !effect->areKnobsFrozen() ) { //if ((*it)->getNode()->is) ///if the node is a writer, just use it to render! AppInstance::RenderWork w; w.writer = dynamic_cast<OutputEffectInstance*>( effect.get() ); assert(w.writer); w.firstFrame = INT_MIN; w.lastFrame = INT_MAX; w.frameStep = INT_MIN; w.useRenderStats = useStats; workList.push_back(w); } } else { if (selectedNodes.size() == 1) { ///create a node and connect it to the node and use it to render #ifndef NATRON_ENABLE_IO_META_NODES NodePtr writer = createWriter(); #else NodeGraph* graph = selectedNodes.front()->getDagGui(); NodePtr writer = getApp()->createWriter( "", eCreateNodeReasonInternal, graph->getGroup() ); #endif if (writer) { AppInstance::RenderWork w; w.writer = dynamic_cast<OutputEffectInstance*>( writer->getEffectInstance().get() ); assert(w.writer); w.firstFrame = INT_MIN; w.lastFrame = INT_MAX; w.frameStep = INT_MIN; w.useRenderStats = useStats; workList.push_back(w); } } } } _imp->_appInstance->startWritersRendering(false, workList); } // Gui::renderSelectedNode
void GuiAppInstance::createNodeGui(const NodePtr &node, const NodePtr& parentMultiInstance, const CreateNodeArgs& args) { boost::shared_ptr<NodeCollection> group = node->getGroup(); NodeGraph* graph; if (group) { NodeGraphI* graph_i = group->getNodeGraph(); assert(graph_i); graph = dynamic_cast<NodeGraph*>(graph_i); assert(graph); } else { graph = _imp->_gui->getNodeGraph(); } if (!graph) { throw std::logic_error(""); } NodesGuiList selectedNodes = graph->getSelectedNodes(); NodeGuiPtr nodegui = _imp->_gui->createNodeGUI(node, args); assert(nodegui); if (parentMultiInstance && nodegui) { nodegui->hideGui(); boost::shared_ptr<NodeGuiI> parentNodeGui_i = parentMultiInstance->getNodeGui(); assert(parentNodeGui_i); nodegui->setParentMultiInstance( boost::dynamic_pointer_cast<NodeGui>(parentNodeGui_i) ); } ///It needs to be here because we rely on the _nodeMapping member bool isViewer = node->isEffectViewer() != 0; if (isViewer) { _imp->_gui->createViewerGui(node); } ///must be done after the viewer gui has been created if ( node->isRotoPaintingNode() ) { _imp->_gui->createNewRotoInterface( nodegui.get() ); } if ( ( node->isTrackerNodePlugin() || node->getEffectInstance()->isBuiltinTrackerNode() ) && !parentMultiInstance ) { _imp->_gui->createNewTrackerInterface( nodegui.get() ); } NodeGroup* isGroup = node->isEffectGroup(); if ( isGroup && isGroup->isSubGraphUserVisible() ) { _imp->_gui->createGroupGui(node, args.reason); } ///Don't initialize inputs if it is a multi-instance child since it is not part of the graph if (!parentMultiInstance) { nodegui->initializeInputs(); } if ( (args.reason == eCreateNodeReasonUserCreate) && !isViewer ) { ///we make sure we can have a clean preview. node->computePreviewImage( getTimeLine()->currentFrame() ); triggerAutoSave(); } ///only move main instances if ( node->getParentMultiInstanceName().empty() ) { bool autoConnect = args.reason == eCreateNodeReasonUserCreate; if ( selectedNodes.empty() ) { autoConnect = false; } if ( (args.xPosHint != INT_MIN) && (args.yPosHint != INT_MIN) && (!autoConnect) ) { QPointF pos = nodegui->mapToParent( nodegui->mapFromScene( QPointF(args.xPosHint, args.yPosHint) ) ); nodegui->refreshPosition( pos.x(), pos.y(), true ); } else { BackdropGui* isBd = dynamic_cast<BackdropGui*>( nodegui.get() ); if (!isBd) { NodeGuiPtr selectedNode; if ( (args.reason == eCreateNodeReasonUserCreate) && (selectedNodes.size() == 1) ) { selectedNode = selectedNodes.front(); BackdropGui* isBackdropGui = dynamic_cast<BackdropGui*>( selectedNode.get() ); if (isBackdropGui) { selectedNode.reset(); } } nodegui->getDagGui()->moveNodesForIdealPosition(nodegui, selectedNode, autoConnect); } } } } // createNodeGui
void GuiAppInstance::createNodeGui(const NodePtr &node, const NodePtr& parentMultiInstance, const CreateNodeArgs& args) { NodeCollectionPtr group = node->getGroup(); NodeGraph* graph; if (group) { NodeGraphI* graph_i = group->getNodeGraph(); assert(graph_i); graph = dynamic_cast<NodeGraph*>(graph_i); assert(graph); } else { graph = _imp->_gui->getNodeGraph(); } if (!graph) { throw std::logic_error(""); } NodesGuiList selectedNodes = graph->getSelectedNodes(); NodeGuiPtr nodegui = _imp->_gui->createNodeGUI(node, args); assert(nodegui); if (parentMultiInstance && nodegui) { nodegui->hideGui(); NodeGuiIPtr parentNodeGui_i = parentMultiInstance->getNodeGui(); assert(parentNodeGui_i); nodegui->setParentMultiInstance( boost::dynamic_pointer_cast<NodeGui>(parentNodeGui_i) ); } bool isViewer = node->isEffectViewerInstance() != 0; if (isViewer) { _imp->_gui->createViewerGui(node); } // Must be done after the viewer gui has been created _imp->_gui->createNodeViewerInterface(nodegui); NodeGroupPtr isGroup = node->isEffectNodeGroup(); if ( isGroup && isGroup->isSubGraphUserVisible() ) { _imp->_gui->createGroupGui(node, args); } ///Don't initialize inputs if it is a multi-instance child since it is not part of the graph if (!parentMultiInstance) { nodegui->initializeInputs(); } NodeSerializationPtr serialization = args.getProperty<NodeSerializationPtr >(kCreateNodeArgsPropNodeSerialization); if ( !serialization && !isViewer ) { ///we make sure we can have a clean preview. node->computePreviewImage( getTimeLine()->currentFrame() ); triggerAutoSave(); } ///only move main instances if ( node->getParentMultiInstanceName().empty() && !serialization) { bool autoConnect = args.getProperty<bool>(kCreateNodeArgsPropAutoConnect); if ( selectedNodes.empty() || serialization) { autoConnect = false; } double xPosHint = serialization ? INT_MIN : args.getProperty<double>(kCreateNodeArgsPropNodeInitialPosition, 0); double yPosHint = serialization ? INT_MIN : args.getProperty<double>(kCreateNodeArgsPropNodeInitialPosition, 1); if ( (xPosHint != INT_MIN) && (yPosHint != INT_MIN) && (!autoConnect) ) { QPointF pos = nodegui->mapToParent( nodegui->mapFromScene( QPointF(xPosHint, yPosHint) ) ); nodegui->refreshPosition( pos.x(), pos.y(), true ); } else { BackdropGuiPtr isBd = toBackdropGui(nodegui); if (!isBd) { NodeGuiPtr selectedNode; if ( !serialization && (selectedNodes.size() == 1) ) { selectedNode = selectedNodes.front(); BackdropGuiPtr isBdGui = toBackdropGui(selectedNode); if (isBdGui) { selectedNode.reset(); } } nodegui->getDagGui()->moveNodesForIdealPosition(nodegui, selectedNode, autoConnect); } } } } // createNodeGui