/** @brief ctor */ PenArgs::PenArgs( const PropertySet& props ) : InteractArgs( props ) { pixelScale = getPixelScale( props ); penPosition.x = props.propGetDouble( kOfxInteractPropPenPosition, 0 ); penPosition.y = props.propGetDouble( kOfxInteractPropPenPosition, 1 ); penPressure = props.propGetDouble( kOfxInteractPropPenPressure ); }
/** @brief ctor */ FocusArgs::FocusArgs(const PropertySet &props) : InteractArgs(props) { #ifdef kOfxInteractPropViewportSize // removed in OFX 1.4 viewportSize.x = viewportSize.y = 0.; props.propGetDoubleN(kOfxInteractPropViewportSize, &viewportSize.x, 2, false); #endif pixelScale = getPixelScale(props); backGroundColour = getBackgroundColour(props); }
/** @brief ctor */ PenArgs::PenArgs(const PropertySet &props) : InteractArgs(props) { #ifdef kOfxInteractPropViewportSize // removed in OFX 1.4 viewportSize.x = viewportSize.y = 0.; props.propGetDoubleN(kOfxInteractPropViewportSize, &viewportSize.x, 2, false); #endif pixelScale = getPixelScale(props); backGroundColour = getBackgroundColour(props); penPosition.x = penPosition.y = 0; props.propGetDoubleN(kOfxInteractPropPenPosition, &penPosition.x, 2); // Introduced in OFX 1.2. Return (-1,-1) if not available OfxPointI pen = {-1, -1}; props.propGetIntN(kOfxInteractPropPenViewportPosition, &pen.x, 2); penViewportPosition.x = pen.x; penViewportPosition.y = pen.y; penPressure = props.propGetDouble(kOfxInteractPropPenPressure); }
bool PointOverlayInteract::onOverlayPenUp(TimeValue time, const RenderScale & renderScale, ViewIdx view, const QPointF & viewportPos, const QPointF & penPos, double pressure, TimeValue timestamp) { KnobDoublePtr knob = _imp->param.lock(); // do not show interact if knob is secret or not enabled // see https://github.com/MrKepzie/Natron/issues/932 if ( !knob || !knob->shouldDrawOverlayInteract() ) { return false; } RenderScale pscale; getPixelScale(pscale.x, pscale.y); bool didSomething = false; if (_imp->state == ePositionInteractStatePicked) { if (!_imp->interactiveDrag) { std::vector<double> p(2); p[0] = fround(_imp->lastPenPos.x(), pscale.x); p[1] = fround(_imp->lastPenPos.y(), pscale.y); for (int i = 0; i < 2; ++i) { if (knob->getValueIsNormalized(DimIdx(i)) != eValueIsNormalizedNone) { p[i] = knob->normalize(DimIdx(i), time, p[i]); } } knob->setValueAcrossDimensions(p, DimIdx(0), view, eValueChangedReasonUserEdited); } _imp->state = ePositionInteractStateInactive; bool motion = onOverlayPenMotion(time, renderScale, view, viewportPos, penPos, pressure, timestamp); Q_UNUSED(motion); didSomething = true; } return didSomething; } // onOverlayPenUp
bool ViewerNodeOverlay::onOverlayPenMotion(TimeValue /*time*/, const RenderScale & /*renderScale*/, ViewIdx /*view*/, const QPointF & /*viewportPos*/, const QPointF & pos, double /*pressure*/, TimeValue /*timestamp*/) { Point pixelScale; getPixelScale(pixelScale.x, pixelScale.y); bool userRoIEnabled = _imp->toggleUserRoIButtonKnob.lock()->getValue(); RectD userRoI; if (userRoIEnabled) { if (uiState == eViewerNodeInteractMouseStateDraggingRoiBottomEdge || uiState == eViewerNodeInteractMouseStateDraggingRoiTopEdge || uiState == eViewerNodeInteractMouseStateDraggingRoiLeftEdge || uiState == eViewerNodeInteractMouseStateDraggingRoiRightEdge || uiState == eViewerNodeInteractMouseStateDraggingRoiCross || uiState == eViewerNodeInteractMouseStateDraggingRoiBottomLeft || uiState == eViewerNodeInteractMouseStateDraggingRoiBottomRight || uiState == eViewerNodeInteractMouseStateDraggingRoiTopLeft || uiState == eViewerNodeInteractMouseStateDraggingRoiTopRight) { userRoI = draggedUserRoI; } else { userRoI = _imp->_publicInterface->getUserRoI(); } } bool wipeEnabled = (ViewerCompositingOperatorEnum)_imp->blendingModeChoiceKnob.lock()->getValue() != eViewerCompositingOperatorNone; double wipeAmount = _imp->_publicInterface->getWipeAmount(); double wipeAngle = _imp->_publicInterface->getWipeAngle(); QPointF wipeCenter = _imp->_publicInterface->getWipeCenter(); bool wasHovering = hoverState != eHoverStateNothing; bool cursorSet = false; bool overlayCaught = false; hoverState = eHoverStateNothing; if ( wipeEnabled && isNearbyWipeCenter(wipeCenter, pos, pixelScale.x, pixelScale.y) ) { _imp->_publicInterface->setCurrentCursor(eCursorSizeAll); cursorSet = true; } else if ( wipeEnabled && isNearbyWipeMixHandle(wipeCenter, wipeAngle, wipeAmount, pos, pixelScale.x, pixelScale.y) ) { hoverState = eHoverStateWipeMix; overlayCaught = true; } else if ( wipeEnabled && isNearbyWipeRotateBar(wipeCenter, wipeAngle, pos, pixelScale.x, pixelScale.y) ) { hoverState = eHoverStateWipeRotateHandle; overlayCaught = true; } else if (userRoIEnabled) { if ( isNearbyUserRoIBottomEdge(userRoI, pos, pixelScale.x, pixelScale.y) || isNearbyUserRoITopEdge(userRoI, pos, pixelScale.x, pixelScale.y) || ( uiState == eViewerNodeInteractMouseStateDraggingRoiBottomEdge) || ( uiState == eViewerNodeInteractMouseStateDraggingRoiTopEdge) ) { _imp->_publicInterface->setCurrentCursor(eCursorSizeVer); cursorSet = true; } else if ( isNearbyUserRoILeftEdge(userRoI, pos, pixelScale.x, pixelScale.y) || isNearbyUserRoIRightEdge(userRoI, pos, pixelScale.x, pixelScale.y) || ( uiState == eViewerNodeInteractMouseStateDraggingRoiLeftEdge) || ( uiState == eViewerNodeInteractMouseStateDraggingRoiRightEdge) ) { _imp->_publicInterface->setCurrentCursor(eCursorSizeHor); cursorSet = true; } else if ( isNearbyUserRoI( (userRoI.x1 + userRoI.x2) / 2, (userRoI.y1 + userRoI.y2) / 2, pos, pixelScale.x, pixelScale.y ) || ( uiState == eViewerNodeInteractMouseStateDraggingRoiCross) ) { _imp->_publicInterface->setCurrentCursor(eCursorSizeAll); cursorSet = true; } else if ( isNearbyUserRoI(userRoI.x2, userRoI.y1, pos, pixelScale.x, pixelScale.y) || isNearbyUserRoI(userRoI.x1, userRoI.y2, pos, pixelScale.x, pixelScale.y) || ( uiState == eViewerNodeInteractMouseStateDraggingRoiBottomRight) || ( uiState == eViewerNodeInteractMouseStateDraggingRoiTopLeft) ) { _imp->_publicInterface->setCurrentCursor(eCursorFDiag); cursorSet = true; } else if ( isNearbyUserRoI(userRoI.x1, userRoI.y1, pos, pixelScale.x, pixelScale.y) || isNearbyUserRoI(userRoI.x2, userRoI.y2, pos, pixelScale.x, pixelScale.y) || ( uiState == eViewerNodeInteractMouseStateDraggingRoiBottomLeft) || ( uiState == eViewerNodeInteractMouseStateDraggingRoiTopRight) ) { _imp->_publicInterface->setCurrentCursor(eCursorBDiag); cursorSet = true; } } if (!cursorSet) { _imp->_publicInterface->setCurrentCursor(eCursorDefault); } if ( (hoverState == eHoverStateNothing) && wasHovering ) { overlayCaught = true; } double dx = pos.x() - lastMousePos.x(); double dy = pos.y() - lastMousePos.y(); switch (uiState) { case eViewerNodeInteractMouseStateDraggingRoiBottomEdge: { if ( (draggedUserRoI.y1 + dy) < draggedUserRoI.y2 ) { draggedUserRoI.y1 += dy; overlayCaught = true; } break; } case eViewerNodeInteractMouseStateDraggingRoiLeftEdge: { if ( (draggedUserRoI.x1 + dx) < draggedUserRoI.x2 ) { draggedUserRoI.x1 += dx; overlayCaught = true; } break; } case eViewerNodeInteractMouseStateDraggingRoiRightEdge: { if ( (draggedUserRoI.x2 + dx) > draggedUserRoI.x1 ) { draggedUserRoI.x2 += dx; overlayCaught = true; } break; } case eViewerNodeInteractMouseStateDraggingRoiTopEdge: { if ( (draggedUserRoI.y2 + dy) > draggedUserRoI.y1 ) { draggedUserRoI.y2 += dy; overlayCaught = true; } break; } case eViewerNodeInteractMouseStateDraggingRoiCross: { draggedUserRoI.translate(dx, dy); overlayCaught = true; break; } case eViewerNodeInteractMouseStateDraggingRoiTopLeft: { if ( (draggedUserRoI.y2 + dy) > draggedUserRoI.y1 ) { draggedUserRoI.y2 += dy; } if ( (draggedUserRoI.x1 + dx) < draggedUserRoI.x2 ) { draggedUserRoI.x1 += dx; } overlayCaught = true; break; } case eViewerNodeInteractMouseStateDraggingRoiTopRight: { if ( (draggedUserRoI.y2 + dy) > draggedUserRoI.y1 ) { draggedUserRoI.y2 += dy; } if ( (draggedUserRoI.x2 + dx) > draggedUserRoI.x1 ) { draggedUserRoI.x2 += dx; } overlayCaught = true; break; } case eViewerNodeInteractMouseStateDraggingRoiBottomRight: case eViewerNodeInteractMouseStateBuildingUserRoI:{ if ( (draggedUserRoI.x2 + dx) > draggedUserRoI.x1 ) { draggedUserRoI.x2 += dx; } if ( (draggedUserRoI.y1 + dy) < draggedUserRoI.y2 ) { draggedUserRoI.y1 += dy; } overlayCaught = true; break; } case eViewerNodeInteractMouseStateDraggingRoiBottomLeft: { if ( (draggedUserRoI.y1 + dy) < draggedUserRoI.y2 ) { draggedUserRoI.y1 += dy; } if ( (draggedUserRoI.x1 + dx) < draggedUserRoI.x2 ) { draggedUserRoI.x1 += dx; } overlayCaught = true; break; } case eViewerNodeInteractMouseStateDraggingWipeCenter: { KnobDoublePtr centerKnob = _imp->wipeCenter.lock(); centerKnob->setValue(centerKnob->getValue() + dx); centerKnob->setValue(centerKnob->getValue(DimIdx(1)) + dy, ViewSetSpec::all(), DimIdx(1)); overlayCaught = true; break; } case eViewerNodeInteractMouseStateDraggingWipeMixHandle: { KnobDoublePtr centerKnob = _imp->wipeCenter.lock(); Point center; center.x = centerKnob->getValue(); center.y = centerKnob->getValue(DimIdx(1)); double angle = std::atan2( pos.y() - center.y, pos.x() - center.x ); double prevAngle = std::atan2( lastMousePos.y() - center.y, lastMousePos.x() - center.x ); KnobDoublePtr mixKnob = _imp->wipeAmount.lock(); double mixAmount = mixKnob->getValue(); mixAmount -= (angle - prevAngle); mixAmount = std::max( 0., std::min(mixAmount, 1.) ); mixKnob->setValue(mixAmount); overlayCaught = true; break; } case eViewerNodeInteractMouseStateRotatingWipeHandle: { KnobDoublePtr centerKnob = _imp->wipeCenter.lock(); Point center; center.x = centerKnob->getValue(); center.y = centerKnob->getValue(DimIdx(1)); double angle = std::atan2( pos.y() - center.y, pos.x() - center.x ); KnobDoublePtr angleKnob = _imp->wipeAngle.lock(); double closestPI2 = M_PI_2 * std::floor(angle / M_PI_2 + 0.5); if (std::fabs(angle - closestPI2) < 0.1) { // snap to closest multiple of PI / 2. angle = closestPI2; } angleKnob->setValue(angle); overlayCaught = true; break; } default: break; } lastMousePos = pos; return overlayCaught; } // onOverlayPenMotion
bool ViewerNodeOverlay::onOverlayPenDown(TimeValue /*time*/, const RenderScale & /*renderScale*/, ViewIdx /*view*/, const QPointF & /*viewportPos*/, const QPointF & pos, double /*pressure*/, TimeValue /*timestamp*/, PenType pen) { Point pixelScale; getPixelScale(pixelScale.x, pixelScale.y); bool overlaysCaught = false; if (!overlaysCaught && pen == ePenTypeLMB && buildUserRoIOnNextPress) { draggedUserRoI.x1 = pos.x(); draggedUserRoI.y1 = pos.y(); draggedUserRoI.x2 = pos.x(); draggedUserRoI.y2 = pos.y(); buildUserRoIOnNextPress = false; uiState = eViewerNodeInteractMouseStateBuildingUserRoI; overlaysCaught = true; } bool userRoIEnabled = _imp->toggleUserRoIButtonKnob.lock()->getValue(); RectD userRoI; if (userRoIEnabled) { userRoI = _imp->_publicInterface->getUserRoI(); } // Catch wipe bool wipeEnabled = (ViewerCompositingOperatorEnum)_imp->blendingModeChoiceKnob.lock()->getValue() != eViewerCompositingOperatorNone; double wipeAmount = _imp->_publicInterface->getWipeAmount(); double wipeAngle = _imp->_publicInterface->getWipeAngle(); QPointF wipeCenter = _imp->_publicInterface->getWipeCenter(); if ( !overlaysCaught && wipeEnabled && pen == ePenTypeLMB && isNearbyWipeCenter(wipeCenter, pos, pixelScale.x, pixelScale.y) ) { uiState = eViewerNodeInteractMouseStateDraggingWipeCenter; overlaysCaught = true; } if ( !overlaysCaught && wipeEnabled && pen == ePenTypeLMB && isNearbyWipeMixHandle(wipeCenter, wipeAngle, wipeAmount, pos, pixelScale.x, pixelScale.y) ) { uiState = eViewerNodeInteractMouseStateDraggingWipeMixHandle; overlaysCaught = true; } if ( !overlaysCaught && wipeEnabled && pen == ePenTypeLMB && isNearbyWipeRotateBar(wipeCenter, wipeAngle, pos, pixelScale.x, pixelScale.y) ) { uiState = eViewerNodeInteractMouseStateRotatingWipeHandle; overlaysCaught = true; } // Catch User RoI if ( !overlaysCaught && pen == ePenTypeLMB && userRoIEnabled && isNearbyUserRoIBottomEdge(userRoI, pos, pixelScale.x, pixelScale.y) ) { // start dragging the bottom edge of the user ROI uiState = eViewerNodeInteractMouseStateDraggingRoiBottomEdge; draggedUserRoI = userRoI; overlaysCaught = true; } if ( !overlaysCaught && pen == ePenTypeLMB && userRoIEnabled && isNearbyUserRoILeftEdge(userRoI, pos, pixelScale.x, pixelScale.y) ) { // start dragging the left edge of the user ROI uiState = eViewerNodeInteractMouseStateDraggingRoiLeftEdge; draggedUserRoI = userRoI; overlaysCaught = true; } if ( !overlaysCaught && pen == ePenTypeLMB && userRoIEnabled && isNearbyUserRoIRightEdge(userRoI, pos, pixelScale.x, pixelScale.y) ) { // start dragging the right edge of the user ROI uiState = eViewerNodeInteractMouseStateDraggingRoiRightEdge; draggedUserRoI = userRoI; overlaysCaught = true; } if ( !overlaysCaught && pen == ePenTypeLMB && userRoIEnabled && isNearbyUserRoITopEdge(userRoI, pos, pixelScale.x, pixelScale.y) ) { // start dragging the top edge of the user ROI uiState = eViewerNodeInteractMouseStateDraggingRoiTopEdge; draggedUserRoI = userRoI; overlaysCaught = true; } if ( !overlaysCaught && pen == ePenTypeLMB && userRoIEnabled && isNearbyUserRoI( (userRoI.x1 + userRoI.x2) / 2., (userRoI.y1 + userRoI.y2) / 2., pos, pixelScale.x, pixelScale.y ) ) { // start dragging the midpoint of the user ROI uiState = eViewerNodeInteractMouseStateDraggingRoiCross; draggedUserRoI = userRoI; overlaysCaught = true; } if ( !overlaysCaught && pen == ePenTypeLMB && userRoIEnabled && isNearbyUserRoI(userRoI.x1, userRoI.y2, pos, pixelScale.x, pixelScale.y) ) { // start dragging the topleft corner of the user ROI uiState = eViewerNodeInteractMouseStateDraggingRoiTopLeft; draggedUserRoI = userRoI; overlaysCaught = true; } if ( !overlaysCaught && pen == ePenTypeLMB && userRoIEnabled && isNearbyUserRoI(userRoI.x2, userRoI.y2, pos, pixelScale.x, pixelScale.y) ) { // start dragging the topright corner of the user ROI uiState = eViewerNodeInteractMouseStateDraggingRoiTopRight; draggedUserRoI = userRoI; overlaysCaught = true; } if ( !overlaysCaught && pen == ePenTypeLMB && userRoIEnabled && isNearbyUserRoI(userRoI.x1, userRoI.y1, pos, pixelScale.x, pixelScale.y) ) { // start dragging the bottomleft corner of the user ROI uiState = eViewerNodeInteractMouseStateDraggingRoiBottomLeft; draggedUserRoI = userRoI; overlaysCaught = true; } if ( !overlaysCaught && pen == ePenTypeLMB && userRoIEnabled && isNearbyUserRoI(userRoI.x2, userRoI.y1, pos, pixelScale.x, pixelScale.y) ) { // start dragging the bottomright corner of the user ROI uiState = eViewerNodeInteractMouseStateDraggingRoiBottomRight; draggedUserRoI = userRoI; overlaysCaught = true; } if ( !overlaysCaught && pen == ePenTypeRMB ) { showRightClickMenu(); overlaysCaught = true; } lastMousePos = pos; return overlaysCaught; } // onOverlayPenDown
void ViewerNodeOverlay::drawWipeControl() { Point pixelScale; getPixelScale(pixelScale.x, pixelScale.y); double angle; QPointF center; double mixAmount; { angle = _imp->wipeAngle.lock()->getValue(); KnobDoublePtr centerKnob = _imp->wipeCenter.lock(); center.rx() = centerKnob->getValue(); center.ry() = centerKnob->getValue(DimIdx(1)); mixAmount = _imp->wipeAmount.lock()->getValue(); } double alphaMix1, alphaMix0, alphaCurMix; alphaMix1 = angle + M_PI_4 / 2; alphaMix0 = angle + 3. * M_PI_4 / 2; alphaCurMix = mixAmount * (alphaMix1 - alphaMix0) + alphaMix0; QPointF mix0Pos, mixPos, mix1Pos; double mixX, mixY, rotateW, rotateH, rotateOffsetX, rotateOffsetY; mixX = WIPE_MIX_HANDLE_LENGTH * pixelScale.x; mixY = WIPE_MIX_HANDLE_LENGTH * pixelScale.y; rotateW = WIPE_ROTATE_HANDLE_LENGTH * pixelScale.x; rotateH = WIPE_ROTATE_HANDLE_LENGTH * pixelScale.y; rotateOffsetX = WIPE_ROTATE_OFFSET * pixelScale.x; rotateOffsetY = WIPE_ROTATE_OFFSET * pixelScale.y; mixPos.setX(center.x() + std::cos(alphaCurMix) * mixX); mixPos.setY(center.y() + std::sin(alphaCurMix) * mixY); mix0Pos.setX(center.x() + std::cos(alphaMix0) * mixX); mix0Pos.setY(center.y() + std::sin(alphaMix0) * mixY); mix1Pos.setX(center.x() + std::cos(alphaMix1) * mixX); mix1Pos.setY(center.y() + std::sin(alphaMix1) * mixY); QPointF oppositeAxisBottom, oppositeAxisTop, rotateAxisLeft, rotateAxisRight; rotateAxisRight.setX( center.x() + std::cos(angle) * (rotateW - rotateOffsetX) ); rotateAxisRight.setY( center.y() + std::sin(angle) * (rotateH - rotateOffsetY) ); rotateAxisLeft.setX(center.x() - std::cos(angle) * rotateOffsetX); rotateAxisLeft.setY( center.y() - (std::sin(angle) * rotateOffsetY) ); oppositeAxisTop.setX( center.x() + std::cos(angle + M_PI_2) * (rotateW / 2.) ); oppositeAxisTop.setY( center.y() + std::sin(angle + M_PI_2) * (rotateH / 2.) ); oppositeAxisBottom.setX( center.x() - std::cos(angle + M_PI_2) * (rotateW / 2.) ); oppositeAxisBottom.setY( center.y() - std::sin(angle + M_PI_2) * (rotateH / 2.) ); { GLProtectAttrib<GL_GPU> a(GL_ENABLE_BIT | GL_LINE_BIT | GL_CURRENT_BIT | GL_HINT_BIT | GL_TRANSFORM_BIT | GL_COLOR_BUFFER_BIT); //GLProtectMatrix p(GL_PROJECTION); // useless (we do two glTranslate in opposite directions) // Draw everything twice // l = 0: shadow // l = 1: drawing double baseColor[3]; for (int l = 0; l < 2; ++l) { // shadow (uses GL_PROJECTION) GL_GPU::MatrixMode(GL_PROJECTION); int direction = (l == 0) ? 1 : -1; // translate (1,-1) pixels GL_GPU::Translated(direction * pixelScale.x, -direction * pixelScale.y, 0); GL_GPU::MatrixMode(GL_MODELVIEW); // Modelview should be used on Nuke if (l == 0) { // Draw a shadow for the cross hair baseColor[0] = baseColor[1] = baseColor[2] = 0.; } else { baseColor[0] = baseColor[1] = baseColor[2] = 0.8; } GL_GPU::Enable(GL_BLEND); GL_GPU::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_GPU::Enable(GL_LINE_SMOOTH); GL_GPU::Hint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE); GL_GPU::LineWidth(1.5); GL_GPU::Begin(GL_LINES); if ( (hoverState == eHoverStateWipeRotateHandle) || (uiState == eViewerNodeInteractMouseStateRotatingWipeHandle) ) { GL_GPU::Color4f(0., 1. * l, 0., 1.); } GL_GPU::Color4f(baseColor[0], baseColor[1], baseColor[2], 1.); GL_GPU::Vertex2d( rotateAxisLeft.x(), rotateAxisLeft.y() ); GL_GPU::Vertex2d( rotateAxisRight.x(), rotateAxisRight.y() ); GL_GPU::Vertex2d( oppositeAxisBottom.x(), oppositeAxisBottom.y() ); GL_GPU::Vertex2d( oppositeAxisTop.x(), oppositeAxisTop.y() ); GL_GPU::Vertex2d( center.x(), center.y() ); GL_GPU::Vertex2d( mixPos.x(), mixPos.y() ); GL_GPU::End(); GL_GPU::LineWidth(1.); ///if hovering the rotate handle or dragging it show a small bended arrow if ( (hoverState == eHoverStateWipeRotateHandle) || (uiState == eViewerNodeInteractMouseStateRotatingWipeHandle) ) { GLProtectMatrix<GL_GPU> p(GL_MODELVIEW); GL_GPU::Color4f(0., 1. * l, 0., 1.); double arrowCenterX = WIPE_ROTATE_HANDLE_LENGTH * pixelScale.x / 2; ///draw an arrow slightly bended. This is an arc of circle of radius 5 in X, and 10 in Y. OfxPointD arrowRadius; arrowRadius.x = 5. * pixelScale.x; arrowRadius.y = 10. * pixelScale.y; GL_GPU::Translatef(center.x(), center.y(), 0.); GL_GPU::Rotatef(angle * 180.0 / M_PI, 0, 0, 1); // center the oval at x_center, y_center GL_GPU::Translatef (arrowCenterX, 0., 0); // draw the oval using line segments GL_GPU::Begin (GL_LINE_STRIP); GL_GPU::Vertex2f (0, arrowRadius.y); GL_GPU::Vertex2f (arrowRadius.x, 0.); GL_GPU::Vertex2f (0, -arrowRadius.y); GL_GPU::End (); GL_GPU::Begin(GL_LINES); ///draw the top head GL_GPU::Vertex2f(0., arrowRadius.y); GL_GPU::Vertex2f(0., arrowRadius.y - arrowRadius.x ); GL_GPU::Vertex2f(0., arrowRadius.y); GL_GPU::Vertex2f(4. * pixelScale.x, arrowRadius.y - 3. * pixelScale.y); // 5^2 = 3^2+4^2 ///draw the bottom head GL_GPU::Vertex2f(0., -arrowRadius.y); GL_GPU::Vertex2f(0., -arrowRadius.y + 5. * pixelScale.y); GL_GPU::Vertex2f(0., -arrowRadius.y); GL_GPU::Vertex2f(4. * pixelScale.x, -arrowRadius.y + 3. * pixelScale.y); // 5^2 = 3^2+4^2 GL_GPU::End(); GL_GPU::Color4f(baseColor[0], baseColor[1], baseColor[2], 1.); } GL_GPU::PointSize(5.); GL_GPU::Enable(GL_POINT_SMOOTH); GL_GPU::Begin(GL_POINTS); GL_GPU::Vertex2d( center.x(), center.y() ); if ( ( (hoverState == eHoverStateWipeMix) && (uiState != eViewerNodeInteractMouseStateRotatingWipeHandle) ) || (uiState == eViewerNodeInteractMouseStateDraggingWipeMixHandle) ) { GL_GPU::Color4f(0., 1. * l, 0., 1.); } GL_GPU::Vertex2d( mixPos.x(), mixPos.y() ); GL_GPU::End(); GL_GPU::PointSize(1.); drawArcOfCircle(center, mixX, mixY, angle + M_PI_4 / 2, angle + 3. * M_PI_4 / 2); } } // GLProtectAttrib a(GL_ENABLE_BIT | GL_LINE_BIT | GL_CURRENT_BIT | GL_HINT_BIT | GL_TRANSFORM_BIT | GL_COLOR_BUFFER_BIT); } // drawWipeControl
void ViewerNodeOverlay::drawUserRoI() { Point pixelScale; getPixelScale(pixelScale.x, pixelScale.y); { GLProtectAttrib<GL_GPU> a(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_ENABLE_BIT); GL_GPU::Disable(GL_BLEND); GL_GPU::Color4f(0.9, 0.9, 0.9, 1.); RectD userRoI; if ( uiState == eViewerNodeInteractMouseStateBuildingUserRoI || uiState == eViewerNodeInteractMouseStateDraggingRoiBottomEdge || uiState == eViewerNodeInteractMouseStateDraggingRoiBottomLeft || uiState == eViewerNodeInteractMouseStateDraggingRoiBottomRight || uiState == eViewerNodeInteractMouseStateDraggingRoiRightEdge || uiState == eViewerNodeInteractMouseStateDraggingRoiTopRight || uiState == eViewerNodeInteractMouseStateDraggingRoiTopEdge || uiState == eViewerNodeInteractMouseStateDraggingRoiTopLeft || uiState == eViewerNodeInteractMouseStateDraggingRoiLeftEdge || uiState == eViewerNodeInteractMouseStateDraggingRoiCross || buildUserRoIOnNextPress ) { userRoI = draggedUserRoI; } else { userRoI = _imp->_publicInterface->getUserRoI(); } if (buildUserRoIOnNextPress) { GL_GPU::LineStipple(2, 0xAAAA); GL_GPU::Enable(GL_LINE_STIPPLE); } ///base rect GL_GPU::Begin(GL_LINE_LOOP); GL_GPU::Vertex2f(userRoI.x1, userRoI.y1); //bottom left GL_GPU::Vertex2f(userRoI.x1, userRoI.y2); //top left GL_GPU::Vertex2f(userRoI.x2, userRoI.y2); //top right GL_GPU::Vertex2f(userRoI.x2, userRoI.y1); //bottom right GL_GPU::End(); GL_GPU::Begin(GL_LINES); ///border ticks double borderTickWidth = USER_ROI_BORDER_TICK_SIZE * pixelScale.x; double borderTickHeight = USER_ROI_BORDER_TICK_SIZE * pixelScale.y; GL_GPU::Vertex2f(userRoI.x1, (userRoI.y1 + userRoI.y2) / 2); GL_GPU::Vertex2f(userRoI.x1 - borderTickWidth, (userRoI.y1 + userRoI.y2) / 2); GL_GPU::Vertex2f(userRoI.x2, (userRoI.y1 + userRoI.y2) / 2); GL_GPU::Vertex2f(userRoI.x2 + borderTickWidth, (userRoI.y1 + userRoI.y2) / 2); GL_GPU::Vertex2f( (userRoI.x1 + userRoI.x2) / 2, userRoI.y2 ); GL_GPU::Vertex2f( (userRoI.x1 + userRoI.x2) / 2, userRoI.y2 + borderTickHeight ); GL_GPU::Vertex2f( (userRoI.x1 + userRoI.x2) / 2, userRoI.y1 ); GL_GPU::Vertex2f( (userRoI.x1 + userRoI.x2) / 2, userRoI.y1 - borderTickHeight ); ///middle cross double crossWidth = USER_ROI_CROSS_RADIUS * pixelScale.x; double crossHeight = USER_ROI_CROSS_RADIUS * pixelScale.y; GL_GPU::Vertex2f( (userRoI.x1 + userRoI.x2) / 2, (userRoI.y1 + userRoI.y2) / 2 - crossHeight ); GL_GPU::Vertex2f( (userRoI.x1 + userRoI.x2) / 2, (userRoI.y1 + userRoI.y2) / 2 + crossHeight ); GL_GPU::Vertex2f( (userRoI.x1 + userRoI.x2) / 2 - crossWidth, (userRoI.y1 + userRoI.y2) / 2 ); GL_GPU::Vertex2f( (userRoI.x1 + userRoI.x2) / 2 + crossWidth, (userRoI.y1 + userRoI.y2) / 2 ); GL_GPU::End(); ///draw handles hint for the user GL_GPU::Begin(GL_QUADS); double rectHalfWidth = (USER_ROI_SELECTION_POINT_SIZE * pixelScale.x) / 2.; double rectHalfHeight = (USER_ROI_SELECTION_POINT_SIZE * pixelScale.y) / 2.; //left GL_GPU::Vertex2f(userRoI.x1 + rectHalfWidth, (userRoI.y1 + userRoI.y2) / 2 - rectHalfHeight); GL_GPU::Vertex2f(userRoI.x1 + rectHalfWidth, (userRoI.y1 + userRoI.y2) / 2 + rectHalfHeight); GL_GPU::Vertex2f(userRoI.x1 - rectHalfWidth, (userRoI.y1 + userRoI.y2) / 2 + rectHalfHeight); GL_GPU::Vertex2f(userRoI.x1 - rectHalfWidth, (userRoI.y1 + userRoI.y2) / 2 - rectHalfHeight); //top GL_GPU::Vertex2f( (userRoI.x1 + userRoI.x2) / 2 - rectHalfWidth, userRoI.y2 - rectHalfHeight ); GL_GPU::Vertex2f( (userRoI.x1 + userRoI.x2) / 2 - rectHalfWidth, userRoI.y2 + rectHalfHeight ); GL_GPU::Vertex2f( (userRoI.x1 + userRoI.x2) / 2 + rectHalfWidth, userRoI.y2 + rectHalfHeight ); GL_GPU::Vertex2f( (userRoI.x1 + userRoI.x2) / 2 + rectHalfWidth, userRoI.y2 - rectHalfHeight ); //right GL_GPU::Vertex2f(userRoI.x2 - rectHalfWidth, (userRoI.y1 + userRoI.y2) / 2 - rectHalfHeight); GL_GPU::Vertex2f(userRoI.x2 - rectHalfWidth, (userRoI.y1 + userRoI.y2) / 2 + rectHalfHeight); GL_GPU::Vertex2f(userRoI.x2 + rectHalfWidth, (userRoI.y1 + userRoI.y2) / 2 + rectHalfHeight); GL_GPU::Vertex2f(userRoI.x2 + rectHalfWidth, (userRoI.y1 + userRoI.y2) / 2 - rectHalfHeight); //bottom GL_GPU::Vertex2f( (userRoI.x1 + userRoI.x2) / 2 - rectHalfWidth, userRoI.y1 - rectHalfHeight ); GL_GPU::Vertex2f( (userRoI.x1 + userRoI.x2) / 2 - rectHalfWidth, userRoI.y1 + rectHalfHeight ); GL_GPU::Vertex2f( (userRoI.x1 + userRoI.x2) / 2 + rectHalfWidth, userRoI.y1 + rectHalfHeight ); GL_GPU::Vertex2f( (userRoI.x1 + userRoI.x2) / 2 + rectHalfWidth, userRoI.y1 - rectHalfHeight ); //middle GL_GPU::Vertex2f( (userRoI.x1 + userRoI.x2) / 2 - rectHalfWidth, (userRoI.y1 + userRoI.y2) / 2 - rectHalfHeight ); GL_GPU::Vertex2f( (userRoI.x1 + userRoI.x2) / 2 - rectHalfWidth, (userRoI.y1 + userRoI.y2) / 2 + rectHalfHeight ); GL_GPU::Vertex2f( (userRoI.x1 + userRoI.x2) / 2 + rectHalfWidth, (userRoI.y1 + userRoI.y2) / 2 + rectHalfHeight ); GL_GPU::Vertex2f( (userRoI.x1 + userRoI.x2) / 2 + rectHalfWidth, (userRoI.y1 + userRoI.y2) / 2 - rectHalfHeight ); //top left GL_GPU::Vertex2f(userRoI.x1 - rectHalfWidth, userRoI.y2 - rectHalfHeight); GL_GPU::Vertex2f(userRoI.x1 - rectHalfWidth, userRoI.y2 + rectHalfHeight); GL_GPU::Vertex2f(userRoI.x1 + rectHalfWidth, userRoI.y2 + rectHalfHeight); GL_GPU::Vertex2f(userRoI.x1 + rectHalfWidth, userRoI.y2 - rectHalfHeight); //top right GL_GPU::Vertex2f(userRoI.x2 - rectHalfWidth, userRoI.y2 - rectHalfHeight); GL_GPU::Vertex2f(userRoI.x2 - rectHalfWidth, userRoI.y2 + rectHalfHeight); GL_GPU::Vertex2f(userRoI.x2 + rectHalfWidth, userRoI.y2 + rectHalfHeight); GL_GPU::Vertex2f(userRoI.x2 + rectHalfWidth, userRoI.y2 - rectHalfHeight); //bottom right GL_GPU::Vertex2f(userRoI.x2 - rectHalfWidth, userRoI.y1 - rectHalfHeight); GL_GPU::Vertex2f(userRoI.x2 - rectHalfWidth, userRoI.y1 + rectHalfHeight); GL_GPU::Vertex2f(userRoI.x2 + rectHalfWidth, userRoI.y1 + rectHalfHeight); GL_GPU::Vertex2f(userRoI.x2 + rectHalfWidth, userRoI.y1 - rectHalfHeight); //bottom left GL_GPU::Vertex2f(userRoI.x1 - rectHalfWidth, userRoI.y1 - rectHalfHeight); GL_GPU::Vertex2f(userRoI.x1 - rectHalfWidth, userRoI.y1 + rectHalfHeight); GL_GPU::Vertex2f(userRoI.x1 + rectHalfWidth, userRoI.y1 + rectHalfHeight); GL_GPU::Vertex2f(userRoI.x1 + rectHalfWidth, userRoI.y1 - rectHalfHeight); GL_GPU::End(); if (buildUserRoIOnNextPress) { GL_GPU::Disable(GL_LINE_STIPPLE); } } // GLProtectAttrib a(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_ENABLE_BIT); } // drawUserRoI
bool CornerPinOverlayInteract::onOverlayPenMotion(TimeValue time, const RenderScale & /*renderScale*/, ViewIdx view, const QPointF & /*viewportPos*/, const QPointF & penPos, double /*pressure*/, TimeValue /*timestamp*/) { // do not show interact if knob is secret or not enabled // see https://github.com/MrKepzie/Natron/issues/932 KnobDoublePtr from1Knob = _imp->from[0].lock(); if ( !from1Knob || !from1Knob->shouldDrawOverlayInteract() ) { return false; } RenderScale pscale; getPixelScale(pscale.x, pscale.y); OfxPointD to[4]; OfxPointD from[4]; bool enable[4]; bool useFrom; if (_imp->dragging == -1) { for (int i = 0; i < 4; ++i) { _imp->getFrom(time, i, &from[i].x, &from[i].y); _imp->getTo(time, i, &to[i].x, &to[i].y); enable[i] = _imp->getEnabled(time, i); } useFrom = _imp->getUseFromPoints(time); } else { for (int i = 0; i < 4; ++i) { to[i] = _imp->toDrag[i]; from[i] = _imp->fromDrag[i]; enable[i] = _imp->enableDrag[i]; } useFrom = _imp->useFromDrag; } if (!useFrom && !_imp->areToPointsAnimated()) { return false; } OfxPointD p[4]; OfxPointD q[4]; int enableBegin = 4; int enableEnd = 0; for (int i = 0; i < 4; ++i) { if (enable[i]) { if (useFrom) { p[i] = from[i]; q[i] = to[i]; } else { q[i] = from[i]; p[i] = to[i]; } if (i < enableBegin) { enableBegin = i; } if (i + 1 > enableEnd) { enableEnd = i + 1; } } } bool didSomething = false; bool valuesChanged = false; OfxPointD delta; delta.x = penPos.x() - _imp->lastPenPos.x(); delta.y = penPos.y() - _imp->lastPenPos.y(); _imp->hovering = -1; for (int i = enableBegin; i < enableEnd; ++i) { if (enable[i]) { if (_imp->dragging == i) { if (useFrom) { from[i].x += delta.x; from[i].y += delta.y; _imp->fromDrag[i] = from[i]; } else { to[i].x += delta.x; to[i].y += delta.y; _imp->toDrag[i] = to[i]; } valuesChanged = true; } else if ( CornerPinOverlayInteractPrivate::isNearby(penPos, p[i].x, p[i].y, CornerPinOverlayInteractPrivate::pointTolerance(), pscale) ) { _imp->hovering = i; didSomething = true; } } } if ( (_imp->dragging != -1) && _imp->interactiveDrag && valuesChanged ) { // no need to redraw overlay since it is slave to the paramaters if (_imp->useFromDrag) { KnobDoublePtr knob = _imp->from[_imp->dragging].lock(); assert(knob); std::vector<double> val(2); val[0] = from[_imp->dragging].x; val[1] = from[_imp->dragging].y; knob->setValueAcrossDimensions(val, DimIdx(0), view, eValueChangedReasonUserEdited); } else { KnobDoublePtr knob = _imp->to[_imp->dragging].lock(); assert(knob); std::vector<double> val(2); val[0] = to[_imp->dragging].x; val[1] = to[_imp->dragging].y; if (_imp->toPointsAutoKeyingEnabled) { knob->setValueAtTimeAcrossDimensions(time, val, DimIdx(0), view, eValueChangedReasonUserEdited); // Also set a keyframe on other points for (int i = 0; i < 4; ++i) { if (i == _imp->dragging) { continue; } std::vector<double> values(2); KnobDoublePtr toPoint = _imp->to[i].lock(); values[0] = toPoint->getValueAtTime(time, DimIdx(0)); values[1] = toPoint->getValueAtTime(time, DimIdx(1)); toPoint->setValueAtTimeAcrossDimensions(time, values, DimIdx(0), view, eValueChangedReasonUserEdited); } } else { knob->setValueAcrossDimensions(val, DimIdx(0), view, eValueChangedReasonUserEdited); } } } _imp->lastPenPos = penPos; return didSomething || valuesChanged; } // onOverlayPenMotion
bool CornerPinOverlayInteract::onOverlayPenDown(TimeValue time, const RenderScale & /*renderScale*/, ViewIdx /*view*/, const QPointF & /*viewportPos*/, const QPointF & pos, double /*pressure*/, TimeValue /*timestamp*/, PenType /*pen*/) { // do not show interact if knob is secret or not enabled // see https://github.com/MrKepzie/Natron/issues/932 KnobDoublePtr from1Knob = _imp->from[0].lock(); if ( !from1Knob || !from1Knob->shouldDrawOverlayInteract() ) { return false; } RenderScale pscale; getPixelScale(pscale.x, pscale.y); OfxPointD to[4]; OfxPointD from[4]; bool enable[4]; bool useFrom; if (_imp->dragging == -1) { for (int i = 0; i < 4; ++i) { _imp->getFrom(time, i, &from[i].x, &from[i].y); _imp->getTo(time, i, &to[i].x, &to[i].y); enable[i] = _imp->getEnabled(time, i); } useFrom = _imp->getUseFromPoints(time); } else { for (int i = 0; i < 4; ++i) { to[i] = _imp->toDrag[i]; from[i] = _imp->fromDrag[i]; enable[i] = _imp->enableDrag[i]; } useFrom = _imp->useFromDrag; } if (!useFrom && !_imp->areToPointsAnimated()) { return false; } OfxPointD p[4]; OfxPointD q[4]; int enableBegin = 4; int enableEnd = 0; for (int i = 0; i < 4; ++i) { if (enable[i]) { if (useFrom) { p[i] = from[i]; q[i] = to[i]; } else { q[i] = from[i]; p[i] = to[i]; } if (i < enableBegin) { enableBegin = i; } if (i + 1 > enableEnd) { enableEnd = i + 1; } } } bool didSomething = false; for (int i = enableBegin; i < enableEnd; ++i) { if (enable[i]) { if ( CornerPinOverlayInteractPrivate::isNearby(pos, p[i].x, p[i].y, CornerPinOverlayInteractPrivate::pointTolerance(), pscale) ) { _imp->dragging = i; didSomething = true; } _imp->toDrag[i] = to[i]; _imp->fromDrag[i] = from[i]; _imp->enableDrag[i] = enable[i]; } } _imp->interactiveDrag = _imp->getInteractive(); _imp->useFromDrag = useFrom; _imp->lastPenPos = pos; return didSomething; } // onOverlayPenDown
void CornerPinOverlayInteract::drawOverlay(TimeValue time, const RenderScale & /*renderScale*/, ViewIdx /*view*/) { // do not show interact if knob is secret or not enabled // see https://github.com/MrKepzie/Natron/issues/932 KnobDoublePtr from1Knob = _imp->from[0].lock(); if ( !from1Knob || !from1Knob->shouldDrawOverlayInteract() ) { return; } OfxRGBColourD color; if ( !getOverlayColor(color.r, color.g, color.b) ) { color.r = color.g = color.b = 0.8; } RenderScale pscale; getPixelScale(pscale.x, pscale.y); OfxPointD to[4]; OfxPointD from[4]; bool enable[4]; bool useFrom; if (_imp->dragging == -1) { for (int i = 0; i < 4; ++i) { _imp->getFrom(time, i, &from[i].x, &from[i].y); _imp->getTo(time, i, &to[i].x, &to[i].y); enable[i] = _imp->getEnabled(time, i); } useFrom = _imp->getUseFromPoints(time); } else { for (int i = 0; i < 4; ++i) { to[i] = _imp->toDrag[i]; from[i] = _imp->fromDrag[i]; enable[i] = _imp->enableDrag[i]; } useFrom = _imp->useFromDrag; } if (!useFrom && !_imp->areToPointsAnimated()) { return; } OfxPointD p[4]; OfxPointD q[4]; int enableBegin = 4; int enableEnd = 0; for (int i = 0; i < 4; ++i) { if (enable[i]) { if (useFrom) { p[i] = from[i]; q[i] = to[i]; } else { q[i] = from[i]; p[i] = to[i]; } if (i < enableBegin) { enableBegin = i; } if (i + 1 > enableEnd) { enableEnd = i + 1; } } } double w, h; getViewportSize(w, h); GLdouble projection[16]; GL_GPU::GetDoublev( GL_PROJECTION_MATRIX, projection); OfxPointD shadow; // how much to translate GL_PROJECTION to get exactly one pixel on screen shadow.x = 2. / (projection[0] * w); shadow.y = 2. / (projection[5] * h); //glPushAttrib(GL_ALL_ATTRIB_BITS); // caller is responsible for protecting attribs //glDisable(GL_LINE_STIPPLE); GL_GPU::Enable(GL_LINE_SMOOTH); //glEnable(GL_POINT_SMOOTH); GL_GPU::Enable(GL_BLEND); GL_GPU::Hint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE); GL_GPU::LineWidth(1.5f); GL_GPU::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_GPU::PointSize( CornerPinOverlayInteractPrivate::pointSize() ); // Draw everything twice // l = 0: shadow // l = 1: drawing for (int l = 0; l < 2; ++l) { // shadow (uses GL_PROJECTION) GL_GPU::MatrixMode(GL_PROJECTION); int direction = (l == 0) ? 1 : -1; // translate (1,-1) pixels GL_GPU::Translated(direction * shadow.x, -direction * shadow.y, 0); GL_GPU::MatrixMode(GL_MODELVIEW); // Modelview should be used on Nuke GL_GPU::Color3f( (float)(color.r / 2) * l, (float)(color.g / 2) * l, (float)(color.b / 2) * l ); GL_GPU::Begin(GL_LINES); for (int i = enableBegin; i < enableEnd; ++i) { if (enable[i]) { GL_GPU::Vertex2d(p[i].x, p[i].y); GL_GPU::Vertex2d(q[i].x, q[i].y); } } GL_GPU::End(); GL_GPU::Color3f( (float)color.r * l, (float)color.g * l, (float)color.b * l ); GL_GPU::Begin(GL_LINE_LOOP); for (int i = enableBegin; i < enableEnd; ++i) { if (enable[i]) { GL_GPU::Vertex2d(p[i].x, p[i].y); } } GL_GPU::End(); GL_GPU::Begin(GL_POINTS); for (int i = enableBegin; i < enableEnd; ++i) { if (enable[i]) { if ( (_imp->hovering == i) || (_imp->dragging == i) ) { GL_GPU::Color3f(0.f * l, 1.f * l, 0.f * l); } else { GL_GPU::Color3f( (float)color.r * l, (float)color.g * l, (float)color.b * l ); } GL_GPU::Vertex2d(p[i].x, p[i].y); } } GL_GPU::End(); for (int i = enableBegin; i < enableEnd; ++i) { if (enable[i]) { std::string text = useFrom ? _imp->from[i].lock()->getName().c_str() : _imp->to[i].lock()->getName().c_str() ; getLastCallingViewport()->renderText(p[i].x, p[i].y, text, color.r * l , color.g * l, color.b * l, 1); } } } //glPopAttrib(); } // drawOverlay
/** @brief ctor */ FocusArgs::FocusArgs( const PropertySet& props ) : InteractArgs( props ) { pixelScale = getPixelScale( props ); backGroundColour = getBackgroundColour( props ); }
bool PointOverlayInteract::onOverlayPenMotion(TimeValue time, const RenderScale & /*renderScale*/, ViewIdx view, const QPointF & /*viewportPos*/, const QPointF & penPos, double /*pressure*/, TimeValue /*timestamp*/) { KnobDoublePtr knob = _imp->param.lock(); // do not show interact if knob is secret or not enabled // see https://github.com/MrKepzie/Natron/issues/932 if ( !knob || !knob->shouldDrawOverlayInteract() ) { return false; } RenderScale pscale; getPixelScale(pscale.x, pscale.y); QPointF pos; if (_imp->state == ePositionInteractStatePicked) { pos = _imp->lastPenPos; } else { double p[2]; for (int i = 0; i < 2; ++i) { p[i] = knob->getValueAtTime(time, DimIdx(i)); if (knob->getValueIsNormalized(DimIdx(i)) != eValueIsNormalizedNone) { p[i] = knob->denormalize(DimIdx(i), time, p[i]); } } pos.setX(p[0]); pos.setY(p[1]); } bool didSomething = false; bool valuesChanged = false; switch (_imp->state) { case ePositionInteractStateInactive: case ePositionInteractStatePoised: { // are we in the box, become 'poised' PositionInteractState newState; if ( ( std::fabs( penPos.x() - pos.x() ) <= _imp->pointTolerance() * pscale.x) && ( std::fabs( penPos.y() - pos.y() ) <= _imp->pointTolerance() * pscale.y) ) { newState = ePositionInteractStatePoised; } else { newState = ePositionInteractStateInactive; } if (_imp->state != newState) { // state changed, must redraw redraw(); } _imp->state = newState; //} break; } case ePositionInteractStatePicked: { valuesChanged = true; break; } } didSomething = (_imp->state == ePositionInteractStatePoised) || (_imp->state == ePositionInteractStatePicked); if ( (_imp->state != ePositionInteractStateInactive) && _imp->interactiveDrag && valuesChanged ) { std::vector<double> p(2); p[0] = fround(_imp->lastPenPos.x(), pscale.x); p[1] = fround(_imp->lastPenPos.y(), pscale.y); for (int i = 0; i < 2; ++i) { if (knob->getValueIsNormalized(DimIdx(i)) != eValueIsNormalizedNone) { p[i] = knob->normalize(DimIdx(i), time, p[i]); } } knob->setValueAcrossDimensions(p, DimIdx(0), ViewSetSpec(view), eValueChangedReasonUserEdited); } _imp->lastPenPos = penPos; return (didSomething || valuesChanged); } // onOverlayPenMotion
void PointOverlayInteract::drawOverlay(TimeValue time, const RenderScale & /*renderScale*/, ViewIdx /*view*/) { KnobDoublePtr knob = _imp->param.lock(); // do not show interact if knob is secret or not enabled // see https://github.com/MrKepzie/Natron/issues/932 if ( !knob || !knob->shouldDrawOverlayInteract()) { return; } ColorRgba<double> color; if ( !getOverlayColor(color.r, color.g, color.b) ) { color.r = color.g = color.b = 0.8; } RenderScale pscale; getPixelScale(pscale.x, pscale.y); float pR = 1.f; float pG = 1.f; float pB = 1.f; switch (_imp->state) { case ePositionInteractStateInactive: pR = (float)color.r; pG = (float)color.g; pB = (float)color.b; break; case ePositionInteractStatePoised: pR = 0.f; pG = 1.0f; pB = 0.0f; break; case ePositionInteractStatePicked: pR = 0.f; pG = 1.0f; pB = 0.0f; break; } QPointF pos; if (_imp->state == ePositionInteractStatePicked) { pos = _imp->lastPenPos; } else { double p[2]; for (int i = 0; i < 2; ++i) { p[i] = knob->getValueAtTime(time, DimIdx(i)); if (knob->getValueIsNormalized(DimIdx(i)) != eValueIsNormalizedNone) { p[i] = knob->denormalize(DimIdx(i), time, p[i]); } } pos.setX(p[0]); pos.setY(p[1]); } //glPushAttrib(GL_ALL_ATTRIB_BITS); // caller is responsible for protecting attribs GL_GPU::PointSize( (GLfloat)_imp->pointSize() ); // Draw everything twice // l = 0: shadow // l = 1: drawing double w, h; getViewportSize(w, h); GLdouble projection[16]; GL_GPU::GetDoublev( GL_PROJECTION_MATRIX, projection); OfxPointD shadow; // how much to translate GL_PROJECTION to get exactly one pixel on screen shadow.x = 2. / (projection[0] * w); shadow.y = 2. / (projection[5] * h); int fmHeight = getLastCallingViewport()->getWidgetFontHeight(); for (int l = 0; l < 2; ++l) { // shadow (uses GL_PROJECTION) GL_GPU::MatrixMode(GL_PROJECTION); int direction = (l == 0) ? 1 : -1; // translate (1,-1) pixels GL_GPU::Translated(direction * shadow.x, -direction * shadow.y, 0); GL_GPU::MatrixMode(GL_MODELVIEW); // Modelview should be used on Nuke GL_GPU::Color3f(pR * l, pG * l, pB * l); GL_GPU::Begin(GL_POINTS); GL_GPU::Vertex2d( pos.x(), pos.y() ); GL_GPU::End(); getLastCallingViewport()->renderText(pos.x(), pos.y() - ( fmHeight + _imp->pointSize() ) * pscale.y, knob->getOriginalName(), pR*l, pG*l, pB*l, 1.); } } // drawOverlay