TVectorImageP MyInbetweener::tween(double t) { TVectorImageP vi = m_vi0->clone(); int n = tmin(m_vi0->getStrokeCount(), m_vi1->getStrokeCount()); for (int i = 0; i < n; i++) { TStroke *stroke0 = m_vi0->getStroke(i); TStroke *stroke1 = m_vi1->getStroke(i); TStroke *stroke = vi->getStroke(i); int m = tmin(stroke0->getControlPointCount(), stroke1->getControlPointCount()); for (int j = 0; j < m; j++) { TThickPoint p0 = stroke0->getControlPoint(j); TThickPoint p1 = stroke1->getControlPoint(j); TThickPoint p = (1 - t) * p0 + t * p1; stroke->setControlPoint(j, p); } /* for(int j=2;j+2<m;j+=2) { TThickPoint p0 = stroke0->getControlPoint(j-2); TThickPoint p1 = stroke0->getControlPoint(j-1); TThickPoint p2 = stroke0->getControlPoint(j); TThickPoint p3 = stroke0->getControlPoint(j+1); TThickPoint p4 = stroke0->getControlPoint(j+2); if(tdistance2(p0,p1)<0.001 && tdistance2(p3,p4)<0.001) { p2 = 0.5*(p1+p2); stroke->setControlPoint(j,p2); } } */ } return vi; }
void doClose(double t, const TImageP &img, const TVectorImageP &firstImage, const TVectorImageP &lastImage) { if (t == 0) applyAutoclose(img, TRectD(), firstImage->getStroke(0)); else if (t == 1) applyAutoclose(img, TRectD(), lastImage->getStroke(0)); else { assert(firstImage->getStrokeCount() == 1); assert(lastImage->getStrokeCount() == 1); TVectorImageP vi = TInbetween(firstImage, lastImage).tween(t); assert(vi->getStrokeCount() == 1); applyAutoclose(img, TRectD(), vi->getStroke(0)); } }
TStroke *PinchTool::getClosestStroke(const TPointD &pos, double &w) const { TVectorImageP vi = TImageP(getImage(false)); if (!vi) return 0; double dist = 0; UINT index; if (vi->getNearestStroke(pos, w, index, dist, true)) return vi->getStroke(index); else return 0; }
void StrokeSelection::paste() { TTool *tool = TTool::getApplication()->getCurrentTool()->getTool(); if (!tool) return; if (TTool::getApplication()->getCurrentObject()->isSpline()) { const StrokesData *stData = dynamic_cast<const StrokesData *>( QApplication::clipboard()->mimeData()); if (!stData) return; TVectorImageP splineImg = tool->getImage(true); TVectorImageP img = stData->m_image; if (!splineImg || !img) return; QMutexLocker lock(splineImg->getMutex()); TUndo *undo = new ToolUtils::UndoPath( tool->getXsheet()->getStageObject(tool->getObjectId())->getSpline()); while (splineImg->getStrokeCount() > 0) splineImg->deleteStroke(0); TStroke *stroke = img->getStroke(0); splineImg->addStroke(new TStroke(*stroke), false); TUndoManager::manager()->add(undo); tool->notifyImageChanged(); tool->invalidate(); return; } TVectorImageP tarImg = tool->touchImage(); if (!tarImg) return; TPaletteP palette = tarImg->getPalette(); TPaletteP oldPalette = new TPalette(); if (palette) oldPalette = palette->clone(); bool isPaste = pasteStrokesWithoutUndo(tarImg, m_indexes, m_sceneHandle); if (isPaste) { TXshSimpleLevel *level = TTool::getApplication()->getCurrentLevel()->getSimpleLevel(); TUndoManager::manager()->add(new PasteStrokesUndo( level, tool->getCurrentFid(), m_indexes, oldPalette, m_sceneHandle)); m_updateSelectionBBox = isPaste; } tool->notifyImageChanged(); tool->getApplication() ->getPaletteController() ->getCurrentLevelPalette() ->notifyPaletteChanged(); m_updateSelectionBBox = false; tool->invalidate(); }
//!Converts a TVectorImage into a TRasterImage. The input vector image //!is transformed through the passed affine \b aff, and put into a //!TRasterImage strictly covering the bounding box of the transformed //!vector image. The output image has its lower-left position in the //!world reference specified by the \b pos parameter, which is granted to //!be an integer displacement of the passed value. Additional parameters //!include an integer \b enlarge by which the output image is enlarged with //!respect to the transformed image's bbox, and the bool \b transformThickness //!to specify whether the transformation should involve strokes' thickensses //!or not. TRasterImageP TRasterImageUtils::vectorToFullColorImage( const TVectorImageP &vimage, const TAffine &aff, TPalette *palette, const TPointD &outputPos, const TDimension &outputSize, const std::vector<TRasterFxRenderDataP> *fxs, bool transformThickness) { if (!vimage || !palette) return 0; //Transform the vector image through aff TVectorImageP vi = vimage->clone(); vi->transform(aff, transformThickness); //Allocate the output ToonzImage TRaster32P raster(outputSize.lx, outputSize.ly); raster->clear(); TRasterImageP ri(raster); ri->setPalette(palette->clone()); //Shift outputPos to the origin vi->transform(TTranslation(-outputPos)); int strokeCount = vi->getStrokeCount(); std::vector<int> strokeIndex(strokeCount); std::vector<TStroke *> strokes(strokeCount); int i; for (i = 0; i < strokeCount; ++i) { strokeIndex[i] = i; strokes[i] = vi->getStroke(i); } vi->notifyChangedStrokes(strokeIndex, strokes); int maxStyleId = palette->getStyleCount() - 1; for (i = 0; i < (int)vi->getRegionCount(); ++i) { TRegion *region = vi->getRegion(i); fastAddPaintRegion(ri, region, tmin(maxStyleId, region->getStyle()), maxStyleId); } set<int> colors; if (fxs) { for (i = 0; i < (int)fxs->size(); i++) { SandorFxRenderData *sandorData = dynamic_cast<SandorFxRenderData *>((*fxs)[i].getPointer()); if (sandorData && sandorData->m_type == BlendTz) { std::string indexes = toString(sandorData->m_blendParams.m_colorIndex); std::vector<std::string> items; parseIndexes(indexes, items); PaletteFilterFxRenderData paletteFilterData; insertIndexes(items, &paletteFilterData); colors = paletteFilterData.m_colors; break; } } } for (i = 0; i < strokeCount; ++i) { TStroke *stroke = vi->getStroke(i); bool visible = false; int styleId = stroke->getStyle(); TColorStyleP style = palette->getStyle(styleId); assert(style); int colorCount = style->getColorParamCount(); if (colorCount == 0) visible = true; else { visible = false; for (int j = 0; j < style->getColorParamCount() && !visible; j++) { TPixel32 color = style->getColorParamValue(j); if (color.m != 0) visible = true; } } if (visible) fastAddInkStroke(ri, stroke, TRectD(), 1, true); } return ri; }
void MyInbetweener::stabilizeSegments(TVectorImageP &image) { for (int i = 0; i < image->getStrokeCount(); i++) stabilizeSegments(image->getStroke(i)); }
void VectorBrushProp::draw(const TVectorRenderData &rd) { //Ensure that the stroke overlaps our clipping rect if (rd.m_clippingRect != TRect() && !rd.m_is3dView && !convert(rd.m_aff * m_stroke->getBBox()).overlaps(rd.m_clippingRect)) return; TPaletteP palette(m_brush->getPalette()); if (!palette) return; static TOutlineUtil::OutlineParameter param; //unused, but requested //Build a solid color style to draw each m_vi's stroke with. TSolidColorStyle colorStyle; //Push the specified rd affine before drawing glPushMatrix(); tglMultMatrix(rd.m_aff); //1. If necessary, build the outlines double currentPixelSize = sqrt(tglGetPixelSize2()); bool differentPixelSize = !isAlmostZero(currentPixelSize - m_pixelSize, 1e-5); m_pixelSize = currentPixelSize; int i, viRegionsCount = m_brush->getRegionCount(), viStrokesCount = m_brush->getStrokeCount(); if (differentPixelSize || m_strokeChanged) { m_strokeChanged = false; //1a. First, the regions m_regionOutlines.resize(viRegionsCount); for (i = 0; i < viRegionsCount; ++i) { TRegionOutline &outline = m_regionOutlines[i]; const TRegion *brushRegion = m_brush->getRegion(i); //Build the outline outline.clear(); TOutlineUtil::makeOutline(*getStroke(), *brushRegion, m_brushBox, outline); } //1b. Then, the strokes m_strokeOutlines.resize(viStrokesCount); for (i = 0; i < viStrokesCount; ++i) { TStrokeOutline &outline = m_strokeOutlines[i]; const TStroke *brushStroke = m_brush->getStroke(i); outline.getArray().clear(); TOutlineUtil::makeOutline(*getStroke(), *brushStroke, m_brushBox, outline, param); } } //2. Draw the outlines UINT s, t, r, strokesCount = m_brush->getStrokeCount(), regionCount = m_brush->getRegionCount(); for (s = 0; s < strokesCount; s = t) //Each cycle draws a group { //A vector image stores group strokes with consecutive indices. //2a. First, draw regions in the strokeIdx-th stroke's group for (r = 0; r < regionCount; ++r) { if (m_brush->sameGroupStrokeAndRegion(s, r)) { const TRegion *brushRegion = m_brush->getRegion(r); const TColorStyle *brushStyle = palette->getStyle(brushRegion->getStyle()); assert(brushStyle); //Draw the outline colorStyle.setMainColor(brushStyle->getMainColor()); colorStyle.drawRegion(0, false, m_regionOutlines[r]); } } //2b. Then, draw all strokes in strokeIdx-th stroke's group for (t = s; t < strokesCount && m_brush->sameGroup(s, t); ++t) { const TStroke *brushStroke = m_brush->getStroke(t); const TColorStyle *brushStyle = palette->getStyle(brushStroke->getStyle()); if (!brushStyle) continue; colorStyle.setMainColor(brushStyle->getMainColor()); colorStyle.drawStroke(0, &m_strokeOutlines[t], brushStroke); //brushStroke unused but requested } } glPopMatrix(); }
void leftButtonUp(const TPointD &, const TMouseEvent &) { if (!m_active) return; m_active = false; m_pointAtMouseDown = m_pointAtMove = TConsts::napd; TStroke *ref; TVectorImageP vi = TImageP(getImage(true)); if (!vi) return; QMutexLocker lock(vi->getMutex()); UINT i, j; for (i = 0; i < m_strokeHit.size(); ++i) { ref = m_strokeHit[i]; ref->enableComputeOfCaches(); ref->reduceControlPoints(getPixelSize() * ReduceControlPointCorrection, *(m_hitStrokeCorners[i])); // vi->validateRegionEdges(ref, false); } clearPointerContainer(m_hitStrokeCorners); m_hitStrokeCorners.clear(); UINT count = 0; for (i = 0; i < m_strokeToModify.size(); ++i) { // recupero la stroke collection MagnetTool::strokeCollection &sc = m_strokeToModify[i]; for (j = 0; j < sc.m_splittedToMove.size(); ++j) { ref = sc.m_splittedToMove[j]; ref->enableComputeOfCaches(); ref->reduceControlPoints(getPixelSize() * ReduceControlPointCorrection, *(m_strokeToModifyCorners[count++])); } // ricostruisco una stroke con quella data ref = merge(sc.m_splitted); if (sc.m_parent->isSelfLoop()) { int cpCount = ref->getControlPointCount(); TThickPoint p1 = ref->getControlPoint(0); TThickPoint p2 = ref->getControlPoint(cpCount - 1); TThickPoint midP = (p1 + p2) * 0.5; ref->setControlPoint(0, midP); ref->setControlPoint(cpCount - 1, midP); ref->setSelfLoop(true); } sc.m_parent->swapGeometry(*ref); delete ref; // elimino la curva temporanea clearPointerContainer(sc.m_splitted); // pulisco le stroke trovate con lo split sc.m_splittedToMove.clear(); // pulisco il contenitore ( le stroke // che erano contenute qua sono state // eliminate nella clearPointer.... } clearPointerContainer(m_strokeToModifyCorners); m_strokeToModifyCorners.clear(); for (i = 0; i < vi->getStrokeCount(); ++i) { ref = vi->getStroke(i); ref->invalidate(); } vi->notifyChangedStrokes(m_changedStrokes, m_oldStrokesArray); notifyImageChanged(); if (m_undo) TUndoManager::manager()->add(m_undo); m_undo = 0; clearPointerContainer(m_oldStrokesArray); m_oldStrokesArray.clear(); invalidate(); };
void leftButtonDown(const TPointD &pos, const TMouseEvent &e) { TPointD p(pos); m_oldPos = pos; m_pointAtMouseDown = p; m_startingPos = p; m_active = false; TVectorImageP vi = TImageP(getImage(true)); if (!vi) return; QMutexLocker lock(vi->getMutex()); m_active = true; m_pointAtMove = m_pointAtMouseDown = p; m_strokeHit.clear(); m_changedStrokes.clear(); m_strokeToModify.clear(); std::vector<TStroke *> strokeUndo; TStroke *ref; m_hitStrokeCorners.clear(); m_strokeToModifyCorners.clear(); UINT i = 0; for (; i < vi->getStrokeCount(); ++i) { if (!vi->inCurrentGroup(i)) continue; TStroke *stroke = vi->getStroke(i); ref = stroke; // calcola le intersezioni std::vector<double> intersections; intersect(*ref, p, m_pointSize, intersections); if (intersections.empty()) { if (increaseControlPoints(*ref, TStrokePointDeformation(p, m_pointSize))) { m_changedStrokes.push_back(i); m_strokeHit.push_back(ref); std::vector<int> *corners = new std::vector<int>; corners->push_back(0); detectCorners(ref, 20, *corners); corners->push_back(ref->getChunkCount()); m_hitStrokeCorners.push_back(corners); ref->disableComputeOfCaches(); strokeUndo.push_back(ref); } } else { strokeUndo.push_back(ref); MagnetTool::strokeCollection sc; sc.m_parent = ref; splitStroke(*sc.m_parent, intersections, sc.m_splitted); selectStrokeToMove(sc.m_splitted, p, m_pointSize, sc.m_splittedToMove); for (UINT ii = 0; ii < sc.m_splittedToMove.size(); ++ii) { TStroke *temp = sc.m_splittedToMove[ii]; bool test = increaseControlPoints(*temp, TStrokePointDeformation(p, m_pointSize)); assert(test); std::vector<int> *corners = new std::vector<int>; corners->push_back(0); detectCorners(temp, 20, *corners); corners->push_back(temp->getChunkCount()); m_strokeToModifyCorners.push_back(corners); } m_strokeToModify.push_back(sc); m_changedStrokes.push_back(i); } } m_oldStrokesArray.resize(m_changedStrokes.size()); for (i = 0; i < m_changedStrokes.size(); i++) m_oldStrokesArray[i] = new TStroke(*(vi->getStroke(m_changedStrokes[i]))); if (!strokeUndo.empty()) { if (TTool::getApplication()->getCurrentObject()->isSpline()) m_undo = new UndoPath(getXsheet()->getStageObject(getObjectId())->getSpline()); else { TXshSimpleLevel *sl = TTool::getApplication()->getCurrentLevel()->getSimpleLevel(); assert(sl); TFrameId id = getCurrentFid(); m_undo = new UndoModifyListStroke(sl, id, strokeUndo); } } invalidate(); // vi->validateRegionEdges(ref, true); };
void PinchTool::leftButtonDown(const TPointD &pos, const TMouseEvent &event) { m_curr = m_down = pos; if (!m_active && !m_selector.isSelected()) { m_active = false; assert(m_undo == 0); StrokeDeformation * deformation = m_deformation; TVectorImageP vi = TImageP(getImage(true)); if (!vi) return; m_active = true; ContextStatus *status = &m_status; // reset status status->init(); double w, dist2; // find nearest stroke if (vi->getNearestStroke(m_down, w, m_n, dist2, true)) { TStroke *stroke = vi->getStroke(m_n); assert(stroke && "Not valid stroke found!!!"); if (!stroke) return; updateStrokeStatus(stroke, w); // set parameters from sliders updateInterfaceStatus(event); deformation->activate(status); // stroke can be changed (replaced by another) during deformation activate if (TTool::getApplication()->getCurrentObject()->isSpline()) m_undo = new ToolUtils::UndoPath(getXsheet()->getStageObject(getObjectId())->getSpline()); else { TXshSimpleLevel *sl = TTool::getApplication()->getCurrentLevel()->getSimpleLevel(); assert(sl); TFrameId id = getCurrentFid(); m_undo = new UndoModifyStrokeAndPaint(sl, id, m_n); } } } m_selector.mouseDown(m_curr); m_prev = m_curr; invalidate(); }