1 //------------------------------------------------------
2 /*! Finger Tool : 線のノイズを埋めるツール
3  */
4 #include "tstroke.h"
5 #include "tools/toolutils.h"
6 #include "tools/tool.h"
7 #include "tmathutil.h"
8 #include "tools/cursors.h"
9 #include "drawutil.h"
10 #include "tcolorstyles.h"
11 #include "tundo.h"
12 #include "tvectorimage.h"
13 #include "ttoonzimage.h"
14 #include "tproperty.h"
15 #include "toonz/strokegenerator.h"
16 #include "toonz/ttilesaver.h"
17 #include "toonz/txshsimplelevel.h"
18 #include "toonz/observer.h"
19 #include "toonz/toonzimageutils.h"
20 #include "toonz/levelproperties.h"
21 #include "toonz/stage2.h"
22 #include "toonz/ttileset.h"
23 #include "toonz/rasterstrokegenerator.h"
24 #include "toonz/preferences.h"
25 #include "tgl.h"
26 #include "tenv.h"
27 
28 #include "trop.h"
29 
30 #include "tinbetween.h"
31 #include "ttile.h"
32 
33 #include "toonz/tpalettehandle.h"
34 #include "toonz/txsheethandle.h"
35 #include "toonz/txshlevelhandle.h"
36 #include "toonz/tframehandle.h"
37 #include "tools/toolhandle.h"
38 
39 // For Qt translation support
40 #include <QCoreApplication>
41 
42 #include "tools/stylepicker.h"
43 #include "toonzqt/tselectionhandle.h"
44 #include "toonzqt/styleselection.h"
45 #include "historytypes.h"
46 
47 using namespace ToolUtils;
48 
49 TEnv::IntVar FingerInvert("InknpaintFingerInvert", 0);
50 TEnv::DoubleVar FingerSize("InknpaintFingerSize", 10);
51 
52 //-----------------------------------------------------------------------------
53 
54 const int BackgroundStyle = 0;
55 
56 //-----------------------------------------------------------------------------
57 
58 namespace {
59 
60 class FingerUndo final : public TRasterUndo {
61   std::vector<TThickPoint> m_points;
62   int m_styleId;
63   bool m_invert;
64 
65 public:
FingerUndo(TTileSetCM32 * tileSet,const std::vector<TThickPoint> & points,int styleId,bool invert,TXshSimpleLevel * level,const TFrameId & frameId)66   FingerUndo(TTileSetCM32 *tileSet, const std::vector<TThickPoint> &points,
67              int styleId, bool invert, TXshSimpleLevel *level,
68              const TFrameId &frameId)
69       : TRasterUndo(tileSet, level, frameId, false, false, 0)
70       , m_points(points)
71       , m_styleId(styleId)
72       , m_invert(invert) {}
73 
redo() const74   void redo() const override {
75     TToonzImageP image = m_level->getFrame(m_frameId, true);
76     TRasterCM32P ras   = image->getRaster();
77     RasterStrokeGenerator m_rasterTrack(ras, FINGER, INK, m_styleId,
78                                         m_points[0], m_invert, 0, false);
79     m_rasterTrack.setPointsSequence(m_points);
80     m_rasterTrack.generateStroke(true);
81     image->setSavebox(image->getSavebox() +
82                       m_rasterTrack.getBBox(m_rasterTrack.getPointsSequence()));
83 
84     ToolUtils::updateSaveBox();
85 
86     TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
87     notifyImageChanged();
88   }
89 
getSize() const90   int getSize() const override {
91     return sizeof(*this) + TRasterUndo::getSize();
92   }
93 
getToolName()94   QString getToolName() override { return QString("Finger Tool"); }
getHistoryType()95   int getHistoryType() override { return HistoryType::FingerTool; }
96 };
97 
98 //-------------------------------------------------------------------------------------------
99 
drawLine(const TPointD & point,const TPointD & centre,bool horizontal,bool isDecimal)100 void drawLine(const TPointD &point, const TPointD &centre, bool horizontal,
101               bool isDecimal) {
102   if (!isDecimal) {
103     if (horizontal) {
104       tglDrawSegment(TPointD(point.x - 1.5, point.y + 0.5) + centre,
105                      TPointD(point.x - 0.5, point.y + 0.5) + centre);
106       tglDrawSegment(TPointD(point.y - 0.5, -point.x + 1.5) + centre,
107                      TPointD(point.y - 0.5, -point.x + 0.5) + centre);
108       tglDrawSegment(TPointD(-point.x + 0.5, -point.y + 0.5) + centre,
109                      TPointD(-point.x - 0.5, -point.y + 0.5) + centre);
110       tglDrawSegment(TPointD(-point.y - 0.5, point.x - 0.5) + centre,
111                      TPointD(-point.y - 0.5, point.x + 0.5) + centre);
112 
113       tglDrawSegment(TPointD(point.y - 0.5, point.x + 0.5) + centre,
114                      TPointD(point.y - 0.5, point.x - 0.5) + centre);
115       tglDrawSegment(TPointD(point.x - 0.5, -point.y + 0.5) + centre,
116                      TPointD(point.x - 1.5, -point.y + 0.5) + centre);
117       tglDrawSegment(TPointD(-point.y - 0.5, -point.x + 0.5) + centre,
118                      TPointD(-point.y - 0.5, -point.x + 1.5) + centre);
119       tglDrawSegment(TPointD(-point.x - 0.5, point.y + 0.5) + centre,
120                      TPointD(-point.x + 0.5, point.y + 0.5) + centre);
121     } else {
122       tglDrawSegment(TPointD(point.x - 1.5, point.y + 1.5) + centre,
123                      TPointD(point.x - 1.5, point.y + 0.5) + centre);
124       tglDrawSegment(TPointD(point.x - 1.5, point.y + 0.5) + centre,
125                      TPointD(point.x - 0.5, point.y + 0.5) + centre);
126       tglDrawSegment(TPointD(point.y + 0.5, -point.x + 1.5) + centre,
127                      TPointD(point.y - 0.5, -point.x + 1.5) + centre);
128       tglDrawSegment(TPointD(point.y - 0.5, -point.x + 1.5) + centre,
129                      TPointD(point.y - 0.5, -point.x + 0.5) + centre);
130       tglDrawSegment(TPointD(-point.x + 0.5, -point.y - 0.5) + centre,
131                      TPointD(-point.x + 0.5, -point.y + 0.5) + centre);
132       tglDrawSegment(TPointD(-point.x + 0.5, -point.y + 0.5) + centre,
133                      TPointD(-point.x - 0.5, -point.y + 0.5) + centre);
134       tglDrawSegment(TPointD(-point.y - 1.5, point.x - 0.5) + centre,
135                      TPointD(-point.y - 0.5, point.x - 0.5) + centre);
136       tglDrawSegment(TPointD(-point.y - 0.5, point.x - 0.5) + centre,
137                      TPointD(-point.y - 0.5, point.x + 0.5) + centre);
138 
139       tglDrawSegment(TPointD(point.y + 0.5, point.x - 0.5) + centre,
140                      TPointD(point.y - 0.5, point.x - 0.5) + centre);
141       tglDrawSegment(TPointD(point.y - 0.5, point.x - 0.5) + centre,
142                      TPointD(point.y - 0.5, point.x + 0.5) + centre);
143       tglDrawSegment(TPointD(point.x - 1.5, -point.y - 0.5) + centre,
144                      TPointD(point.x - 1.5, -point.y + 0.5) + centre);
145       tglDrawSegment(TPointD(point.x - 1.5, -point.y + 0.5) + centre,
146                      TPointD(point.x - 0.5, -point.y + 0.5) + centre);
147       tglDrawSegment(TPointD(-point.y - 1.5, -point.x + 1.5) + centre,
148                      TPointD(-point.y - 0.5, -point.x + 1.5) + centre);
149       tglDrawSegment(TPointD(-point.y - 0.5, -point.x + 1.5) + centre,
150                      TPointD(-point.y - 0.5, -point.x + 0.5) + centre);
151       tglDrawSegment(TPointD(-point.x + 0.5, point.y + 1.5) + centre,
152                      TPointD(-point.x + 0.5, point.y + 0.5) + centre);
153       tglDrawSegment(TPointD(-point.x + 0.5, point.y + 0.5) + centre,
154                      TPointD(-point.x - 0.5, point.y + 0.5) + centre);
155     }
156   } else {
157     if (horizontal) {
158       tglDrawSegment(TPointD(point.x - 0.5, point.y + 0.5) + centre,
159                      TPointD(point.x + 0.5, point.y + 0.5) + centre);
160       tglDrawSegment(TPointD(point.y + 0.5, point.x - 0.5) + centre,
161                      TPointD(point.y + 0.5, point.x + 0.5) + centre);
162       tglDrawSegment(TPointD(point.y + 0.5, -point.x + 0.5) + centre,
163                      TPointD(point.y + 0.5, -point.x - 0.5) + centre);
164       tglDrawSegment(TPointD(point.x + 0.5, -point.y - 0.5) + centre,
165                      TPointD(point.x - 0.5, -point.y - 0.5) + centre);
166       tglDrawSegment(TPointD(-point.x - 0.5, -point.y - 0.5) + centre,
167                      TPointD(-point.x + 0.5, -point.y - 0.5) + centre);
168       tglDrawSegment(TPointD(-point.y - 0.5, -point.x + 0.5) + centre,
169                      TPointD(-point.y - 0.5, -point.x - 0.5) + centre);
170       tglDrawSegment(TPointD(-point.y - 0.5, point.x - 0.5) + centre,
171                      TPointD(-point.y - 0.5, point.x + 0.5) + centre);
172       tglDrawSegment(TPointD(-point.x + 0.5, point.y + 0.5) + centre,
173                      TPointD(-point.x - 0.5, point.y + 0.5) + centre);
174     } else {
175       tglDrawSegment(TPointD(point.x - 0.5, point.y + 1.5) + centre,
176                      TPointD(point.x - 0.5, point.y + 0.5) + centre);
177       tglDrawSegment(TPointD(point.x - 0.5, point.y + 0.5) + centre,
178                      TPointD(point.x + 0.5, point.y + 0.5) + centre);
179       tglDrawSegment(TPointD(point.y + 1.5, point.x - 0.5) + centre,
180                      TPointD(point.y + 0.5, point.x - 0.5) + centre);
181       tglDrawSegment(TPointD(point.y + 0.5, point.x - 0.5) + centre,
182                      TPointD(point.y + 0.5, point.x + 0.5) + centre);
183       tglDrawSegment(TPointD(point.y + 1.5, -point.x + 0.5) + centre,
184                      TPointD(point.y + 0.5, -point.x + 0.5) + centre);
185       tglDrawSegment(TPointD(point.y + 0.5, -point.x + 0.5) + centre,
186                      TPointD(point.y + 0.5, -point.x - 0.5) + centre);
187       tglDrawSegment(TPointD(point.x - 0.5, -point.y - 1.5) + centre,
188                      TPointD(point.x - 0.5, -point.y - 0.5) + centre);
189       tglDrawSegment(TPointD(point.x - 0.5, -point.y - 0.5) + centre,
190                      TPointD(point.x + 0.5, -point.y - 0.5) + centre);
191 
192       tglDrawSegment(TPointD(-point.x + 0.5, -point.y - 1.5) + centre,
193                      TPointD(-point.x + 0.5, -point.y - 0.5) + centre);
194       tglDrawSegment(TPointD(-point.x + 0.5, -point.y - 0.5) + centre,
195                      TPointD(-point.x - 0.5, -point.y - 0.5) + centre);
196       tglDrawSegment(TPointD(-point.y - 1.5, -point.x + 0.5) + centre,
197                      TPointD(-point.y - 0.5, -point.x + 0.5) + centre);
198       tglDrawSegment(TPointD(-point.y - 0.5, -point.x + 0.5) + centre,
199                      TPointD(-point.y - 0.5, -point.x - 0.5) + centre);
200       tglDrawSegment(TPointD(-point.y - 1.5, point.x - 0.5) + centre,
201                      TPointD(-point.y - 0.5, point.x - 0.5) + centre);
202       tglDrawSegment(TPointD(-point.y - 0.5, point.x - 0.5) + centre,
203                      TPointD(-point.y - 0.5, point.x + 0.5) + centre);
204       tglDrawSegment(TPointD(-point.x + 0.5, point.y + 1.5) + centre,
205                      TPointD(-point.x + 0.5, point.y + 0.5) + centre);
206       tglDrawSegment(TPointD(-point.x + 0.5, point.y + 0.5) + centre,
207                      TPointD(-point.x - 0.5, point.y + 0.5) + centre);
208     }
209   }
210 }
211 
212 //-------------------------------------------------------------------------------------------------------
213 
drawEmptyCircle(int thick,const TPointD & mousePos,bool isPencil,bool isLxEven,bool isLyEven)214 void drawEmptyCircle(int thick, const TPointD &mousePos, bool isPencil,
215                      bool isLxEven, bool isLyEven) {
216   TPointD pos = mousePos;
217   if (isLxEven) pos.x += 0.5;
218   if (isLyEven) pos.y += 0.5;
219   if (!isPencil)
220     tglDrawCircle(pos, (thick + 1) * 0.5);
221   else {
222     int x = 0, y = tround((thick * 0.5) - 0.5);
223     int d           = 3 - 2 * (int)(thick * 0.5);
224     bool horizontal = true, isDecimal = thick % 2 != 0;
225     drawLine(TPointD(x, y), pos, horizontal, isDecimal);
226     while (y > x) {
227       if (d < 0) {
228         d          = d + 4 * x + 6;
229         horizontal = true;
230       } else {
231         d          = d + 4 * (x - y) + 10;
232         horizontal = false;
233         y--;
234       }
235       x++;
236       drawLine(TPointD(x, y), pos, horizontal, isDecimal);
237     }
238   }
239 }
240 
241 }  // namespace
242 
243 //-----------------------------------------------------------------------------
244 
245 class FingerTool final : public TTool {
246   Q_DECLARE_TR_FUNCTIONS(FingerTool)
247 
248   RasterStrokeGenerator *m_rasterTrack;
249 
250   bool m_firstTime;
251 
252   double m_pointSize, m_distance2;
253 
254   bool m_selecting;
255   TTileSaverCM32 *m_tileSaver;
256 
257   TPointD m_mousePos;
258 
259   TIntProperty m_toolSize;
260   TBoolProperty m_invert;
261   TPropertyGroup m_prop;
262   int m_cursor;
263 
264   /*---	作業中のFrameIdをクリック時に保存し、マウスリリース時(Undoの登録時)
265                   に別のフレームに移動している場合があるため ---*/
266   TFrameId m_workingFrameId;
267 
268   /*-- 最初のクリックでStyleを切り替える --*/
269   void pick(const TPointD &pos);
270 
271 public:
272   FingerTool();
273 
274   void draw() override;
275   void update(TToonzImageP ti, TRectD area);
276 
277   void updateTranslation() override;
278 
279   void leftButtonDown(const TPointD &pos, const TMouseEvent &e) override;
280   void leftButtonDrag(const TPointD &pos, const TMouseEvent &e) override;
281   void leftButtonUp(const TPointD &pos, const TMouseEvent &) override;
282   void mouseMove(const TPointD &pos, const TMouseEvent &e) override;
283   void onEnter() override;
284   void onLeave() override;
285   void onActivate() override;
286   void onDeactivate() override;
287   bool onPropertyChanged(std::string propertyName) override;
288 
getProperties(int targetType)289   TPropertyGroup *getProperties(int targetType) override { return &m_prop; }
getToolType() const290   ToolType getToolType() const override { return TTool::LevelWriteTool; }
getCursorId() const291   int getCursorId() const override { return m_cursor; }
292 
getColorClass() const293   int getColorClass() const { return 2; }
294 
295   /*--
296    * ドラッグ中にツールが切り替わった場合に備え、onDeactivateにもMouseReleaseと同じ処理を行う
297    * --*/
298   void finishBrush();
299 };
300 
301 FingerTool fingerTool;
302 
303 //=============================================================================
304 //
305 //  InkPaintTool implemention
306 //
307 //-----------------------------------------------------------------------------
308 
FingerTool()309 FingerTool::FingerTool()
310     : TTool("T_Finger")
311     , m_rasterTrack(0)
312     , m_pointSize(-1)
313     , m_selecting(false)
314     , m_tileSaver(0)
315     , m_cursor(ToolCursor::EraserCursor)
316     , m_toolSize("Size:", 1, 1000, 10, false)
317     , m_invert("Invert", false)
318     , m_firstTime(true)
319     , m_workingFrameId(TFrameId()) {
320   bind(TTool::ToonzImage);
321 
322   m_toolSize.setNonLinearSlider();
323 
324   m_prop.bind(m_toolSize);
325   m_prop.bind(m_invert);
326 
327   m_invert.setId("Invert");
328 }
329 
330 //-----------------------------------------------------------------------------
331 
updateTranslation()332 void FingerTool::updateTranslation() {
333   m_toolSize.setQStringName(tr("Size:"));
334   m_invert.setQStringName(tr("Invert", NULL));
335 }
336 
337 //-----------------------------------------------------------------------------
338 
draw()339 void FingerTool::draw() {
340   if (m_pointSize == -1) {
341     return;
342   }
343 
344   // If toggled off, don't draw brush outline
345   if (!Preferences::instance()->isCursorOutlineEnabled()) return;
346 
347   TToonzImageP ti = (TToonzImageP)getImage(false);
348   if (!ti) return;
349   TRasterP ras = ti->getRaster();
350   int lx       = ras->getLx();
351   int ly       = ras->getLy();
352 
353   if ((ToonzCheck::instance()->getChecks() & ToonzCheck::eInk) ||
354       (ToonzCheck::instance()->getChecks() & ToonzCheck::ePaint))
355     glColor3d(0.5, 0.8, 0.8);
356   else
357     glColor3d(1.0, 0.0, 0.0);
358 
359   drawEmptyCircle(m_toolSize.getValue(), m_mousePos, true, lx % 2 == 0,
360                   ly % 2 == 0);
361 }
362 
363 //-----------------------------------------------------------------------------
364 
365 const UINT pointCount = 20;
366 
367 //-----------------------------------------------------------------------------
368 
onPropertyChanged(std::string propertyName)369 bool FingerTool::onPropertyChanged(std::string propertyName) {
370   /*-- サイズ --*/
371   if (propertyName == m_toolSize.getName()) {
372     FingerSize = m_toolSize.getValue();
373     double x   = m_toolSize.getValue();
374 
375     double minRange = 1;
376     double maxRange = 100;
377 
378     double minSize = 0.01;
379     double maxSize = 100;
380 
381     m_pointSize =
382         (x - minRange) / (maxRange - minRange) * (maxSize - minSize) + minSize;
383     invalidate();
384   }
385 
386   // Invert
387   else if (propertyName == m_invert.getName()) {
388     FingerInvert = (int)(m_invert.getValue());
389   }
390 
391   return true;
392 }
393 
394 //-----------------------------------------------------------------------------
395 
leftButtonDown(const TPointD & pos,const TMouseEvent & e)396 void FingerTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) {
397   pick(pos);
398 
399   m_selecting = true;
400   TImageP image(getImage(true));
401 
402   if (TToonzImageP ti = image) {
403     TRasterCM32P ras = ti->getRaster();
404     if (ras) {
405       int thickness = m_toolSize.getValue();
406       int styleId   = TTool::getApplication()->getCurrentLevelStyleIndex();
407       TTileSetCM32 *tileSet = new TTileSetCM32(ras->getSize());
408       m_tileSaver           = new TTileSaverCM32(ras, tileSet);
409       m_rasterTrack         = new RasterStrokeGenerator(
410           ras, FINGER, INK, styleId,
411           TThickPoint(pos + convert(ras->getCenter()), thickness),
412           m_invert.getValue(), 0, false);
413 
414       /*-- 作業中Fidを現在のFIDにする --*/
415       m_workingFrameId = getFrameId();
416 
417       m_tileSaver->save(m_rasterTrack->getLastRect());
418       TRect modifiedBbox = m_rasterTrack->generateLastPieceOfStroke(true);
419       invalidate();
420     }
421   }
422 }
423 
424 //-----------------------------------------------------------------------------
425 
leftButtonDrag(const TPointD & pos,const TMouseEvent & e)426 void FingerTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) {
427   if (!m_selecting) return;
428 
429   m_mousePos = pos;
430   if (TToonzImageP ri = TImageP(getImage(true))) {
431     /*---	マウスを動かしながらショートカットで切り替わった場合、
432                     いきなりleftButtonDragから呼ばれることがあり、
433                     m_rasterTrackが無くて落ちることがある。 ---*/
434     if (m_rasterTrack) {
435       int thickness = m_toolSize.getValue();
436       m_rasterTrack->add(
437           TThickPoint(pos + convert(ri->getRaster()->getCenter()), thickness));
438       m_tileSaver->save(m_rasterTrack->getLastRect());
439       TRect modifiedBbox = m_rasterTrack->generateLastPieceOfStroke(true);
440       invalidate();
441     }
442   }
443 }
444 
445 //-----------------------------------------------------------------------------
446 
leftButtonUp(const TPointD & pos,const TMouseEvent &)447 void FingerTool::leftButtonUp(const TPointD &pos, const TMouseEvent &) {
448   if (!m_selecting) return;
449 
450   m_mousePos = pos;
451 
452   finishBrush();
453 }
454 
455 //-----------------------------------------------------------------------------
456 
mouseMove(const TPointD & pos,const TMouseEvent & e)457 void FingerTool::mouseMove(const TPointD &pos, const TMouseEvent &e) {
458   m_mousePos = pos;
459   TPointD pp(tround(pos.x), tround(pos.y));
460   m_mousePos = pp;
461   invalidate();
462 }
463 
464 //-----------------------------------------------------------------------------
465 
onEnter()466 void FingerTool::onEnter() {
467   if (m_firstTime) {
468     m_invert.setValue(FingerInvert ? 1 : 0);
469     m_toolSize.setValue(FingerSize);
470     m_firstTime = false;
471   }
472   double x = m_toolSize.getValue();
473 
474   double minRange = 1;
475   double maxRange = 100;
476 
477   double minSize = 0.01;
478   double maxSize = 100;
479 
480   m_pointSize =
481       (x - minRange) / (maxRange - minRange) * (maxSize - minSize) + minSize;
482 
483   if ((TToonzImageP)getImage(false))
484     m_cursor = ToolCursor::PenCursor;
485   else
486     m_cursor = ToolCursor::CURSOR_NO;
487 }
488 
489 //-----------------------------------------------------------------------------
490 
onLeave()491 void FingerTool::onLeave() { m_pointSize = -1; }
492 
493 //-----------------------------------------------------------------------------
494 
onActivate()495 void FingerTool::onActivate() { onEnter(); }
496 
497 //-----------------------------------------------------------------------------
498 
onDeactivate()499 void FingerTool::onDeactivate() {
500   /*---
501    * マウスドラッグ中(m_selecting=true)にツールが切り替わったときに線を終わらせる
502    * ---*/
503   if (m_selecting) finishBrush();
504 }
505 
506 //-----------------------------------------------------------------------------
507 /*!
508  * ドラッグ中にツールが切り替わった場合に備え、onDeactivateにもMouseReleaseと同じ処理を行う
509  */
finishBrush()510 void FingerTool::finishBrush() {
511   if (TToonzImageP ti = (TToonzImageP)getImage(true)) {
512     if (m_rasterTrack) {
513       int thickness = m_toolSize.getValue();
514       m_rasterTrack->add(TThickPoint(
515           m_mousePos + convert(ti->getRaster()->getCenter()), thickness));
516       m_tileSaver->save(m_rasterTrack->getLastRect());
517       TRect modifiedBbox = m_rasterTrack->generateLastPieceOfStroke(true, true);
518 
519       TTool::Application *app   = TTool::getApplication();
520       TXshLevel *level          = app->getCurrentLevel()->getLevel();
521       TXshSimpleLevelP simLevel = level->getSimpleLevel();
522 
523       TFrameId frameId =
524           m_workingFrameId.isEmptyFrame() ? getCurrentFid() : m_workingFrameId;
525 
526       TUndoManager::manager()->add(new FingerUndo(
527           m_tileSaver->getTileSet(), m_rasterTrack->getPointsSequence(),
528           m_rasterTrack->getStyleId(), m_rasterTrack->isSelective(),
529           simLevel.getPointer(), frameId));
530       ToolUtils::updateSaveBox();
531 
532       /*! FIdを指定して、作業中にフレームが動いても、
533               クリック時のFidのサムネイルが更新されるようにする。
534       */
535       notifyImageChanged(frameId);
536 
537       invalidate();
538       delete m_rasterTrack;
539       m_rasterTrack = 0;
540       delete m_tileSaver;
541 
542       /*-- 作業中fIdをリセット --*/
543       m_workingFrameId = TFrameId();
544     }
545   }
546   m_selecting = false;
547 }
548 
pick(const TPointD & pos)549 void FingerTool::pick(const TPointD &pos) {
550   int modeValue = 2;  // LINES
551 
552   TImageP image    = getImage(false);
553   TToonzImageP ti  = image;
554   TVectorImageP vi = image;
555   TXshSimpleLevel *level =
556       getApplication()->getCurrentLevel()->getSimpleLevel();
557   if (!ti || !level) return;
558 
559   /*--- 画面外をpickしても拾えないようにする ---*/
560   if (!m_viewer->getGeometry().contains(pos)) return;
561 
562   int subsampling = level->getImageSubsampling(getCurrentFid());
563 
564   StylePicker picker(image);
565 
566   int styleId =
567       picker.pickStyleId(TScale(1.0 / subsampling) * pos + TPointD(-0.5, -0.5),
568                          getPixelSize() * getPixelSize(), 1.0, modeValue);
569 
570   if (styleId < 0) return;
571 
572   if (modeValue == 2)  // LINES
573   {
574     /*--- pickLineモードのとき、取得Styleが0の場合はカレントStyleを変えない。
575      * ---*/
576     if (styleId == 0) return;
577 
578     /*---
579      * pickLineモードのとき、PurePaintの部分をクリックしてもカレントStyleを変えない
580      * ---*/
581     if (ti && picker.pickTone(TScale(1.0 / subsampling) * pos +
582                               TPointD(-0.5, -0.5)) == 255)
583       return;
584   }
585 
586   /*--- Styleを選択している場合は選択を解除する ---*/
587   TSelection *selection =
588       TTool::getApplication()->getCurrentSelection()->getSelection();
589   if (selection) {
590     TStyleSelection *styleSelection =
591         dynamic_cast<TStyleSelection *>(selection);
592     if (styleSelection) styleSelection->selectNone();
593   }
594 
595   getApplication()->setCurrentLevelStyleIndex(styleId);
596 }
597