ViewerTab::~ViewerTab() { Gui* gui = getGui(); if (gui) { NodeGraph* graph = 0; ViewerNodePtr internalNode = getInternalNode(); ViewerInstancePtr viewerNode = internalNode ? internalNode->getInternalViewerNode() : ViewerInstancePtr(); if (viewerNode) { NodeCollectionPtr collection = viewerNode->getNode()->getGroup(); if (collection) { NodeGroupPtr isGrp = toNodeGroup(collection); if (isGrp) { NodeGraphI* graph_i = isGrp->getNodeGraph(); if (graph_i) { graph = dynamic_cast<NodeGraph*>(graph_i); assert(graph); } } else { graph = gui->getNodeGraph(); } } internalNode->invalidateUiContext(); } else { graph = gui->getNodeGraph(); } assert(graph); GuiAppInstancePtr app = gui->getApp(); if ( app && !app->isClosing() && graph && (graph->getLastSelectedViewer() == this) ) { graph->setLastSelectedViewer(0); } } _imp->nodesContext.clear(); }
void ViewerTab::onTimeLineTimeChanged(SequenceTime time, int reason) { Gui* gui = getGui(); if (!gui) { return; } ViewerNodePtr node = _imp->viewerNode.lock(); ViewerInstancePtr viewerNode = node->getInternalViewerNode(); if ((TimelineChangeReasonEnum)reason != eTimelineChangeReasonPlaybackSeek) { node->getCurrentFrameKnob()->setValue(time, ViewSetSpec::current(), DimIdx(0), eValueChangedReasonPluginEdited); } GuiAppInstancePtr app = gui->getApp(); if ( app && _imp->timeLineGui->getTimeline() != app->getTimeLine() ) { viewerNode->renderCurrentFrame(true); } }
void ViewerTab::abortViewersAndRefresh() { Gui* gui = getGui(); if (!gui) { return; } const std::list<ViewerTab*> & activeNodes = gui->getViewersList(); for (std::list<ViewerTab*>::const_iterator it = activeNodes.begin(); it != activeNodes.end(); ++it) { ViewerNodePtr viewer = (*it)->getInternalNode(); if (viewer) { ViewerInstancePtr instance = viewer->getInternalViewerNode(); if (instance) { RenderEnginePtr engine = instance->getRenderEngine(); if ( engine ) { engine->abortRenderingAutoRestart(); engine->renderCurrentFrame(false, true); } } } } }
void ViewerNodePrivate::setAlphaChannelFromLayerIfRGBA() { ImagePlaneDesc selectedLayer, selectedAlphaLayer, selectedDisplayLayer; int alphaChannelIndex; ViewerInstancePtr internalViewer = internalViewerProcessNode[0].lock()->isEffectViewerInstance(); internalViewer->getChannelOptions(_publicInterface->getTimelineCurrentTime(), &selectedLayer, &selectedAlphaLayer, &alphaChannelIndex, &selectedDisplayLayer); // Set the alpha channel to the selected layer's alpha channel if it is not pointing to anything if (selectedLayer.getNumComponents() == 4 && selectedAlphaLayer.getNumComponents() == 0) { ChoiceOption newOption = selectedLayer.getChannelOption(3); KnobChoicePtr alphaChoice = alphaChannelKnob.lock(); std::vector<ChoiceOption> options = alphaChoice->getEntries(); for (std::size_t i = 0; i < options.size(); ++i) { if (options[i].id == newOption.id) { alphaChoice->setValue(i); break; } } } }
void ViewerNode::createViewerProcessNode() { NodePtr internalViewerNode[2]; for (int i = 0; i < 2; ++ i) { ViewerNodePtr thisShared = shared_from_this(); QString nodeName = QString::fromUtf8("ViewerProcess"); nodeName += QString::number(i + 1); CreateNodeArgsPtr args(CreateNodeArgs::create(PLUGINID_NATRON_VIEWER_INTERNAL, thisShared)); args->setProperty<bool>(kCreateNodeArgsPropAutoConnect, false); args->setProperty<bool>(kCreateNodeArgsPropAddUndoRedoCommand, false); args->setProperty<bool>(kCreateNodeArgsPropAllowNonUserCreatablePlugins, true); args->setProperty<bool>(kCreateNodeArgsPropSettingsOpened, false); args->setProperty<std::string>(kCreateNodeArgsPropNodeInitialName, nodeName.toStdString()); internalViewerNode[i] = getApp()->createNode(args); assert(internalViewerNode[i]); if (!internalViewerNode[i]) { throw std::invalid_argument("ViewerNode::setupGraph: No internal viewer process!"); } if (i == 1) { Point position; internalViewerNode[0]->getPosition(&position.x, &position.y); double w,h; internalViewerNode[0]->getSize(&w, &h); internalViewerNode[0]->setPosition(position.x - w /2. - w/2, position.y); internalViewerNode[1]->setPosition(position.x + w /2., position.y); } _imp->internalViewerProcessNode[i] = internalViewerNode[i]; // Link output layer and alpha channel to the viewer process choices KnobIPtr viewerProcessOutputLayerChoice = internalViewerNode[i]->getKnobByName(kViewerInstanceParamOutputLayer); viewerProcessOutputLayerChoice->linkTo(_imp->layersKnob.lock()); KnobIPtr viewerProcessAlphaChannelChoice = internalViewerNode[i]->getKnobByName(kViewerInstanceParamAlphaChannel); viewerProcessAlphaChannelChoice->linkTo(_imp->alphaChannelKnob.lock()); KnobIPtr viewerProcessDisplayChanelsChoice = internalViewerNode[i]->getKnobByName(kViewerInstanceParamDisplayChannels); viewerProcessDisplayChanelsChoice->linkTo(_imp->displayChannelsKnob[i].lock()); KnobIPtr viewerProcessGammaKnob = internalViewerNode[i]->getKnobByName(kViewerInstanceParamGamma); viewerProcessGammaKnob->linkTo(_imp->gammaSliderKnob.lock()); KnobIPtr viewerProcessGainKnob = internalViewerNode[i]->getKnobByName(kViewerInstanceNodeParamGain); viewerProcessGainKnob->linkTo(_imp->gainSliderKnob.lock()); KnobIPtr viewerProcessAutoContrastKnob = internalViewerNode[i]->getKnobByName(kViewerInstanceParamEnableAutoContrast); viewerProcessAutoContrastKnob->linkTo(_imp->enableAutoContrastButtonKnob.lock()); KnobIPtr viewerProcessAutoColorspaceKnob = internalViewerNode[i]->getKnobByName(kViewerInstanceParamColorspace); viewerProcessAutoColorspaceKnob->linkTo(_imp->colorspaceKnob.lock()); KnobIPtr userRoiEnabledKnob = internalViewerNode[i]->getKnobByName(kViewerInstanceParamEnableUserRoI); userRoiEnabledKnob->linkTo(_imp->toggleUserRoIButtonKnob.lock()); KnobIPtr userRoiBtmLeftKnob = internalViewerNode[i]->getKnobByName(kViewerInstanceParamUserRoIBottomLeft); userRoiBtmLeftKnob->linkTo(_imp->userRoIBtmLeftKnob.lock()); KnobIPtr userRoiSizeKnob = internalViewerNode[i]->getKnobByName(kViewerInstanceParamUserRoISize); userRoiSizeKnob->linkTo(_imp->userRoISizeKnob.lock()); KnobIPtr clipToFormatKnob = internalViewerNode[i]->getKnobByName(kViewerInstanceParamClipToFormat); clipToFormatKnob->linkTo(_imp->clipToFormatButtonKnob.lock()); // A ViewerNode is composed of 2 ViewerProcess nodes but it only has 1 layer and 1 alpha channel choices. // We thus disable the refreshing of the menu from the 2nd ViewerProcess node. if (i == 1) { ViewerInstancePtr instance = internalViewerNode[i]->isEffectViewerInstance(); instance->setRefreshLayerAndAlphaChoiceEnabled(false); } } Q_EMIT internalViewerCreated(); } // createViewerProcessNode
static ActionRetCodeEnum createFrameRenderResultsForView(const ViewerNodePtr& viewer, const TreeRenderQueueProviderPtr& provider, const ViewerRenderFrameResultsContainerPtr& results, ViewIdx view, const RenderStatsPtr& stats, bool isPlayback, const RectD* partialUpdateRoIParam, unsigned int mipMapLevel, ViewerCompositingOperatorEnum viewerBlend, bool byPassCache, bool draftModeEnabled, bool fullFrameProcessing, bool viewerBEqualsViewerA, const RotoStrokeItemPtr& activeDrawingStroke) { // Initialize for each view a sub-result. // Each view has 2 renders: the A and B viewerprocess ViewerRenderFrameSubResultPtr subResult(new ViewerRenderFrameSubResult); results->frames.push_back(subResult); subResult->view = view; subResult->stats = stats; if (partialUpdateRoIParam) { subResult->textureTransferType = OpenGLViewerI::TextureTransferArgs::eTextureTransferTypeOverlay; } else if (activeDrawingStroke && activeDrawingStroke->getRenderCloneCurrentStrokeStartPointIndex() > 0) { // Upon painting ticks, we just have to update the viewer for the area that was painted subResult->textureTransferType = OpenGLViewerI::TextureTransferArgs::eTextureTransferTypeModify; } else { subResult->textureTransferType = OpenGLViewerI::TextureTransferArgs::eTextureTransferTypeReplace; } for (int viewerInputIndex = 0; viewerInputIndex < 2; ++viewerInputIndex) { subResult->perInputsData[viewerInputIndex].retCode = eActionStatusFailed; if (viewerInputIndex == 1 && (viewerBEqualsViewerA || viewerBlend == eViewerCompositingOperatorNone)) { if (viewerBEqualsViewerA && viewerBlend != eViewerCompositingOperatorNone) { subResult->copyInputBFromA = true; } continue; } if (viewer->isViewerPaused(viewerInputIndex)) { subResult->perInputsData[viewerInputIndex].retCode = eActionStatusAborted; continue; } ViewerInstancePtr viewerProcess = viewer->getViewerProcessNode(viewerInputIndex); subResult->perInputsData[viewerInputIndex].viewerProcessNode = viewerProcess->getNode(); TreeRender::CtorArgsPtr initArgs(new TreeRender::CtorArgs); initArgs->treeRootEffect = viewerProcess; initArgs->provider = provider; initArgs->time = results->time; initArgs->view = subResult->view; // Render by default on disk is always using a mipmap level of 0 but using the proxy scale of the project initArgs->mipMapLevel = mipMapLevel; #pragma message WARN("Todo: set proxy scale here") initArgs->proxyScale = RenderScale(1.); // Render the RoD if fullframe processing if (partialUpdateRoIParam) { initArgs->canonicalRoI = *partialUpdateRoIParam; } else { RectD roi; if (!fullFrameProcessing) { roi = viewerProcess->getViewerRoI(); } initArgs->canonicalRoI = roi; } initArgs->stats = stats; initArgs->activeRotoDrawableItem = activeDrawingStroke; initArgs->draftMode = draftModeEnabled; initArgs->playback = isPlayback; initArgs->byPassCache = byPassCache; initArgs->preventConcurrentTreeRenders = (activeDrawingStroke || partialUpdateRoIParam); if (!isPlayback && subResult->textureTransferType == OpenGLViewerI::TextureTransferArgs::eTextureTransferTypeReplace && !activeDrawingStroke) { subResult->perInputsData[viewerInputIndex].colorPickerNode = viewerInputIndex == 0 ? viewer->getCurrentAInput() : viewer->getCurrentBInput(); if (subResult->perInputsData[viewerInputIndex].colorPickerNode) { // Also sample the "main" input of the color picker node, this is useful for keyers. int mainInput = subResult->perInputsData[viewerInputIndex].colorPickerNode->getPreferredInput(); subResult->perInputsData[viewerInputIndex].colorPickerInputNode = subResult->perInputsData[viewerInputIndex].colorPickerNode->getInput(mainInput); } } if (subResult->perInputsData[viewerInputIndex].colorPickerNode) { initArgs->extraNodesToSample.push_back(subResult->perInputsData[viewerInputIndex].colorPickerNode); } if (subResult->perInputsData[viewerInputIndex].colorPickerInputImage) { initArgs->extraNodesToSample.push_back(subResult->perInputsData[viewerInputIndex].colorPickerInputNode); } subResult->perInputsData[viewerInputIndex].render = TreeRender::create(initArgs); if (!subResult->perInputsData[viewerInputIndex].render) { return eActionStatusFailed; } } // for each viewer input return eActionStatusOK; } // createFrameRenderResultsForView
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
void ProjectGuiSerialization::initialize(const ProjectGui* projectGui) { NodesList activeNodes; projectGui->getInternalProject()->getActiveNodesExpandGroups(&activeNodes); _serializedNodes.clear(); for (NodesList::iterator it = activeNodes.begin(); it != activeNodes.end(); ++it) { NodeGuiIPtr nodegui_i = (*it)->getNodeGui(); if (!nodegui_i) { continue; } NodeGuiPtr nodegui = boost::dynamic_pointer_cast<NodeGui>(nodegui_i); if ( nodegui->isVisible() ) { NodeCollectionPtr isInCollection = (*it)->getGroup(); NodeGroupPtr isCollectionAGroup = toNodeGroup( isInCollection ); if (!isCollectionAGroup) { ///Nodes within a group will be serialized recursively in the node group serialization NodeGuiSerialization state; nodegui->serialize(&state); _serializedNodes.push_back(state); } ViewerInstancePtr viewer = (*it)->isEffectViewerInstance(); 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.isFullFrameProcessEnabled = tab->isFullFrameProcessingEnabled(); 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() ) { KnobHolderPtr holder = (*it)->getHolder(); assert(holder); EffectInstancePtr isEffect = toEffectInstance(holder); ProjectPtr isProj = toProject(holder); if (isProj) { _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