bool getInverted(TimeValue time) const { KnobBoolPtr knob = invert.lock(); if (!knob) { return false; } return knob->getValueAtTime(time); }
bool getEnabled(TimeValue time, int index) const { KnobBoolPtr knob = enable[index].lock(); if (!knob) { return true; } return knob->getValueAtTime(time); }
bool RotoShapeRenderNodePrivate::renderStroke_generic(RenderStrokeDataPtr userData, PFNRenderStrokeBeginRender beginCallback, PFNRenderStrokeRenderDot renderDotCallback, PFNRenderStrokeEndRender endCallback, const std::list<std::list<std::pair<Point, double> > >& strokes, const double distToNextIn, const Point& lastCenterPointIn, const RotoDrawableItemPtr& stroke, bool doBuildup, double opacity, TimeValue time, ViewIdx /*view*/, const RenderScale& scale, double* distToNextOut, Point* lastCenterPoint) { assert(distToNextOut && lastCenterPoint); *distToNextOut = 0; double brushSize, brushSizePixelX, brushSizePixelY, brushSpacing, brushHardness, writeOnStart, writeOnEnd; bool pressureAffectsOpacity, pressureAffectsHardness, pressureAffectsSize; { KnobDoublePtr brushSizeKnob = stroke->getBrushSizeKnob(); brushSize = brushSizeKnob->getValueAtTime(time); KnobDoublePtr brushSpacingKnob = stroke->getBrushSpacingKnob(); brushSpacing = brushSpacingKnob->getValueAtTime(time); if (brushSpacing == 0.) { return false; } brushSpacing = std::max(brushSpacing, 0.05); KnobDoublePtr brushHardnessKnob = stroke->getBrushHardnessKnob(); brushHardness = brushHardnessKnob->getValueAtTime(time); KnobDoublePtr visiblePortionKnob = stroke->getBrushVisiblePortionKnob(); writeOnStart = visiblePortionKnob->getValueAtTime(time); writeOnEnd = visiblePortionKnob->getValueAtTime(time, DimIdx(1)); if ( (writeOnEnd - writeOnStart) <= 0. ) { return false; } // This function is also used for opened bezier which do not have pressure. RotoStrokeItemPtr isStroke = toRotoStrokeItem(stroke); if (!isStroke) { pressureAffectsOpacity = false; pressureAffectsSize = false; pressureAffectsHardness = false; } else { KnobBoolPtr pressureOpacityKnob = isStroke->getPressureOpacityKnob(); KnobBoolPtr pressureSizeKnob = isStroke->getPressureSizeKnob(); KnobBoolPtr pressureHardnessKnob = isStroke->getPressureHardnessKnob(); pressureAffectsOpacity = pressureOpacityKnob->getValueAtTime(time); pressureAffectsSize = pressureSizeKnob->getValueAtTime(time); pressureAffectsHardness = pressureHardnessKnob->getValueAtTime(time); } brushSizePixelX = brushSize; brushSizePixelY = brushSizePixelX; brushSizePixelX = std::max( 1., brushSizePixelX * scale.x); brushSizePixelY = std::max( 1., brushSizePixelY * scale.y); } double distToNext = distToNextIn; bool hasRenderedDot = false; beginCallback(userData, brushSizePixelX, brushSizePixelY, brushSpacing, brushHardness, pressureAffectsOpacity, pressureAffectsHardness, pressureAffectsSize, doBuildup, opacity); *lastCenterPoint = lastCenterPointIn; Point prevCenter = lastCenterPointIn; for (std::list<std::list<std::pair<Point, double> > >::const_iterator strokeIt = strokes.begin(); strokeIt != strokes.end(); ++strokeIt) { int firstPoint = (int)std::floor( (strokeIt->size() * writeOnStart) ); int endPoint = (int)std::ceil( (strokeIt->size() * writeOnEnd) ); assert( firstPoint >= 0 && firstPoint < (int)strokeIt->size() && endPoint > firstPoint && endPoint <= (int)strokeIt->size() ); ///The visible portion of the paint's stroke with points adjusted to pixel coordinates std::list<std::pair<Point, double> > visiblePortion; std::list<std::pair<Point, double> >::const_iterator startingIt = strokeIt->begin(); std::list<std::pair<Point, double> >::const_iterator endingIt = strokeIt->begin(); std::advance(startingIt, firstPoint); std::advance(endingIt, endPoint); for (std::list<std::pair<Point, double> >::const_iterator it = startingIt; it != endingIt; ++it) { visiblePortion.push_back(*it); } if ( visiblePortion.empty() ) { continue; } std::list<std::pair<Point, double> >::iterator it = visiblePortion.begin(); if (visiblePortion.size() == 1) { double spacing; *lastCenterPoint = it->first; renderDotCallback(userData, prevCenter, *lastCenterPoint, it->second, &spacing); distToNext += spacing; continue; } //prevCenter = it->first; std::list<std::pair<Point, double> >::iterator next = it; ++next; while ( next != visiblePortion.end() ) { //Render for each point a dot. Spacing is a percentage of brushSize: //Spacing at 1 means no dot is overlapping another (so the spacing is in fact brushSize) //Spacing at 0 we do not render the stroke double dx = next->first.x - it->first.x; double dy = next->first.y - it->first.y; // This is the distance between the current and next discretized points // Since the distance between each points may vary, we uniformly position a dot along the segments double dist = std::sqrt(dx * dx + dy * dy); // while the next point can be drawn on this segment, draw a point and advance while (distToNext <= dist) { double a = dist == 0. ? 0. : distToNext / dist; lastCenterPoint->x = it->first.x * (1 - a) + next->first.x * a; lastCenterPoint->y = it->first.y * (1 - a) + next->first.y * a; double pressure = it->second * (1 - a) + next->second * a; // draw the dot double spacing; bool rendered = renderDotCallback(userData, prevCenter, *lastCenterPoint, pressure, &spacing); hasRenderedDot |= rendered; prevCenter = *lastCenterPoint; distToNext += spacing; /*if (rendered) { } else { break; }*/ } // go to the next segment distToNext -= dist; ++next; ++it; } } endCallback(userData); *distToNextOut = distToNext; return hasRenderedDot; }