diff --git a/toonz/sources/include/tools/stylepicker.h b/toonz/sources/include/tools/stylepicker.h index b5381bb..d48b29d 100644 --- a/toonz/sources/include/tools/stylepicker.h +++ b/toonz/sources/include/tools/stylepicker.h @@ -57,14 +57,15 @@ public: /*-- (StylePickerTool内で)LineとAreaを切り替えてPickできる。mode: 0=Area, * 1=Line, 2=Line&Areas(default) --*/ - int pickStyleId(const TPointD &point, double radius2 = 1, int mode = 2) const; + int pickStyleId(const TPointD &point, double radius, double scale2, + int mode = 2) const; /*--- Toonz Raster LevelのToneを拾う。 ---*/ int pickTone(const TPointD &pos) const; // per pli come sopra, ma ritorna il maincolor // per tzp e fullcolor ritorna il colore effettivo del pixel - TPixel32 pickColor(const TPointD &point, double radius2 = 1) const; + TPixel32 pickColor(const TPointD &point, double radius, double scale2) const; TPixel32 pickAverageColor(const TRectD &rect) const; // ritorna il colore medio presente nell'area della finestra corrente openGL diff --git a/toonz/sources/include/tools/tool.h b/toonz/sources/include/tools/tool.h index 8ce93ed..fedac8e 100644 --- a/toonz/sources/include/tools/tool.h +++ b/toonz/sources/include/tools/tool.h @@ -466,8 +466,9 @@ return true if the method execution can have changed the current tool const TAffine &getMatrix() const { return m_matrix; } void setMatrix(const TAffine &matrix) { m_matrix = matrix; } - TAffine getCurrentColumnMatrix() + TAffine getCurrentColumnMatrix(int frame = -1) const; //!< Returns the current column matrix transformation. + //! if frame = -1 then it uses the current frame //! \sa TXsheet::getPlacement. TAffine getCurrentColumnParentMatrix() @@ -480,9 +481,10 @@ return true if the method execution can have changed the current tool Returns the matrix transformation of the stage object with column index equal to \p index and frame as the current frame. + if frame = -1 then it uses the current frame \sa TXsheet::getPlacement. */ - TAffine getColumnMatrix(int index) const; + TAffine getColumnMatrix(int index, int frame = -1) const; /*! Updates the current matrix transformation with the actual column matrix diff --git a/toonz/sources/include/toonz/stagevisitor.h b/toonz/sources/include/toonz/stagevisitor.h index f5cbdf4..0baf5a9 100644 --- a/toonz/sources/include/toonz/stagevisitor.h +++ b/toonz/sources/include/toonz/stagevisitor.h @@ -295,14 +295,16 @@ class DVAPI Picker final : public Visitor { TPointD m_point; TAffine m_viewAff; double m_minDist2; + int m_devPixRatio; int m_currentColumnIndex = -1; public: Picker(const TAffine &viewAff, const TPointD &p, - const ImagePainter::VisualSettings &vs); + const ImagePainter::VisualSettings &vs, int devPixRatio = 1); - void setDistance(double d); + // minimum distance to pick thin vector strokes. + void setMinimumDistance(double d); void onImage(const Stage::Player &data) override; void beginMask() override; diff --git a/toonz/sources/tnztools/controlpointeditortool.cpp b/toonz/sources/tnztools/controlpointeditortool.cpp index 6e56dfe..45b1849 100644 --- a/toonz/sources/tnztools/controlpointeditortool.cpp +++ b/toonz/sources/tnztools/controlpointeditortool.cpp @@ -576,8 +576,7 @@ void ControlPointEditorTool::leftButtonDown(const TPointD &pos, if (m_autoSelectDrawing.getValue()) { // Non sono in nessun gadget std::vector columnIndexes; - getViewer()->posToColumnIndexes(e.m_pos, columnIndexes, - getPixelSize() * 5, false); + getViewer()->posToColumnIndexes(e.m_pos, columnIndexes, 5.0, false); getNearestStrokeColumnIndexes(columnIndexes, pos); if (!columnIndexes.empty()) { int currentColumnIndex = app->getCurrentColumn()->getColumnIndex(); diff --git a/toonz/sources/tnztools/edittool.cpp b/toonz/sources/tnztools/edittool.cpp index 2d9b0b3..c9055c1 100644 --- a/toonz/sources/tnztools/edittool.cpp +++ b/toonz/sources/tnztools/edittool.cpp @@ -1053,9 +1053,8 @@ void EditTool::onEditAllLeftButtonDown(TPointD &pos, const TMouseEvent &e) { m_what = selectedDevice >= 0 ? selectedDevice : Translation; if (selectedDevice < 0 && m_autoSelect.getValue() != L"None") { - pos = getMatrix() * pos; - int columnIndex = - getViewer()->posToColumnIndex(e.m_pos, 5 * getPixelSize(), false); + pos = getMatrix() * pos; + int columnIndex = getViewer()->posToColumnIndex(e.m_pos, 5.0, false); if (columnIndex >= 0) { TStageObjectId id = TStageObjectId::ColumnId(columnIndex); int currentColumnIndex = getColumnIndex(); diff --git a/toonz/sources/tnztools/filltool.cpp b/toonz/sources/tnztools/filltool.cpp index ae35355..1cab85b 100644 --- a/toonz/sources/tnztools/filltool.cpp +++ b/toonz/sources/tnztools/filltool.cpp @@ -1584,6 +1584,8 @@ void AreaFillTool::onEnter() { // getApplication()->editImage(); } +bool descending(int i, int j) { return (i > j); } + } // namespace //============================================================================= @@ -2165,14 +2167,30 @@ void FillTool::draw() { //----------------------------------------------------------------------------- -int FillTool::pick(const TImageP &image, const TPointD &pos) { +int FillTool::pick(const TImageP &image, const TPointD &pos, const int frame) { TToonzImageP ti = image; TVectorImageP vi = image; if (!ti && !vi) return 0; StylePicker picker(image); - double pixelSize2 = getPixelSize() * getPixelSize(); - return picker.pickStyleId(pos, pixelSize2); + double scale2 = 1.0; + if (vi) { + TAffine aff = getViewer()->getViewMatrix() * getCurrentColumnMatrix(frame); + scale2 = aff.det(); + } + TPointD pickPos = pos; + // in case that the column is animated in scene-editing mode + if (frame > 0) { + TPointD dpiScale = getViewer()->getDpiScale(); + pickPos.x *= dpiScale.x; + pickPos.y *= dpiScale.y; + TPointD worldPos = getCurrentColumnMatrix() * pickPos; + pickPos = getCurrentColumnMatrix(frame).inv() * worldPos; + pickPos.x /= dpiScale.x; + pickPos.y /= dpiScale.y; + } + // thin stroke can be picked with 10 pixel range + return picker.pickStyleId(pickPos, 10.0, scale2); } //----------------------------------------------------------------------------- @@ -2189,32 +2207,54 @@ int FillTool::pickOnionColor(const TPointD &pos) { if (!sl) return 0; std::vector rows; - osMask.getAll(sl->guessIndex(fid), rows); - - int i, j; - for (i = 0; i < (int)rows.size(); i++) - if (sl->index2fid(rows[i]) > fid) break; + // level editing case + if (app->getCurrentFrame()->isEditingLevel()) { + osMask.getAll(sl->guessIndex(fid), rows); + int i, j; + for (i = 0; i < (int)rows.size(); i++) + if (sl->index2fid(rows[i]) > fid) break; - int onionStyleId = 0; - for (j = i - 1; j >= 0; j--) { - TFrameId onionFid = sl->index2fid(rows[j]); - if (onionFid != fid && - ((onionStyleId = - pick(m_level->getFrame(onionFid, ImageManager::none, 1), pos)) > - 0)) // subsabling must be 1, otherwise onionfill does not work - break; - } - if (onionStyleId == 0) - for (j = i; j < (int)rows.size(); j++) { + int onionStyleId = 0; + for (j = i - 1; j >= 0; j--) { TFrameId onionFid = sl->index2fid(rows[j]); if (onionFid != fid && ((onionStyleId = pick(m_level->getFrame(onionFid, ImageManager::none, 1), pos)) > - 0)) // subsabling must be 1, otherwise onionfill does not work + 0)) // subsampling must be 1, otherwise onionfill does not work break; } - return onionStyleId; + if (onionStyleId == 0) + for (j = i; j < (int)rows.size(); j++) { + TFrameId onionFid = sl->index2fid(rows[j]); + if (onionFid != fid && + ((onionStyleId = pick( + m_level->getFrame(onionFid, ImageManager::none, 1), pos)) > + 0)) // subsampling must be 1, otherwise onionfill does not work + break; + } + return onionStyleId; + } else { // scene editing case + TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); + int colId = app->getCurrentColumn()->getColumnIndex(); + int row = app->getCurrentFrame()->getFrame(); + osMask.getAll(row, rows); + std::vector::iterator it = rows.begin(); + while (it != rows.end() && *it < row) it++; + std::sort(rows.begin(), it, descending); + int onionStyleId = 0; + for (int i = 0; i < (int)rows.size(); i++) { + if (rows[i] == row) continue; + TXshCell cell = xsh->getCell(rows[i], colId); + TXshLevel *xl = cell.m_level.getPointer(); + if (!xl || xl->getSimpleLevel() != sl) continue; + TFrameId onionFid = cell.getFrameId(); + onionStyleId = pick(m_level->getFrame(onionFid, ImageManager::none, 1), + pos, rows[i]); + if (onionStyleId > 0) break; + } + return onionStyleId; + } } //----------------------------------------------------------------------------- diff --git a/toonz/sources/tnztools/filltool.h b/toonz/sources/tnztools/filltool.h index 30ec357..32342b7 100644 --- a/toonz/sources/tnztools/filltool.h +++ b/toonz/sources/tnztools/filltool.h @@ -69,7 +69,7 @@ public: void onActivate(); void onEnter(); }; -} +} // namespace class FillTool final : public QObject, public TTool { // Q_DECLARE_TR_FUNCTIONS(FillTool) Q_OBJECT @@ -125,7 +125,8 @@ public: void onImageChanged() override; void draw() override; - int pick(const TImageP &image, const TPointD &pos); + // if frame = -1 it uses current frame + int pick(const TImageP &image, const TPointD &pos, const int frame = -1); int pickOnionColor(const TPointD &pos); void onEnter() override; diff --git a/toonz/sources/tnztools/shifttracetool.cpp b/toonz/sources/tnztools/shifttracetool.cpp index 120e5d4..785767c 100644 --- a/toonz/sources/tnztools/shifttracetool.cpp +++ b/toonz/sources/tnztools/shifttracetool.cpp @@ -450,8 +450,7 @@ void ShiftTraceTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) { m_gadget = RotateGadget; } - int row = getViewer()->posToRow(e.m_pos, getPixelSize() * getPixelSize(), - false, true); + int row = getViewer()->posToRow(e.m_pos, 5.0, false, true); if (row >= 0) { int index = -1; TApplication *app = TTool::getApplication(); diff --git a/toonz/sources/tnztools/skeletonsubtools.cpp b/toonz/sources/tnztools/skeletonsubtools.cpp index 3ca95f6..58ea4aa 100644 --- a/toonz/sources/tnztools/skeletonsubtools.cpp +++ b/toonz/sources/tnztools/skeletonsubtools.cpp @@ -180,7 +180,7 @@ DragPositionTool::DragPositionTool(SkeletonTool *tool) void DragPositionTool::leftButtonDown(const TPointD &pos, const TMouseEvent &) { start(); - m_firstPos = pos; + m_firstPos = pos; m_firstDrag = true; } @@ -190,9 +190,9 @@ void DragPositionTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) { TPointD delta = pos - m_firstPos; if (m_firstDrag && (delta.x > 2.0 || delta.y > 2.0)) { - m_firstPos = pos; - delta = TPointD(0.0, 0.0); - m_firstDrag = false; + m_firstPos = pos; + delta = TPointD(0.0, 0.0); + m_firstDrag = false; } if (e.isShiftPressed()) { if (fabs(delta.x) > fabs(delta.y)) @@ -300,10 +300,10 @@ void ParentChangeTool::leftButtonDown(const TPointD &pos, // registro alcune informazioni relative a colId: // placement, bbox, centro, hooks, name, ecc. Element element; - element.m_columnIndex = col; - TImageP img = cell.getImage(false); + element.m_columnIndex = col; + TImageP img = cell.getImage(false); if (img) element.m_bbox = img->getBBox(); - element.m_aff = xsh->getPlacement(colId, currentFrame); + element.m_aff = xsh->getPlacement(colId, currentFrame); Peer peer; peer.m_columnIndex = col; peer.m_handle = 0; @@ -352,7 +352,7 @@ void ParentChangeTool::leftButtonDrag(const TPointD &pos, if (m_snapped) return; getTool()->setParentProbe(getTool()->getCurrentColumnParentMatrix() * pos); - m_index = m_viewer->posToColumnIndex(e.m_pos, m_pixelSize * 5, false); + m_index = m_viewer->posToColumnIndex(e.m_pos, 5.0, false); m_lastPos = m_viewer->winToWorld(e.m_pos); @@ -425,16 +425,13 @@ void ParentChangeTool::draw() { getTool()->drawHooks(); } // //------------------------------------------------------------ - // This needs some clarification. namespace { class Graph { - // local variables defined below are: // Nodes m_nodes; // std::map m_leaves; - public: typedef std::set Links; typedef Links::const_iterator LinkIter; @@ -455,7 +452,7 @@ public: // check if a node is found in m_nodes bool isNode(int id) const { return m_nodes.count(id) > 0; } - + int getNodeCount() const { return (int)m_nodes.size(); } void link(int a, int b) { @@ -468,7 +465,7 @@ public: NodeIter it = m_nodes.find(a); return it == m_nodes.end() ? false : it->second.count(b); } - + const Links &getLinks(int id) const { static const Links empty; NodeIter it = m_nodes.find(id); @@ -501,15 +498,14 @@ public: LeaveIter it = m_leaves.find(id); return it == m_leaves.end() ? 0 : it->second; } - + void setLeaveType(int id, int type) { m_leaves[id] = type; } - // This gets rid of a node. void remove(int id) { NodeIter it = m_nodes.find(id); if (it != m_nodes.end()) { - // iterate over the links + // iterate over the links for (LinkIter j = it->second.begin(); j != it->second.end(); ++j) m_nodes[*j].erase(id); m_nodes.erase(it->first); @@ -536,15 +532,15 @@ bool hasPinned(const Skeleton::Bone *bone, const Skeleton::Bone *prevBone) { if (bone->getParent() && bone->getParent() != prevBone && hasPinned(bone->getParent(), bone)) { - return true; + return true; } for (int i = 0; i < bone->getChildCount(); i++) { - if (bone->getChild(i) != prevBone) { - if (hasPinned(bone->getChild(i), bone)) { - return true; - } + if (bone->getChild(i) != prevBone) { + if (hasPinned(bone->getChild(i), bone)) { + return true; } + } } return false; @@ -556,9 +552,9 @@ bool hasPinned(const Skeleton::Bone *bone, const Skeleton::Bone *prevBone) { bool addToActiveChain(Graph &tree, const Skeleton::Bone *bone, const Skeleton::Bone *prevBone) { if (!bone) return false; - + // The handle is what you grabbed - bool isHandle = prevBone == 0; + bool isHandle = prevBone == 0; bool isChild = prevBone != 0 && prevBone == bone->getParent(); bool isParent = prevBone != 0 && prevBone->getParent() == bone; @@ -571,19 +567,19 @@ bool addToActiveChain(Graph &tree, const Skeleton::Bone *bone, // Go up the chain from what you grabbed and add bones if (!isChild && isFree) { - if (bone->getParent()) { - propagate |= addToActiveChain(tree, bone->getParent(), bone); - } + if (bone->getParent()) { + propagate |= addToActiveChain(tree, bone->getParent(), bone); + } } std::vector children; // Once you reach the top parent, add the other children if (isHandle || isFree) { - for (int i = 0; i < bone->getChildCount(); i++) { - if (bone->getChild(i) != prevBone) { - propagate |= addToActiveChain(tree, bone->getChild(i), bone); - } + for (int i = 0; i < bone->getChildCount(); i++) { + if (bone->getChild(i) != prevBone) { + propagate |= addToActiveChain(tree, bone->getChild(i), bone); } + } } bool insert = false; @@ -856,8 +852,9 @@ void IKTool::initEngine(const TPointD &pos) { Skeleton::Bone *next = m_skeleton->getBoneByColumnIndex(*it++); for (; it != links.end(); ++it) stack.push_back(std::make_pair(*it, prev)); - if (links.size() > 1 || (prev && next && (prev->getParent() == bone && - next->getParent() == bone))) { + if (links.size() > 1 || + (prev && next && + (prev->getParent() == bone && next->getParent() == bone))) { bone = next; } else { m_joints.push_back(Joint(bone, prev, sign)); @@ -918,11 +915,12 @@ void IKTool::computeIHateIK() { int n = (int)objs.size(); int frame = TTool::getApplication()->getCurrentFrame()->getFrame(); m_foot = m_firstFoot = 0; - m_frameOnNewPin = false; + m_frameOnNewPin = false; // this just finds the first pin int i; - for (i = 0; i < n && !objs[i]->getPinnedRangeSet()->isPinned(frame); i++) {} + for (i = 0; i < n && !objs[i]->getPinnedRangeSet()->isPinned(frame); i++) { + } if (i == n) return; // this makes m_foot to be the current pin @@ -934,13 +932,14 @@ void IKTool::computeIHateIK() { if (!range || range->first != frame) return; m_frameOnNewPin = true; - int firstFrame = frame - 1; - m_firstFoot = m_foot; + int firstFrame = frame - 1; + m_firstFoot = m_foot; // the frame is the start of a new pinned frame, find the previous pin for (;;) { for (i = 0; i < n && !objs[i]->getPinnedRangeSet()->isPinned(firstFrame); - i++) {} + i++) { + } if (i == n) break; m_firstFoot = objs[i]; diff --git a/toonz/sources/tnztools/skeletontool.cpp b/toonz/sources/tnztools/skeletontool.cpp index ea6706e..299794d 100644 --- a/toonz/sources/tnztools/skeletontool.cpp +++ b/toonz/sources/tnztools/skeletontool.cpp @@ -383,8 +383,7 @@ void SkeletonTool::leftButtonDown(const TPointD &ppos, const TMouseEvent &e) { if (m_device < 0) { // No gadget clicked. Select the column std::vector columnIndexes; - getViewer()->posToColumnIndexes(e.m_pos, columnIndexes, - getPixelSize() * getPixelSize(), false); + getViewer()->posToColumnIndexes(e.m_pos, columnIndexes, 5.0, false); if (!columnIndexes.empty()) { int columnIndex; columnIndex = columnIndexes.back(); @@ -1056,8 +1055,7 @@ void SkeletonTool::drawHooks() { // otherColumn = "picked" column not connected TPointD parentProbePos = getViewer()->worldToPos(m_parentProbe); std::vector indexes; - getViewer()->posToColumnIndexes(parentProbePos, indexes, - getPixelSize() * 10, false); + getViewer()->posToColumnIndexes(parentProbePos, indexes, 10.0, false); for (int i = (int)indexes.size() - 1; i >= 0; i--) { if (connectedColumns.count(indexes[i]) == 0) { otherColumn = indexes[i]; diff --git a/toonz/sources/tnztools/stylepicker.cpp b/toonz/sources/tnztools/stylepicker.cpp index b6cc05a..20b9308 100644 --- a/toonz/sources/tnztools/stylepicker.cpp +++ b/toonz/sources/tnztools/stylepicker.cpp @@ -11,6 +11,7 @@ #include "toonz/dpiscale.h" #include "tpixelutils.h" #include "tregion.h" +#include "toonzqt/gutil.h" #include @@ -44,7 +45,7 @@ TPoint StylePicker::getRasterPoint(const TPointD &p) const { //--------------------------------------------------------- /*-- (StylePickerTool内で)LineとAreaを切り替えてPickできる。mode: 0=Area, * 1=Line, 2=Line&Areas(default) --*/ -int StylePicker::pickStyleId(const TPointD &pos, double radius2, +int StylePicker::pickStyleId(const TPointD &pos, double radius, double scale2, int mode) const { int styleId = 0; if (TToonzImageP ti = m_image) { @@ -78,11 +79,6 @@ int StylePicker::pickStyleId(const TPointD &pos, double radius2, // prima cerca lo stile della regione piu' vicina TRegion *r = vi->getRegion(pos); if (r) styleId = r->getStyle(); - // poi cerca quello della stroke, ma se prima aveva trovato una regione, - // richiede che - // il click sia proprio sopra la stroke, altrimenti cerca la stroke piu' - // vicina (max circa 10 pixel) - const double maxDist2 = (styleId == 0) ? 100.0 * radius2 : 0; bool strokeFound; double dist2, w, thick; UINT index; @@ -90,9 +86,16 @@ int StylePicker::pickStyleId(const TPointD &pos, double radius2, // la thickness, cioe' la min distance dalla outline e non dalla centerLine strokeFound = vi->getNearestStroke(pos, w, index, dist2); if (strokeFound) { + int devPixRatio = getDevPixRatio(); + dist2 *= scale2; TStroke *stroke = vi->getStroke(index); thick = stroke->getThickPoint(w).thick; - if (dist2 - thick * thick < maxDist2) { + double len2 = thick * thick * scale2; + const double minDist2 = + (styleId == 0) ? radius * radius * (double)(devPixRatio * devPixRatio) + : 0; + double checkDist = std::max(minDist2, len2); + if (dist2 < checkDist) { assert(stroke); styleId = stroke->getStyle(); } @@ -118,7 +121,8 @@ int StylePicker::pickTone(const TPointD &pos) const { //--------------------------------------------------------- -TPixel32 StylePicker::pickColor(const TPointD &pos, double radius2) const { +TPixel32 StylePicker::pickColor(const TPointD &pos, double radius, + double scale2) const { TToonzImageP ti = m_image; TRasterImageP ri = m_image; TVectorImageP vi = m_image; @@ -141,14 +145,14 @@ TPixel32 StylePicker::pickColor(const TPointD &pos, double radius2) const { } else if (vi) { const TPalette *palette = m_palette.getPointer(); if (!palette) return TPixel32::Transparent; - int styleId = pickStyleId(pos, radius2); + int styleId = pickStyleId(pos, radius, scale2); if (0 <= styleId && styleId < palette->getStyleCount()) return palette->getStyle(styleId)->getAverageColor(); } else if (ti) { const TPalette *palette = m_palette.getPointer(); if (!palette) return TPixel32::Transparent; - int paintId = pickStyleId(pos, radius2, 0); - int inkId = pickStyleId(pos, radius2, 1); + int paintId = pickStyleId(pos, radius, scale2, 0); + int inkId = pickStyleId(pos, radius, scale2, 1); int tone = pickTone(pos); TPixel32 ink, paint; if (0 <= inkId && inkId < palette->getStyleCount()) diff --git a/toonz/sources/tnztools/stylepickertool.cpp b/toonz/sources/tnztools/stylepickertool.cpp index fc5fe81..4c94331 100644 --- a/toonz/sources/tnztools/stylepickertool.cpp +++ b/toonz/sources/tnztools/stylepickertool.cpp @@ -9,6 +9,7 @@ // TnzQt includes #include "toonzqt/tselectionhandle.h" #include "toonzqt/styleselection.h" +#include "toonzqt/gutil.h" // TnzLib includes #include "toonz/txshsimplelevel.h" @@ -86,13 +87,13 @@ void StylePickerTool::pick(const TPointD &pos, const TMouseEvent &e, ---*/ if (Preferences::instance()->isMultiLayerStylePickerEnabled() && getApplication()->getCurrentFrame()->isEditingScene()) { - int superPickedColumnId = getViewer()->posToColumnIndex( - e.m_pos, getPixelSize() * getPixelSize(), false); + double pickRange = 10.0; + int superPickedColumnId = + getViewer()->posToColumnIndex(e.m_pos, pickRange, false); if (superPickedColumnId >= 0 /*-- 何かColumnに当たった場合 --*/ - && - getApplication()->getCurrentColumn()->getColumnIndex() != - superPickedColumnId) /*-- かつ、Current Columnでない場合 --*/ + && getApplication()->getCurrentColumn()->getColumnIndex() != + superPickedColumnId) /*-- かつ、Current Columnでない場合 --*/ { /*-- そのColumnからPickを試みる --*/ int currentFrame = getApplication()->getCurrentFrame()->getFrame(); @@ -112,13 +113,16 @@ void StylePickerTool::pick(const TPointD &pos, const TMouseEvent &e, tmpMousePosition.x /= tmpDpiScale.x; tmpMousePosition.y /= tmpDpiScale.y; + TAffine aff = + getViewer()->getViewMatrix() * getColumnMatrix(superPickedColumnId); + double scale2 = aff.det(); StylePicker superPicker(pickedImage); int picked_subsampling = picked_level->getImageSubsampling(pickedCell.getFrameId()); int superPicked_StyleId = superPicker.pickStyleId( TScale(1.0 / picked_subsampling) * tmpMousePosition + TPointD(-0.5, -0.5), - getPixelSize() * getPixelSize(), modeValue); + pickRange, scale2, modeValue); /*-- 何かStyleが拾えて、Transparentでない場合 --*/ if (superPicked_StyleId > 0) { /*-- Levelの移動 --*/ @@ -152,25 +156,26 @@ void StylePickerTool::pick(const TPointD &pos, const TMouseEvent &e, /*-- 画面外をpickしても拾えないようにする --*/ if (!m_viewer->getGeometry().contains(pos)) return; + TAffine aff = getViewer()->getViewMatrix() * getCurrentColumnMatrix(); + double scale2 = aff.det(); int subsampling = level->getImageSubsampling(getCurrentFid()); StylePicker picker(image); int styleId = picker.pickStyleId(TScale(1.0 / subsampling) * pos + TPointD(-0.5, -0.5), - getPixelSize() * getPixelSize(), modeValue); + 10.0, scale2, modeValue); if (styleId < 0) return; if (modeValue == 1) // LINES { /*-- pickLineモードのとき、取得Styleが0の場合はカレントStyleを変えない。 - * --*/ + * --*/ if (styleId == 0) return; /*-- - * pickLineモードのとき、PurePaintの部分をクリックしてもカレントStyleを変えない - * --*/ - if (ti && - picker.pickTone(TScale(1.0 / subsampling) * pos + - TPointD(-0.5, -0.5)) == 255) + * pickLineモードのとき、PurePaintの部分をクリックしてもカレントStyleを変えない + * --*/ + if (ti && picker.pickTone(TScale(1.0 / subsampling) * pos + + TPointD(-0.5, -0.5)) == 255) return; } @@ -207,14 +212,14 @@ void StylePickerTool::mouseMove(const TPointD &pos, const TMouseEvent &e) { return; } + TAffine aff = getViewer()->getViewMatrix() * getCurrentColumnMatrix(); + double scale2 = aff.det(); int subsampling = level->getImageSubsampling(getCurrentFid()); StylePicker picker(image); TPointD pickPos(TScale(1.0 / subsampling) * pos + TPointD(-0.5, -0.5)); - int inkStyleId = - picker.pickStyleId(pickPos, getPixelSize() * getPixelSize(), 1); - int paintStyleId = - picker.pickStyleId(pickPos, getPixelSize() * getPixelSize(), 0); - int tone = picker.pickTone(pickPos); + int inkStyleId = picker.pickStyleId(pickPos, 10.0, scale2, 1); + int paintStyleId = picker.pickStyleId(pickPos, 10.0, scale2, 0); + int tone = picker.pickTone(pickPos); controller->notifyStylePassivePicked(inkStyleId, paintStyleId, tone); } diff --git a/toonz/sources/tnztools/tool.cpp b/toonz/sources/tnztools/tool.cpp index 547971f..d56042e 100644 --- a/toonz/sources/tnztools/tool.cpp +++ b/toonz/sources/tnztools/tool.cpp @@ -697,8 +697,9 @@ TFrameId TTool::getCurrentFid() const { //----------------------------------------------------------------------------- -TAffine TTool::getCurrentColumnMatrix() const { - return getColumnMatrix(m_application->getCurrentColumn()->getColumnIndex()); +TAffine TTool::getCurrentColumnMatrix(int frame) const { + return getColumnMatrix(m_application->getCurrentColumn()->getColumnIndex(), + frame); } //----------------------------------------------------------------------------- @@ -735,12 +736,12 @@ TAffine TTool::getCurrentObjectParentMatrix() const { //----------------------------------------------------------------------------- -TAffine TTool::getColumnMatrix(int columnIndex) const { +TAffine TTool::getColumnMatrix(int columnIndex, int frame) const { if (!m_application) return TAffine(); TFrameHandle *fh = m_application->getCurrentFrame(); if (fh->isEditingLevel()) return TAffine(); - int frame = fh->getFrame(); + if (frame < 0) frame = fh->getFrame(); TXsheet *xsh = m_application->getCurrentXsheet()->getXsheet(); TStageObjectId columnObjId = (columnIndex >= 0) diff --git a/toonz/sources/toonz/imageviewer.cpp b/toonz/sources/toonz/imageviewer.cpp index 2c8e603..7820a23 100644 --- a/toonz/sources/toonz/imageviewer.cpp +++ b/toonz/sources/toonz/imageviewer.cpp @@ -954,9 +954,11 @@ void ImageViewer::pickColor(QMouseEvent *event, bool putValueToStyleEditor) { TPointD(0.5 * imgRect.getLx() + pos.x, 0.5 * imgRect.getLy() + pos.y); TPixel32 pix; - if (m_lutCalibrator && m_lutCalibrator->isValid()) - pix = picker.pickColor(pos + TPointD(-0.5, -0.5)); - else + if (m_lutCalibrator && m_lutCalibrator->isValid()) { + // for specifiying pixel range on picking vector + double scale2 = getViewAff().det(); + pix = picker.pickColor(pos + TPointD(-0.5, -0.5), 10.0, scale2); + } else pix = picker.pickColor(area); if (!img->raster() || imgRect.contains(imagePos)) { diff --git a/toonz/sources/toonz/sceneviewer.cpp b/toonz/sources/toonz/sceneviewer.cpp index bc56589..5b74f79 100644 --- a/toonz/sources/toonz/sceneviewer.cpp +++ b/toonz/sources/toonz/sceneviewer.cpp @@ -2930,8 +2930,9 @@ void SceneViewer::posToColumnIndexes(const TPointD &p, OnionSkinMask osm = app->getCurrentOnionSkin()->getOnionSkinMask(); TPointD pos = TPointD(p.x - width() / 2, p.y - height() / 2); - Stage::Picker picker(getViewMatrix(), pos, m_visualSettings); - picker.setDistance(distance); + Stage::Picker picker(getViewMatrix(), pos, m_visualSettings, + getDevPixRatio()); + picker.setMinimumDistance(distance); TXshSimpleLevel::m_rasterizePli = 0; @@ -2969,8 +2970,9 @@ int SceneViewer::posToRow(const TPointD &p, double distance, OnionSkinMask osm = app->getCurrentOnionSkin()->getOnionSkinMask(); TPointD pos = TPointD(p.x - width() / 2, p.y - height() / 2); - Stage::Picker picker(getViewMatrix(), pos, m_visualSettings); - picker.setDistance(distance); + Stage::Picker picker(getViewMatrix(), pos, m_visualSettings, + getDevPixRatio()); + picker.setMinimumDistance(distance); if (app->getCurrentFrame()->isEditingLevel()) { Stage::visit(picker, app->getCurrentLevel()->getLevel(), diff --git a/toonz/sources/toonzlib/stagevisitor.cpp b/toonz/sources/toonzlib/stagevisitor.cpp index 4c0c2e4..ad6c72d 100644 --- a/toonz/sources/toonzlib/stagevisitor.cpp +++ b/toonz/sources/toonzlib/stagevisitor.cpp @@ -215,16 +215,19 @@ void onPlasticDeformedImage(TStageObject *playerObj, //********************************************************************************************** Picker::Picker(const TAffine &viewAff, const TPointD &point, - const ImagePainter::VisualSettings &vs) + const ImagePainter::VisualSettings &vs, int devPixRatio) : Visitor(vs) , m_viewAff(viewAff) , m_point(point) , m_columnIndexes() - , m_minDist2(1.0e10) {} + , m_minDist2(25.0) + , m_devPixRatio(devPixRatio) {} //----------------------------------------------------------------------------- -void Picker::setDistance(double d) { m_minDist2 = d * d; } +void Picker::setMinimumDistance(double d) { + m_minDist2 = (double)(m_devPixRatio * m_devPixRatio) * d * d; +} //----------------------------------------------------------------------------- @@ -251,21 +254,11 @@ void Picker::onImage(const Stage::Player &player) { if (styleId != 0) picked = true; else if (vi->getNearestStroke(point, w, strokeIndex, dist2)) { - // based on TTool::Viewer::doPickGuideStroke - - // m_minDist2 seems to be the pixel size to the power 4, so take the - // square root of the square root. - // Use abs() just in case m_minDist2 is negative, to avoid math errors. - double pixelSize = sqrt(sqrt(abs(m_minDist2))); - double maxDist = 5 * pixelSize; - double maxDist2 = maxDist * maxDist; - double checkDist = maxDist2 * 4; - + dist2 *= aff.det(); TStroke *stroke = vi->getStroke(strokeIndex); TThickPoint thickPoint = stroke->getThickPoint(w); - double thickness = thickPoint.thick; - double len = thickness * pixelSize * sqrt(m_viewAff.det()); - checkDist = std::max(checkDist, (len * len)); + double len2 = thickPoint.thick * thickPoint.thick * aff.det(); + double checkDist = std::max(m_minDist2, len2); if (dist2 < checkDist) picked = true; } } else if (TRasterImageP ri = img) {