fix vector picker range and onion skin fill

This commit is contained in:
shun-iwasawa 2020-12-21 12:59:35 +09:00 committed by manongjohn
parent af3d141dba
commit 6c76dd8d1e
16 changed files with 178 additions and 129 deletions

View file

@ -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

View file

@ -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.
\sa TXsheet::getPlacement.
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

View file

@ -302,14 +302,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 onRasterImage(TRasterImage *ri, const Stage::Player &data) override{};

View file

@ -576,8 +576,7 @@ void ControlPointEditorTool::leftButtonDown(const TPointD &pos,
if (m_autoSelectDrawing.getValue()) {
// Non sono in nessun gadget
std::vector<int> 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();

View file

@ -1059,8 +1059,7 @@ void EditTool::onEditAllLeftButtonDown(TPointD &pos, const TMouseEvent &e) {
if (selectedDevice < 0 && m_autoSelect.getValue() != L"None") {
pos = getMatrix() * pos;
int columnIndex =
getViewer()->posToColumnIndex(e.m_pos, 5 * getPixelSize(), false);
int columnIndex = getViewer()->posToColumnIndex(e.m_pos, 5.0, false);
if (columnIndex >= 0) {
TStageObjectId id = TStageObjectId::ColumnId(columnIndex);
int currentColumnIndex = getColumnIndex();

View file

@ -1812,6 +1812,8 @@ void AreaFillTool::onEnter() {
// getApplication()->editImage();
}
bool descending(int i, int j) { return (i > j); }
} // namespace
//=============================================================================
@ -2457,14 +2459,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);
}
//-----------------------------------------------------------------------------
@ -2481,32 +2499,53 @@ int FillTool::pickOnionColor(const TPointD &pos) {
if (!sl) return 0;
std::vector<int> rows;
osMask.getAll(sl->guessIndex(fid), rows);
// 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 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<int>::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;
}
}
//-----------------------------------------------------------------------------

View file

@ -76,7 +76,7 @@ public:
void onActivate();
void onEnter();
};
}
} // namespace
class FillTool final : public QObject, public TTool {
// Q_DECLARE_TR_FUNCTIONS(FillTool)
Q_OBJECT
@ -135,7 +135,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;

View file

@ -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();

View file

@ -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<int, int> m_leaves;
public:
typedef std::set<int> 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,7 +498,7 @@ 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; }
@ -509,7 +506,7 @@ public:
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 +533,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 +553,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 +568,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<int> 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 +853,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 +916,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
@ -940,7 +939,8 @@ void IKTool::computeIHateIK() {
// 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];

View file

@ -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<int> 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<int> 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];

View file

@ -11,6 +11,7 @@
#include "toonz/dpiscale.h"
#include "tpixelutils.h"
#include "tregion.h"
#include "toonzqt/gutil.h"
#include <QRect>
@ -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())

View file

@ -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,13 +212,13 @@ 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 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);
}

View file

@ -721,8 +721,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);
}
//-----------------------------------------------------------------------------
@ -759,12 +760,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)

View file

@ -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)) {

View file

@ -3117,8 +3117,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;
@ -3156,8 +3157,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(),

View file

@ -215,16 +215,20 @@ 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 +255,12 @@ 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) {