Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzTools includes
Toshihiro Shimizu 890ddd
#include "tools/toolhandle.h"
Toshihiro Shimizu 890ddd
#include "tools/toolutils.h"
Toshihiro Shimizu 890ddd
#include "tools/tool.h"
Toshihiro Shimizu 890ddd
#include "tools/cursors.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzQt includes
Toshihiro Shimizu 890ddd
#include "toonzqt/imageutils.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzLib includes
Toshihiro Shimizu 890ddd
#include "toonz/txshlevelhandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tframehandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnhandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/txsheethandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/strokegenerator.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshsimplelevel.h"
Toshihiro Shimizu 890ddd
#include "toonz/stage2.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "tenv.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tmathutil.h"
Toshihiro Shimizu 890ddd
#include "tundo.h"
Toshihiro Shimizu 890ddd
#include "tstroke.h"
Toshihiro Shimizu 890ddd
#include "tvectorimage.h"
Toshihiro Shimizu 890ddd
#include "ttoonzimage.h"
Toshihiro Shimizu 890ddd
#include "tproperty.h"
Toshihiro Shimizu 890ddd
#include "tgl.h"
Toshihiro Shimizu 890ddd
#include "tinbetween.h"
Toshihiro Shimizu 890ddd
#include "drawutil.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Qt includes
Shinya Kitaoka 120a6e
#include <qcoreapplication>  // For Qt translation support</qcoreapplication>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace ToolUtils;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TEnv::DoubleVar EraseVectorSize("InknpaintEraseVectorSize", 10);
Toshihiro Shimizu 890ddd
TEnv::StringVar EraseVectorType("InknpaintEraseVectorType", "Normal");
Toshihiro Shimizu 890ddd
TEnv::IntVar EraseVectorSelective("InknpaintEraseVectorSelective", 0);
Toshihiro Shimizu 890ddd
TEnv::IntVar EraseVectorInvert("InknpaintEraseVectorInvert", 0);
Toshihiro Shimizu 890ddd
TEnv::IntVar EraseVectorRange("InknpaintEraseVectorRange", 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Shinya Kitaoka 120a6e
// Eraser Tool
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define NORMAL_ERASE L"Normal"
Toshihiro Shimizu 890ddd
#define RECT_ERASE L"Rectangular"
Toshihiro Shimizu 890ddd
#define FREEHAND_ERASE L"Freehand"
Toshihiro Shimizu 890ddd
#define POLYLINE_ERASE L"Polyline"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const double minDistance2 = 16.0;  // 4 pixel
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void mapToVector(const std::map<int, *="" vistroke=""> &theMap,</int,>
Shinya Kitaoka 120a6e
                 std::vector<int> &theVect) {</int>
Shinya Kitaoka 120a6e
  assert(theMap.size() == theVect.size());
Shinya Kitaoka 120a6e
  std::map<int, *="" vistroke="">::const_iterator it = theMap.begin();</int,>
Shinya Kitaoka 120a6e
  UINT i = 0;
Shinya Kitaoka 120a6e
  for (; it != theMap.end(); ++it) {
Shinya Kitaoka 120a6e
    theVect[i++] = it->first;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class UndoEraser : public ToolUtils::TToolUndo {
Shinya Kitaoka 120a6e
  std::vector<tfilledregioninf> m_oldFillInformation, m_newFillInformation;</tfilledregioninf>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int m_row;
Shinya Kitaoka 120a6e
  int m_column;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  std::map<int, *="" vistroke=""> m_originalStrokes;</int,>
Shinya Kitaoka 120a6e
  std::map<int, *="" vistroke=""> m_newStrokes;</int,>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  UndoEraser(TXshSimpleLevel *level, const TFrameId &frameId)
Shinya Kitaoka 120a6e
      : ToolUtils::TToolUndo(level, frameId) {
Shinya Kitaoka 120a6e
    TVectorImageP image = level->getFrame(m_frameId, true);
Shinya Kitaoka 120a6e
    if (!image) return;
Shinya Kitaoka 120a6e
    TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
    if (app) {
Shinya Kitaoka 120a6e
      m_row    = app->getCurrentFrame()->getFrame();
Shinya Kitaoka 120a6e
      m_column = app->getCurrentColumn()->getColumnIndex();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    ImageUtils::getFillingInformationInArea(image, m_oldFillInformation,
Shinya Kitaoka 120a6e
                                            image->getBBox());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void onAdd() {
Shinya Kitaoka 120a6e
    TVectorImageP image = m_level->getFrame(m_frameId, true);
Shinya Kitaoka 120a6e
    assert(!!image);
Shinya Kitaoka 120a6e
    if (!image) return;
Shinya Kitaoka 120a6e
    ImageUtils::getFillingInformationInArea(image, m_newFillInformation,
Shinya Kitaoka 120a6e
                                            image->getBBox());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~UndoEraser() {
Shinya Kitaoka 120a6e
    std::map<int, *="" vistroke="">::const_iterator it;</int,>
Shinya Kitaoka 120a6e
    for (it = m_originalStrokes.begin(); it != m_originalStrokes.end(); ++it)
Shinya Kitaoka 120a6e
      deleteVIStroke(it->second);
Shinya Kitaoka 120a6e
    for (it = m_newStrokes.begin(); it != m_newStrokes.end(); ++it)
Shinya Kitaoka 120a6e
      deleteVIStroke(it->second);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void addOldStroke(int index, VIStroke *stroke) {
Shinya Kitaoka 120a6e
    VIStroke *s = cloneVIStroke(stroke);
Shinya Kitaoka 120a6e
    m_originalStrokes.insert(std::map<int, *="" vistroke="">::value_type(index, s));</int,>
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void addNewStroke(int index, VIStroke *stroke) {
Shinya Kitaoka 120a6e
    VIStroke *s = cloneVIStroke(stroke);
Shinya Kitaoka 120a6e
    m_newStrokes.insert(std::map<int, *="" vistroke="">::value_type(index, s));</int,>
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void undo() const {
Shinya Kitaoka 120a6e
    TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
    if (!app) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TFrameId currentFid;
Shinya Kitaoka 120a6e
    if (app->getCurrentFrame()->isEditingScene()) {
Shinya Kitaoka 120a6e
      app->getCurrentColumn()->setColumnIndex(m_column);
Shinya Kitaoka 120a6e
      app->getCurrentFrame()->setFrame(m_row);
Shinya Kitaoka 120a6e
      currentFid = TFrameId(m_row + 1);
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      app->getCurrentFrame()->setFid(m_frameId);
Shinya Kitaoka 120a6e
      currentFid = m_frameId;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TVectorImageP image = m_level->getFrame(m_frameId, true);
Shinya Kitaoka 120a6e
    assert(image);
Shinya Kitaoka 120a6e
    if (!image) return;
Shinya Kitaoka 120a6e
    QMutexLocker lock(image->getMutex());
Shinya Kitaoka 120a6e
    std::vector<int> newStrokeIndex(m_newStrokes.size());</int>
Shinya Kitaoka 120a6e
    mapToVector(m_newStrokes, newStrokeIndex);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    image->removeStrokes(newStrokeIndex, true, false);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    std::map<int, *="" vistroke="">::const_iterator it = m_originalStrokes.begin();</int,>
Shinya Kitaoka 120a6e
    UINT i = 0;
Shinya Kitaoka 120a6e
    VIStroke *s;
Shinya Kitaoka 120a6e
    for (; it != m_originalStrokes.end(); ++it) {
Shinya Kitaoka 120a6e
      s = cloneVIStroke(it->second);
Shinya Kitaoka 120a6e
      image->insertStrokeAt(s, it->first);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (image->isComputedRegionAlmostOnce())
Shinya Kitaoka 120a6e
      image->findRegions();  // in futuro togliere. Serve perche' la
Shinya Kitaoka 120a6e
                             // removeStrokes, se gli si dice
Shinya Kitaoka 120a6e
    // di non calcolare le regioni, e' piu' veloce ma poi chrash tutto
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    UINT size = m_oldFillInformation.size();
Shinya Kitaoka 120a6e
    if (!size) {
Shinya Kitaoka 120a6e
      app->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
      notifyImageChanged();
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRegion *reg;
Shinya Kitaoka 120a6e
    i = 0;
Shinya Kitaoka 120a6e
    for (; i < size; i++) {
Shinya Kitaoka 120a6e
      reg = image->getRegion(m_oldFillInformation[i].m_regionId);
Shinya Kitaoka 120a6e
      assert(reg);
Shinya Kitaoka 120a6e
      if (reg) reg->setStyle(m_oldFillInformation[i].m_styleId);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    app->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
    notifyImageChanged();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void redo() const {
Shinya Kitaoka 120a6e
    TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
    if (!app) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TFrameId currentFid;
Shinya Kitaoka 120a6e
    if (app->getCurrentFrame()->isEditingScene()) {
Shinya Kitaoka 120a6e
      app->getCurrentColumn()->setColumnIndex(m_column);
Shinya Kitaoka 120a6e
      app->getCurrentFrame()->setFrame(m_row);
Shinya Kitaoka 120a6e
      currentFid = TFrameId(m_row + 1);
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      app->getCurrentFrame()->setFid(m_frameId);
Shinya Kitaoka 120a6e
      currentFid = m_frameId;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    TVectorImageP image = m_level->getFrame(m_frameId, true);
Shinya Kitaoka 120a6e
    assert(image);
Shinya Kitaoka 120a6e
    if (!image) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    QMutexLocker lock(image->getMutex());
Shinya Kitaoka 120a6e
    std::vector<int> oldStrokeIndex(m_originalStrokes.size());</int>
Shinya Kitaoka 120a6e
    mapToVector(m_originalStrokes, oldStrokeIndex);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    image->removeStrokes(oldStrokeIndex, true, false);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    std::map<int, *="" vistroke="">::const_iterator it = m_newStrokes.begin();</int,>
Shinya Kitaoka 120a6e
    UINT i = 0;
Shinya Kitaoka 120a6e
    VIStroke *s;
Shinya Kitaoka 120a6e
    for (; it != m_newStrokes.end(); ++it) {
Shinya Kitaoka 120a6e
      s = cloneVIStroke(it->second);
Shinya Kitaoka 120a6e
      image->insertStrokeAt(s, it->first);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (image->isComputedRegionAlmostOnce())
Shinya Kitaoka 120a6e
      image->findRegions();  // in futuro togliere. Serve perche' la
Shinya Kitaoka 120a6e
                             // removeStrokes, se gli si dice
Shinya Kitaoka 120a6e
    // di non calcolare le regioni, e' piu' veloce ma poi chrash tutto
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    UINT size = m_newFillInformation.size();
Shinya Kitaoka 120a6e
    if (!size) {
Shinya Kitaoka 120a6e
      app->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
      notifyImageChanged();
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRegion *reg;
Shinya Kitaoka 120a6e
    i = 0;
Shinya Kitaoka 120a6e
    for (; i < size; i++) {
Shinya Kitaoka 120a6e
      reg = image->getRegion(m_newFillInformation[i].m_regionId);
Shinya Kitaoka 120a6e
      assert(reg);
Shinya Kitaoka 120a6e
      if (reg) reg->setStyle(m_newFillInformation[i].m_styleId);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    app->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
    notifyImageChanged();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int getSize() const {
Shinya Kitaoka 120a6e
    return sizeof(*this) +
Shinya Kitaoka 120a6e
           (m_oldFillInformation.capacity() + m_newFillInformation.capacity()) *
Shinya Kitaoka 120a6e
               sizeof(TFilledRegionInf) +
Shinya Kitaoka 120a6e
           500;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  QString getToolName() { return QString("Vector Eraser Tool"); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int getHistoryType() { return HistoryType::EraserTool; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//  EraserTool class declaration
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class EraserTool : public TTool {
Shinya Kitaoka 120a6e
  Q_DECLARE_TR_FUNCTIONS(EraserTool)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  EraserTool();
Shinya Kitaoka 120a6e
  ~EraserTool();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ToolType getToolType() const { return TTool::LevelWriteTool; }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void draw();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void startErase(
Shinya Kitaoka 120a6e
      TVectorImageP vi,
Shinya Kitaoka 120a6e
      const TPointD &pos);  //, const TImageLocation &imageLocation);
Shinya Kitaoka 120a6e
  void erase(TVectorImageP vi, const TPointD &pos);
Shinya Kitaoka 120a6e
  void erase(TVectorImageP vi,
Shinya Kitaoka 120a6e
             TRectD &rect);  //, const TImageLocation &imageLocation);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void stopErase(TVectorImageP vi);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void leftButtonDown(const TPointD &pos, const TMouseEvent &e);
Shinya Kitaoka 120a6e
  void leftButtonDrag(const TPointD &pos, const TMouseEvent &e);
Shinya Kitaoka 120a6e
  void leftButtonUp(const TPointD &pos, const TMouseEvent &);
Shinya Kitaoka 120a6e
  void leftButtonDoubleClick(const TPointD &pos, const TMouseEvent &e);
Shinya Kitaoka 120a6e
  void mouseMove(const TPointD &pos, const TMouseEvent &e);
Shinya Kitaoka 120a6e
  bool onPropertyChanged(std::string propertyName);
Shinya Kitaoka 120a6e
  void onEnter();
Shinya Kitaoka 120a6e
  void onLeave();
Shinya Kitaoka 120a6e
  void onActivate();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TPropertyGroup *getProperties(int targetType) { return &m_prop; }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int getCursorId() const { return ToolCursor::EraserCursor; }
Shinya Kitaoka 120a6e
  void onImageChanged();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /*-- ドラッグ中にツールが切り替わった場合、Eraseの終了処理を行う --*/
Shinya Kitaoka 120a6e
  void onDeactivate();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  TPropertyGroup m_prop;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TEnumProperty m_eraseType;
Shinya Kitaoka 120a6e
  TDoubleProperty m_toolSize;
Shinya Kitaoka 120a6e
  TBoolProperty m_selective;
Shinya Kitaoka 120a6e
  TBoolProperty m_invertOption;
Shinya Kitaoka 120a6e
  TBoolProperty m_multi;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double m_pointSize, m_distance2;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TPointD m_mousePos,  //!< Current mouse position.
Shinya Kitaoka 120a6e
      m_oldMousePos,   //!< Previous mouse position.
Shinya Kitaoka 120a6e
      m_brushPos,      //!< Position the brush will be painted at.
Shinya Kitaoka 120a6e
      m_firstPos;      //!< Either The first point inserted either in m_track or
Shinya Kitaoka 120a6e
                       //!m_polyline
Shinya Kitaoka 120a6e
                       //!  (depending on selected erase mode).
Shinya Kitaoka 120a6e
  UndoEraser *m_undo;
Shinya Kitaoka 120a6e
  std::vector<int> m_indexes;</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRectD m_selectingRect, m_firstRect;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TFrameId m_firstFrameId, m_veryFirstFrameId;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshSimpleLevelP m_level;
Shinya Kitaoka 120a6e
  std::pair<int, int=""> m_currCell;</int,>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  StrokeGenerator m_track;  //!< Lazo selection generator.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::vector<tpointd> m_polyline;  //!< Polyline points.</tpointd>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TStroke *m_stroke;  //!< Stores the stroke generated by m_track.
Shinya Kitaoka 120a6e
  TStroke
Shinya Kitaoka 120a6e
      *m_firstStroke;  //!< Stores the first stroke in the "frame range" case.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double m_thick;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool m_firstTime, m_active, m_firstFrameSelected;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  void resetMulti();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void updateTranslation();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Metodi per disegnare la linea della modalita' Freehand
Shinya Kitaoka 120a6e
  void startFreehand(const TPointD &pos);
Shinya Kitaoka 120a6e
  void freehandDrag(const TPointD &pos);
Shinya Kitaoka 120a6e
  void closeFreehand(const TPointD &pos);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Metodi per disegnare la linea della modalita' Polyline
Shinya Kitaoka 120a6e
  void addPointPolyline(const TPointD &pos);
Shinya Kitaoka 120a6e
  void closePolyline(const TPointD &pos);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void eraseRegion(const TVectorImageP vi, TStroke *stroke);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void multiEraseRect(TFrameId firstFrameId, TFrameId lastFrameId,
Shinya Kitaoka 120a6e
                      TRectD firstRect, TRectD lastRect, bool invert);
Shinya Kitaoka 120a6e
  void doMultiErase(TFrameId &firstFrameId, TFrameId &lastFrameId,
Shinya Kitaoka 120a6e
                    const TStroke *firstStroke, const TStroke *lastStroke);
Shinya Kitaoka 120a6e
  void doErase(double t, const TXshSimpleLevelP &sl, const TFrameId &fid,
Shinya Kitaoka 120a6e
               const TVectorImageP &firstImage, const TVectorImageP &lastImage);
Shinya Kitaoka 120a6e
  void multiEreserRegion(TStroke *stroke, const TMouseEvent &e);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} eraserTool;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
//  EraserTool implemention
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
EraserTool::EraserTool()
Shinya Kitaoka 120a6e
    : TTool("T_Eraser")
Shinya Kitaoka 120a6e
    , m_eraseType("Type:")             // "W_ToolOptions_Erasetype"
Shinya Kitaoka 120a6e
    , m_toolSize("Size:", 1, 100, 10)  // "W_ToolOptions_EraserToolSize"
Shinya Kitaoka 120a6e
    , m_selective("Selective", false)  // "W_ToolOptions_Selective"
Shinya Kitaoka 120a6e
    , m_invertOption("Invert", false)  // "W_ToolOptions_Invert"
Shinya Kitaoka 120a6e
    , m_multi("Frame Range", false)    // "W_ToolOptions_FrameRange"
Shinya Kitaoka 120a6e
    , m_pointSize(-1)
Shinya Kitaoka 120a6e
    , m_undo(0)
Shinya Kitaoka 120a6e
    , m_currCell(-1, -1)
Shinya Kitaoka 120a6e
    , m_stroke(0)
Shinya Kitaoka 120a6e
    , m_thick(5)
Shinya Kitaoka 120a6e
    , m_active(false)
Shinya Kitaoka 120a6e
    , m_firstTime(true) {
Shinya Kitaoka 120a6e
  bind(TTool::VectorImage);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_prop.bind(m_toolSize);
Shinya Kitaoka 120a6e
  m_prop.bind(m_eraseType);
Shinya Kitaoka 120a6e
  m_eraseType.addValue(NORMAL_ERASE);
Shinya Kitaoka 120a6e
  m_eraseType.addValue(RECT_ERASE);
Shinya Kitaoka 120a6e
  m_eraseType.addValue(FREEHAND_ERASE);
Shinya Kitaoka 120a6e
  m_eraseType.addValue(POLYLINE_ERASE);
Shinya Kitaoka 120a6e
  m_prop.bind(m_selective);
Shinya Kitaoka 120a6e
  m_prop.bind(m_invertOption);
Shinya Kitaoka 120a6e
  m_prop.bind(m_multi);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_selective.setId("Selective");
Shinya Kitaoka 120a6e
  m_invertOption.setId("Invert");
Shinya Kitaoka 120a6e
  m_multi.setId("FrameRange");
Shinya Kitaoka 120a6e
  m_eraseType.setId("Type");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
EraserTool::~EraserTool() {
Shinya Kitaoka 120a6e
  if (m_stroke) delete m_stroke;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_firstStroke) delete m_firstStroke;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::updateTranslation() {
Shinya Kitaoka 120a6e
  m_toolSize.setQStringName(tr("Size:"));
Shinya Kitaoka 120a6e
  m_selective.setQStringName(tr("Selective"));
Shinya Kitaoka 120a6e
  m_invertOption.setQStringName(tr("Invert"));
Shinya Kitaoka 120a6e
  m_multi.setQStringName(tr("Frame Range"));
Shinya Kitaoka 120a6e
  m_eraseType.setQStringName(tr("Type:"));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::draw() {
Shinya Kitaoka 120a6e
  if (m_pointSize <= 0) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double pixelSize2 = getPixelSize() * getPixelSize();
Shinya Kitaoka 120a6e
  m_thick           = pixelSize2 / 2.0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TImageP image(getImage(false));
Shinya Kitaoka 120a6e
  TVectorImageP vi = image;
Shinya Kitaoka 120a6e
  if (vi) {
Shinya Kitaoka 120a6e
    bool blackBg = ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg;
Shinya Kitaoka 120a6e
    if (m_eraseType.getValue() == RECT_ERASE) {
Shinya Kitaoka 120a6e
      TPixel color = blackBg ? TPixel32::White : TPixel32::Black;
Shinya Kitaoka 120a6e
      if (m_multi.getValue() && m_firstFrameSelected)
Shinya Kitaoka 120a6e
        drawRect(m_firstRect, color, 0x3F33, true);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (m_active || (m_multi.getValue() && !m_firstFrameSelected))
Shinya Kitaoka 120a6e
        drawRect(m_selectingRect, color, 0x3F33, true);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (m_eraseType.getValue() == NORMAL_ERASE) {
Shinya Kitaoka 120a6e
      tglColor(TPixel32(255, 0, 255));
Shinya Kitaoka 120a6e
      tglDrawCircle(m_brushPos, m_pointSize);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if ((m_eraseType.getValue() == FREEHAND_ERASE ||
Shinya Kitaoka 120a6e
         m_eraseType.getValue() == POLYLINE_ERASE) &&
Shinya Kitaoka 120a6e
        m_multi.getValue()) {
Shinya Kitaoka 120a6e
      TPixel color = blackBg ? TPixel32::White : TPixel32::Black;
Shinya Kitaoka 120a6e
      tglColor(color);
Shinya Kitaoka 120a6e
      if (m_firstStroke) drawStrokeCenterline(*m_firstStroke, 1);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (m_eraseType.getValue() == POLYLINE_ERASE && !m_polyline.empty()) {
Shinya Kitaoka 120a6e
      TPixel color = blackBg ? TPixel32::White : TPixel32::Black;
Shinya Kitaoka 120a6e
      tglColor(color);
Shinya Kitaoka 120a6e
      tglDrawCircle(m_polyline[0], 2);
Shinya Kitaoka 120a6e
      glBegin(GL_LINE_STRIP);
Shinya Kitaoka 120a6e
      for (UINT i = 0; i < m_polyline.size(); i++) tglVertex(m_polyline[i]);
Shinya Kitaoka 120a6e
      tglVertex(m_mousePos);
Shinya Kitaoka 120a6e
      glEnd();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::resetMulti() {
Shinya Kitaoka 120a6e
  m_firstFrameSelected = false;
Shinya Kitaoka 120a6e
  m_firstRect.empty();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_selectingRect.empty();
Shinya Kitaoka 120a6e
  TTool::Application *application = TTool::getApplication();
Shinya Kitaoka 120a6e
  if (!application) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_firstFrameId = m_veryFirstFrameId = getCurrentFid();
Shinya Kitaoka 120a6e
  m_level = application->getCurrentLevel()->getLevel()
Shinya Kitaoka 120a6e
                ? application->getCurrentLevel()->getLevel()->getSimpleLevel()
Shinya Kitaoka 120a6e
                : 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_firstStroke) {
Shinya Kitaoka 120a6e
    delete m_firstStroke;
Shinya Kitaoka 120a6e
    m_firstStroke = 0;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::startErase(
Shinya Kitaoka 120a6e
    TVectorImageP vi,
Shinya Kitaoka 120a6e
    const TPointD &pos)  //, const TImageLocation &imageLocation)
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 120a6e
  UINT size = vi->getStrokeCount();
Shinya Kitaoka 120a6e
  m_indexes.resize(size);
Shinya Kitaoka 120a6e
  for (UINT i = 0; i < size; i++) m_indexes[i] = i;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(m_undo == 0);
Shinya Kitaoka 120a6e
  delete m_undo;
Shinya Kitaoka 120a6e
  TXshSimpleLevel *level =
Shinya Kitaoka 120a6e
      TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Shinya Kitaoka 120a6e
  m_undo        = new UndoEraser(level, getCurrentFid());
Shinya Kitaoka 120a6e
  m_oldMousePos = pos;
Shinya Kitaoka 120a6e
  m_distance2   = minDistance2 * getPixelSize() * getPixelSize();
Shinya Kitaoka 120a6e
  erase(vi, pos);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::erase(TVectorImageP vi, const TPointD &pos) {
Shinya Kitaoka 120a6e
  std::vector<int>::iterator it = m_indexes.begin();</int>
Shinya Kitaoka 120a6e
  m_distance2 += tdistance2(m_oldMousePos, pos);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_distance2 < minDistance2 * getPixelSize() * getPixelSize()) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_distance2   = 0;
Shinya Kitaoka 120a6e
  m_oldMousePos = pos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // quadrato circoscritto alla circonferenza
Shinya Kitaoka 120a6e
  TRectD circumscribedSquare(pos.x - m_pointSize, pos.y - m_pointSize,
Shinya Kitaoka 120a6e
                             pos.x + m_pointSize, pos.y + m_pointSize);
Shinya Kitaoka 120a6e
  if (!circumscribedSquare.overlaps(vi->getBBox())) {
Shinya Kitaoka 120a6e
    invalidate();
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<double> intersections;</double>
Shinya Kitaoka 120a6e
  std::vector<doublepair> sortedWRanges;</doublepair>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<tstroke *=""> splitStrokes;</tstroke>
Shinya Kitaoka 120a6e
  double rectEdge_2 = m_pointSize * M_SQRT1_2;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // quadrato iscritto nella circonferenza
Shinya Kitaoka 120a6e
  TRectD enrolledSquare(pos.x - rectEdge_2, pos.y - rectEdge_2,
Shinya Kitaoka 120a6e
                        pos.x + rectEdge_2, pos.y + rectEdge_2);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  UINT i            = 0;
Shinya Kitaoka 120a6e
  double pointSize2 = sq(m_pointSize);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<int> oneStrokeIndex(1);</int>
Shinya Kitaoka 120a6e
  int index = TTool::getApplication()->getCurrentLevelStyleIndex();
Shinya Kitaoka 120a6e
  QMutexLocker lock(vi->getMutex());
Shinya Kitaoka 120a6e
  while (i < vi->getStrokeCount()) {
Shinya Kitaoka 120a6e
    assert(it != m_indexes.end());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TStroke *oldStroke = vi->getStroke(i);
Shinya Kitaoka 120a6e
    if (!vi->inCurrentGroup(i) ||
Shinya Kitaoka 120a6e
        (m_selective.getValue() && oldStroke->getStyle() != index)) {
Shinya Kitaoka 120a6e
      i++;
Shinya Kitaoka 120a6e
      it++;
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRectD strokeBBox = oldStroke->getBBox();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (!circumscribedSquare.overlaps(strokeBBox)) {  // stroke all'esterno del
Shinya Kitaoka 120a6e
                                                      // quadrato circoscritto
Shinya Kitaoka 120a6e
                                                      // alla circonferenxa
Shinya Kitaoka 120a6e
      i++;
Shinya Kitaoka 120a6e
      it++;
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (enrolledSquare.contains(strokeBBox)) {  // stroke tutta contenuta nel
Shinya Kitaoka 120a6e
                                                // quadrato iscritto nella
Shinya Kitaoka 120a6e
                                                // circonferenza
Shinya Kitaoka 120a6e
      if (*it != -1) m_undo->addOldStroke(*it, vi->getVIStroke(i));
Shinya Kitaoka 120a6e
      oneStrokeIndex[0] = i;
Shinya Kitaoka 120a6e
      vi->removeStrokes(oneStrokeIndex, true, true);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      it = m_indexes.erase(it);
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    splitStrokes.clear();
Shinya Kitaoka 120a6e
    intersections.clear();
Shinya Kitaoka 120a6e
    /*int intersNum=*/intersect(*oldStroke, pos, m_pointSize, intersections);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /*
Shinya Kitaoka 120a6e
#ifdef _DEBUG
Shinya Kitaoka 120a6e
if(intersections.size()==2 && intersections[0]==intersections[1])
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 120a6e
intersections.clear();
Shinya Kitaoka 120a6e
intersect( *oldStroke, pos, m_pointSize, intersections );
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
#endif
Shinya Kitaoka 120a6e
*/
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (intersections.empty()) {
Shinya Kitaoka 120a6e
      // BASTEREBBE CONTROLLARE UN SOLO PUNTO PERCHE' SE LA
Shinya Kitaoka 120a6e
      // STROKE NON INTERSECA IL CERCHIO E CONTENTIENE ALMENO
Shinya Kitaoka 120a6e
      // UN PUNTO, LA CONTIENE TUTTA. MA SICCOME NON MI FIDO
Shinya Kitaoka 120a6e
      // DELLA INTERSECT, NE CONTROLLO UN PAIO E AVVANTAGGIO (CON L' AND)
Shinya Kitaoka 120a6e
      // IL NON CONTENIMENTO, DATO CHE E' MEGLIO CANCELLARE UNA COSA IN
Shinya Kitaoka 120a6e
      // MENO, CHE UNA IN PIU'
Shinya Kitaoka 120a6e
      if (tdistance2(oldStroke->getPoint(0), pos) < pointSize2 &&
Shinya Kitaoka 120a6e
          tdistance2(oldStroke->getPoint(1), pos) <
Shinya Kitaoka 120a6e
              pointSize2) {  // stroke tutta contenuta nella circonferenxa
Shinya Kitaoka 120a6e
        if (*it != -1) m_undo->addOldStroke(*it, vi->getVIStroke(i));
Shinya Kitaoka 120a6e
        oneStrokeIndex[0] = i;
Shinya Kitaoka 120a6e
        vi->removeStrokes(oneStrokeIndex, true, true);
Shinya Kitaoka 120a6e
        it = m_indexes.erase(it);
Shinya Kitaoka 120a6e
      } else {  // non colpita
Shinya Kitaoka 120a6e
        i++;
Shinya Kitaoka 120a6e
        it++;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //------------------------ almeno un'intersezione
Shinya Kitaoka 120a6e
    //---------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (intersections.size() == 1) {
Shinya Kitaoka 120a6e
      if (oldStroke->isSelfLoop()) {  // una sola intersezione di una stroke
Shinya Kitaoka 120a6e
                                      // chiusa con un cerchio dovrebbe accadere
Shinya Kitaoka 120a6e
        // solo in caso di sfioramento, quindi faccio finta di nulla
Shinya Kitaoka 120a6e
        i++;
Shinya Kitaoka 120a6e
        it++;
Shinya Kitaoka 120a6e
        continue;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (*it != -1) m_undo->addOldStroke(*it, vi->getVIStroke(i));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      double w0            = intersections[0];
Shinya Kitaoka 120a6e
      TThickPoint hitPoint = oldStroke->getThickPoint(w0);
Shinya Kitaoka 120a6e
      int chunck;
Shinya Kitaoka 120a6e
      double t;
Shinya Kitaoka 120a6e
      oldStroke->getChunkAndT(w0, chunck, t);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int chunckIndex;
Shinya Kitaoka 120a6e
      double w1;
Shinya Kitaoka 120a6e
      if (tdistance2(oldStroke->getPoint(0), pos) < pointSize2) {
Shinya Kitaoka 120a6e
        chunckIndex = oldStroke->getChunkCount() - 1;
Shinya Kitaoka 120a6e
        w1          = 1;
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        chunckIndex = 0;
Shinya Kitaoka 120a6e
        w1          = 0;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      UINT cI;
Shinya Kitaoka 120a6e
      std::vector<tthickpoint> points;</tthickpoint>
Shinya Kitaoka 120a6e
      if (w1 == 0) {
Shinya Kitaoka 120a6e
        for (cI = chunckIndex; cI < (UINT)chunck; cI++) {
Shinya Kitaoka 120a6e
          points.push_back(oldStroke->getChunk(cI)->getThickP0());
Shinya Kitaoka 120a6e
          points.push_back(oldStroke->getChunk(cI)->getThickP1());
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        TThickQuadratic t1, t2;
Shinya Kitaoka 120a6e
        oldStroke->getChunk(chunck)->split(t, t1, t2);
Shinya Kitaoka 120a6e
        points.push_back(t1.getThickP0());
Shinya Kitaoka 120a6e
        points.push_back(t1.getThickP1());
Shinya Kitaoka 120a6e
        points.push_back(hitPoint);
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        TThickQuadratic t1, t2;
Shinya Kitaoka 120a6e
        oldStroke->getChunk(chunck)->split(t, t1, t2);
Shinya Kitaoka 120a6e
        points.push_back(hitPoint);
Shinya Kitaoka 120a6e
        points.push_back(t2.getThickP1());
Shinya Kitaoka 120a6e
        points.push_back(t2.getThickP2());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        for (cI = chunck + 1; cI <= (UINT)chunckIndex; cI++) {
Shinya Kitaoka 120a6e
          points.push_back(oldStroke->getChunk(cI)->getThickP1());
Shinya Kitaoka 120a6e
          points.push_back(oldStroke->getChunk(cI)->getThickP2());
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      oldStroke->reshape(&(points[0]), points.size());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      vi->notifyChangedStrokes(i);  // per adesso cosi', pero' e' lento
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      *it = -1;
Shinya Kitaoka 120a6e
      i++;
Shinya Kitaoka 120a6e
      it++;
Shinya Kitaoka 120a6e
      continue;
Toshihiro Shimizu 890ddd
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //---------- piu'
Shinya Kitaoka 120a6e
    //intersezioni--------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (intersections.size() & 1 &&
Shinya Kitaoka 120a6e
        oldStroke->isSelfLoop()) {  // non dovrebbe mai accadere
Shinya Kitaoka 120a6e
      assert(0);
Shinya Kitaoka 120a6e
      i++;
Shinya Kitaoka 120a6e
      it++;
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (intersections.size() == 2 &&
Shinya Kitaoka 120a6e
        intersections[0] == intersections[1]) {  // solo sfiorata
Shinya Kitaoka 120a6e
      i++;
Shinya Kitaoka 120a6e
      it++;
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    UINT oldStrokeSize = vi->getStrokeCount();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (*it != -1) m_undo->addOldStroke(*it, vi->getVIStroke(i));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    sortedWRanges.clear();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (tdistance2(vi->getStroke(i)->getPoint(0), pos) > pointSize2) {
Shinya Kitaoka 120a6e
      if (intersections[0] == 0.0)
Shinya Kitaoka 120a6e
        intersections.erase(intersections.begin());
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        intersections.insert(intersections.begin(), 0.0);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (intersections[0] != 1.0) intersections.push_back(1.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    sortedWRanges.reserve(intersections.size() / 2);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (UINT j = 0; j < intersections.size() - 1; j += 2)
Shinya Kitaoka 120a6e
      sortedWRanges.push_back(
Shinya Kitaoka 120a6e
          std::make_pair(intersections[j], intersections[j + 1]));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    for (UINT kkk = 0; kkk < sortedWRanges.size() - 1; kkk++) {
Shinya Kitaoka 120a6e
      assert(sortedWRanges[kkk].first < sortedWRanges[kkk].second);
Shinya Kitaoka 120a6e
      assert(sortedWRanges[kkk].second <= sortedWRanges[kkk + 1].first);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    assert(sortedWRanges.back().first < sortedWRanges.back().second);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    vi->splitStroke(i, sortedWRanges);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    UINT addedStroke = vi->getStrokeCount() -
Shinya Kitaoka 120a6e
                       (oldStrokeSize - 1);  //-1 perche' e' quella tolta
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    i += addedStroke;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    *it = -1;
Shinya Kitaoka 120a6e
    m_indexes.insert(it, addedStroke - 1, -1);
Shinya Kitaoka 120a6e
    it = m_indexes.begin() + i;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::erase(TVectorImageP vi, TRectD &rect) {
Shinya Kitaoka 120a6e
  if (rect.x0 > rect.x1) tswap(rect.x1, rect.x0);
Shinya Kitaoka 120a6e
  if (rect.y0 > rect.y1) tswap(rect.y1, rect.y0);
Shinya Kitaoka 120a6e
  int i     = 0;
Shinya Kitaoka 120a6e
  int index = TTool::getApplication()->getCurrentLevelStyleIndex();
Shinya Kitaoka 120a6e
  std::vector<int> eraseStrokes;</int>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TXshSimpleLevel *level =
Shinya Kitaoka 120a6e
      TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Shinya Kitaoka 120a6e
  m_undo = new UndoEraser(level, getCurrentFid());
Shinya Kitaoka 120a6e
  for (i = 0; i < (int)vi->getStrokeCount(); i++) {
Shinya Kitaoka 120a6e
    if (!vi->inCurrentGroup(i)) continue;
Shinya Kitaoka 120a6e
    TStroke *stroke = vi->getStroke(i);
Shinya Kitaoka 120a6e
    if (!m_invertOption.getValue()) {
Shinya Kitaoka 120a6e
      if ((!m_selective.getValue() || stroke->getStyle() == index) &&
Shinya Kitaoka 120a6e
          rect.contains(stroke->getBBox())) {
Shinya Kitaoka 120a6e
        m_undo->addOldStroke(i, vi->getVIStroke(i));
Shinya Kitaoka 120a6e
        eraseStrokes.push_back(i);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      if ((!m_selective.getValue() || stroke->getStyle() == index) &&
Shinya Kitaoka 120a6e
          !rect.contains(stroke->getBBox())) {
Shinya Kitaoka 120a6e
        m_undo->addOldStroke(i, vi->getVIStroke(i));
Shinya Kitaoka 120a6e
        eraseStrokes.push_back(i);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (i = (int)eraseStrokes.size() - 1; i >= 0; i--)
Shinya Kitaoka 120a6e
    vi->deleteStroke(eraseStrokes[i]);
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(m_undo);
Shinya Kitaoka 120a6e
  m_undo = 0;
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::stopErase(TVectorImageP vi) {
Shinya Kitaoka 120a6e
  assert(m_undo != 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  UINT size = m_indexes.size();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(size == vi->getStrokeCount());
Shinya Kitaoka 120a6e
  UINT i = 0;
Shinya Kitaoka 120a6e
  for (; i < size; i++) {
Shinya Kitaoka 120a6e
    if (m_indexes[i] == -1) m_undo->addNewStroke(i, vi->getVIStroke(i));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(m_undo);
Shinya Kitaoka 120a6e
  m_undo = 0;
Shinya Kitaoka 120a6e
  invalidate();
Shinya Kitaoka 120a6e
  notifyImageChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  m_brushPos = m_mousePos = pos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_active = true;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TImageP image(getImage(true));
Shinya Kitaoka 120a6e
  if (m_eraseType.getValue() == NORMAL_ERASE) {
Shinya Kitaoka 120a6e
    if (TVectorImageP vi = image) startErase(vi, pos /*,imageLocation*/);
Shinya Kitaoka 120a6e
  } else if (m_eraseType.getValue() == RECT_ERASE) {
Shinya Kitaoka 120a6e
    m_selectingRect.x0 = pos.x;
Shinya Kitaoka 120a6e
    m_selectingRect.y0 = pos.y;
Shinya Kitaoka 120a6e
    m_selectingRect.x1 = pos.x + 1;
Shinya Kitaoka 120a6e
    m_selectingRect.y1 = pos.y + 1;
Shinya Kitaoka 120a6e
    invalidate();
Shinya Kitaoka 120a6e
  } else if (m_eraseType.getValue() == FREEHAND_ERASE) {
Shinya Kitaoka 120a6e
    startFreehand(pos);
Shinya Kitaoka 120a6e
  } else if (m_eraseType.getValue() == POLYLINE_ERASE) {
Shinya Kitaoka 120a6e
    addPointPolyline(pos);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  m_brushPos = m_mousePos = pos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_active) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TImageP image(getImage(true));
Shinya Kitaoka 120a6e
  if (m_eraseType.getValue() == RECT_ERASE) {
Shinya Kitaoka 120a6e
    m_selectingRect.x1 = pos.x;
Shinya Kitaoka 120a6e
    m_selectingRect.y1 = pos.y;
Shinya Kitaoka 120a6e
    invalidate();
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  } else if (m_eraseType.getValue() == NORMAL_ERASE) {
Shinya Kitaoka 120a6e
    if (TVectorImageP vi = image) erase(vi, pos);
Shinya Kitaoka 120a6e
  } else if (m_eraseType.getValue() == FREEHAND_ERASE) {
Shinya Kitaoka 120a6e
    freehandDrag(pos);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void EraserTool::multiEraseRect(TFrameId firstFrameId, TFrameId lastFrameId,
Shinya Kitaoka 120a6e
                                TRectD firstRect, TRectD lastRect,
Shinya Kitaoka 120a6e
                                bool invert) {
Shinya Kitaoka 120a6e
  int r0 = firstFrameId.getNumber();
Shinya Kitaoka 120a6e
  int r1 = lastFrameId.getNumber();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (r0 > r1) {
Shinya Kitaoka 120a6e
    tswap(r0, r1);
Shinya Kitaoka 120a6e
    tswap(firstFrameId, lastFrameId);
Shinya Kitaoka 120a6e
    tswap(firstRect, lastRect);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if ((r1 - r0) < 1) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<tframeid> allFids;</tframeid>
Shinya Kitaoka 120a6e
  m_level->getFids(allFids);
Shinya Kitaoka 120a6e
  std::vector<tframeid>::iterator i0 = allFids.begin();</tframeid>
Shinya Kitaoka 120a6e
  while (i0 != allFids.end() && *i0 < firstFrameId) i0++;
Shinya Kitaoka 120a6e
  if (i0 == allFids.end()) return;
Shinya Kitaoka 120a6e
  std::vector<tframeid>::iterator i1 = i0;</tframeid>
Shinya Kitaoka 120a6e
  while (i1 != allFids.end() && *i1 <= lastFrameId) i1++;
Shinya Kitaoka 120a6e
  assert(i0 < i1);
Shinya Kitaoka 120a6e
  std::vector<tframeid> fids(i0, i1);</tframeid>
Shinya Kitaoka 120a6e
  int m = fids.size();
Shinya Kitaoka 120a6e
  assert(m > 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TUndoManager::manager()->beginBlock();
Shinya Kitaoka 120a6e
  for (int i = 0; i < m; ++i) {
Shinya Kitaoka 120a6e
    TFrameId fid = fids[i];
Shinya Kitaoka 120a6e
    assert(firstFrameId <= fid && fid <= lastFrameId);
Shinya Kitaoka 120a6e
    TVectorImageP img = (TVectorImageP)m_level->getFrame(fid, true);
Shinya Kitaoka 120a6e
    assert(img);
Shinya Kitaoka 120a6e
    double t    = m > 1 ? (double)i / (double)(m - 1) : 0.5;
Shinya Kitaoka 120a6e
    TRectD rect = interpolateRect(firstRect, lastRect, t);
Shinya Kitaoka 120a6e
    // m_level->setFrame(fid, img); //necessario: se la getFrame ha scompattato
Shinya Kitaoka 120a6e
    // una img compressa, senza setFrame le modifiche sulla img fatte qui
Shinya Kitaoka 120a6e
    // andrebbero perse.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Setto fid come corrente per notificare il cambiamento dell'immagine
Shinya Kitaoka 120a6e
    TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
    if (app) {
Shinya Kitaoka 120a6e
      if (app->getCurrentFrame()->isEditingScene())
Shinya Kitaoka 120a6e
        app->getCurrentFrame()->setFrame(fid.getNumber() - 1);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        app->getCurrentFrame()->setFid(fid);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    erase(img, rect);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    notifyImageChanged();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  TUndoManager::manager()->endBlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::onImageChanged() {
Shinya Kitaoka 120a6e
  if (!m_multi.getValue()) return;
Shinya Kitaoka 120a6e
  TTool::Application *application = TTool::getApplication();
Shinya Kitaoka 120a6e
  if (!application) return;
Shinya Kitaoka 120a6e
  TXshSimpleLevel *xshl = 0;
Shinya Kitaoka 120a6e
  if (application->getCurrentLevel()->getLevel())
Shinya Kitaoka 120a6e
    xshl = application->getCurrentLevel()->getLevel()->getSimpleLevel();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!xshl || m_level.getPointer() != xshl ||
Shinya Kitaoka 120a6e
      (m_eraseType.getValue() == RECT_ERASE && m_selectingRect.isEmpty()) ||
Shinya Kitaoka 120a6e
      ((m_eraseType.getValue() == FREEHAND_ERASE ||
Shinya Kitaoka 120a6e
        m_eraseType.getValue() == POLYLINE_ERASE) &&
Shinya Kitaoka 120a6e
       !m_firstStroke))
Shinya Kitaoka 120a6e
    resetMulti();
Shinya Kitaoka 120a6e
  else if (m_firstFrameId == getCurrentFid())
Shinya Kitaoka 120a6e
    m_firstFrameSelected = false;  // nel caso sono passato allo stato 1 e torno
Shinya Kitaoka 120a6e
                                   // all'immagine iniziale, torno allo stato
Shinya Kitaoka 120a6e
                                   // iniziale
Shinya Kitaoka 120a6e
  else {  // cambio stato.
Shinya Kitaoka 120a6e
    m_firstFrameSelected = true;
Shinya Kitaoka 120a6e
    if (m_eraseType.getValue() == RECT_ERASE) {
Shinya Kitaoka 120a6e
      assert(!m_selectingRect.isEmpty());
Shinya Kitaoka 120a6e
      m_firstRect = m_selectingRect;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  if (!m_active) return;
Shinya Kitaoka 120a6e
  TImageP image(getImage(true));
Shinya Kitaoka 120a6e
  TVectorImageP vi = image;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TTool::Application *application = TTool::getApplication();
Shinya Kitaoka 120a6e
  if (!vi || !application) return;
Shinya Kitaoka 120a6e
  if (m_eraseType.getValue() == NORMAL_ERASE)
Shinya Kitaoka 120a6e
    stopErase(vi);
Shinya Kitaoka 120a6e
  else if (m_eraseType.getValue() == RECT_ERASE) {
Shinya Kitaoka 120a6e
    if (m_selectingRect.x0 > m_selectingRect.x1)
Shinya Kitaoka 120a6e
      tswap(m_selectingRect.x1, m_selectingRect.x0);
Shinya Kitaoka 120a6e
    if (m_selectingRect.y0 > m_selectingRect.y1)
Shinya Kitaoka 120a6e
      tswap(m_selectingRect.y1, m_selectingRect.y0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_multi.getValue()) {
Shinya Kitaoka 120a6e
      if (m_firstFrameSelected) {
Shinya Kitaoka 120a6e
        multiEraseRect(m_firstFrameId, getCurrentFid(), m_firstRect,
Shinya Kitaoka 120a6e
                       m_selectingRect, m_invertOption.getValue());
Shinya Kitaoka 120a6e
        invalidate();  // invalidate(m_selectingRect.enlarge(2));
Shinya Kitaoka 120a6e
        if (e.isShiftPressed()) {
Shinya Kitaoka 120a6e
          m_firstRect    = m_selectingRect;
Shinya Kitaoka 120a6e
          m_firstFrameId = getCurrentFid();
Shinya Kitaoka 120a6e
        } else {
Shinya Kitaoka 120a6e
          if (application->getCurrentFrame()->isEditingScene()) {
Shinya Kitaoka 120a6e
            application->getCurrentColumn()->setColumnIndex(m_currCell.first);
Shinya Kitaoka 120a6e
            application->getCurrentFrame()->setFrame(m_currCell.second);
Shinya Kitaoka 120a6e
          } else
Shinya Kitaoka 120a6e
            application->getCurrentFrame()->setFid(m_veryFirstFrameId);
Shinya Kitaoka 120a6e
          resetMulti();
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        if (application->getCurrentFrame()->isEditingScene())
Shinya Kitaoka 120a6e
          m_currCell = std::pair<int, int="">(</int,>
Shinya Kitaoka 120a6e
              application->getCurrentColumn()->getColumnIndex(),
Shinya Kitaoka 120a6e
              application->getCurrentFrame()->getFrame());
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      erase(vi, m_selectingRect);
Shinya Kitaoka 120a6e
      invalidate();
Shinya Kitaoka 120a6e
      notifyImageChanged();
Shinya Kitaoka 120a6e
      m_selectingRect.empty();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else if (m_eraseType.getValue() == FREEHAND_ERASE) {
Shinya Kitaoka 120a6e
    closeFreehand(pos);
Shinya Kitaoka 120a6e
    if (m_multi.getValue()) {
Shinya Kitaoka 120a6e
      multiEreserRegion(m_stroke, e);
Shinya Kitaoka 120a6e
      invalidate();
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      eraseRegion(vi, m_stroke);
Shinya Kitaoka 120a6e
      invalidate();
Shinya Kitaoka 120a6e
      notifyImageChanged();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  m_active = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Viene chiusa la polyline e si da il via alla cancellazione.
Shinya Kitaoka 120a6e
/*!Viene creato lo \b stroke rappresentante la polyline disegnata.
Shinya Kitaoka 120a6e
  Se e' selzionato il metodo di cancellazione "frame range" viene richiamato il
Shinya Kitaoka 120a6e
  metodo \b multiEreserRegion, altrimenti
Toshihiro Shimizu 890ddd
  viene richiamato il metodo \b eraseRegion*/
Shinya Kitaoka 120a6e
void EraserTool::leftButtonDoubleClick(const TPointD &pos,
Shinya Kitaoka 120a6e
                                       const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  TVectorImageP vi = getImage(true);
Shinya Kitaoka 120a6e
  if (m_eraseType.getValue() == POLYLINE_ERASE) {
Shinya Kitaoka 120a6e
    closePolyline(pos);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    std::vector<tthickpoint> strokePoints;</tthickpoint>
Shinya Kitaoka 120a6e
    for (UINT i = 0; i < m_polyline.size() - 1; i++) {
Shinya Kitaoka 120a6e
      strokePoints.push_back(TThickPoint(m_polyline[i], 1));
Shinya Kitaoka 120a6e
      strokePoints.push_back(
Shinya Kitaoka 120a6e
          TThickPoint(0.5 * (m_polyline[i] + m_polyline[i + 1]), 1));
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    strokePoints.push_back(TThickPoint(m_polyline.back(), 1));
Shinya Kitaoka 120a6e
    m_polyline.clear();
Shinya Kitaoka 120a6e
    TStroke *stroke = new TStroke(strokePoints);
Shinya Kitaoka 120a6e
    assert(stroke->getPoint(0) == stroke->getPoint(1));
Shinya Kitaoka 120a6e
    if (m_multi.getValue())
Shinya Kitaoka 120a6e
      multiEreserRegion(stroke, e);
Shinya Kitaoka 120a6e
    else {
Shinya Kitaoka 120a6e
      eraseRegion(vi, stroke);
Shinya Kitaoka 120a6e
      notifyImageChanged();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    invalidate();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::mouseMove(const TPointD &pos, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  struct Locals {
Shinya Kitaoka 120a6e
    EraserTool *m_this;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    void setValue(TDoubleProperty &prop, double value) {
Shinya Kitaoka 120a6e
      prop.setValue(value);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      m_this->onPropertyChanged(prop.getName());
Shinya Kitaoka 120a6e
      TTool::getApplication()->getCurrentTool()->notifyToolChanged();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    void addValue(TDoubleProperty &prop, double add) {
Shinya Kitaoka 120a6e
      const TDoubleProperty::Range &range = prop.getRange();
Shinya Kitaoka 120a6e
      setValue(prop, tcrop(prop.getValue() + add, range.first, range.second));
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  } locals = {this};
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  switch (e.getModifiersMask()) {
Shinya Kitaoka 120a6e
  case TMouseEvent::ALT_KEY: {
Shinya Kitaoka 120a6e
    // User wants to alter the maximum brush size
Shinya Kitaoka 120a6e
    const TPointD &diff = pos - m_mousePos;
Shinya Kitaoka 120a6e
    double add          = (fabs(diff.x) > fabs(diff.y)) ? diff.x : diff.y;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    locals.addValue(m_toolSize, add);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  default:
Shinya Kitaoka 120a6e
    m_brushPos = pos;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_oldMousePos = m_mousePos = pos;
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool EraserTool::onPropertyChanged(std::string propertyName) {
Shinya Kitaoka 120a6e
  EraseVectorType      = ::to_string(m_eraseType.getValue());
Shinya Kitaoka 120a6e
  EraseVectorSize      = m_toolSize.getValue();
Shinya Kitaoka 120a6e
  EraseVectorSelective = m_selective.getValue();
Shinya Kitaoka 120a6e
  EraseVectorInvert    = m_invertOption.getValue();
Shinya Kitaoka 120a6e
  EraseVectorRange     = m_multi.getValue();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double x = m_toolSize.getValue();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double minRange = 1;
Shinya Kitaoka 120a6e
  double maxRange = 100;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double minSize = 2;
Shinya Kitaoka 120a6e
  double maxSize = 100;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_pointSize =
Shinya Kitaoka 120a6e
      ((x - minRange) / (maxRange - minRange) * (maxSize - minSize) + minSize) *
Shinya Kitaoka 120a6e
      0.5;
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::onEnter() {
Shinya Kitaoka 120a6e
  if (m_firstTime) {
Shinya Kitaoka 120a6e
    m_toolSize.setValue(EraseVectorSize);
Shinya Kitaoka 120a6e
    m_eraseType.setValue(::to_wstring(EraseVectorType.getValue()));
Shinya Kitaoka 120a6e
    m_selective.setValue(EraseVectorSelective ? 1 : 0);
Shinya Kitaoka 120a6e
    m_invertOption.setValue(EraseVectorInvert ? 1 : 0);
Shinya Kitaoka 120a6e
    m_multi.setValue(EraseVectorRange ? 1 : 0);
Shinya Kitaoka 120a6e
    m_firstTime = false;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double x = m_toolSize.getValue();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double minRange = 1;
Shinya Kitaoka 120a6e
  double maxRange = 100;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double minSize = 2;
Shinya Kitaoka 120a6e
  double maxSize = 100;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_pointSize =
Shinya Kitaoka 120a6e
      ((x - minRange) / (maxRange - minRange) * (maxSize - minSize) + minSize) *
Shinya Kitaoka 120a6e
      0.5;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //  getApplication()->editImage();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::onLeave() {
Shinya Kitaoka 120a6e
  draw();
Shinya Kitaoka 120a6e
  m_pointSize = -1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::onActivate() {
Shinya Kitaoka 120a6e
  resetMulti();
Shinya Kitaoka 120a6e
  onEnter();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Viene aggiunto \b pos a \b m_track e disegnato il primo pezzetto del lazzo.
Shinya Kitaoka 120a6e
//! Viene inizializzato \b m_firstPos
Shinya Kitaoka 120a6e
void EraserTool::startFreehand(const TPointD &pos) {
Shinya Kitaoka 120a6e
  m_track.clear();
Shinya Kitaoka 120a6e
  m_firstPos = pos;
Shinya Kitaoka 120a6e
  m_track.add(TThickPoint(pos, m_thick), getPixelSize() * getPixelSize());
Shinya Kitaoka 120a6e
  TPointD dpiScale = m_viewer->getDpiScale();
Toshihiro Shimizu 890ddd
#if defined(MACOSX)
Toshihiro Shimizu 890ddd
//			m_viewer->prepareForegroundDrawing();
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  //	m_viewer->makeCurrent();
Shinya Kitaoka 120a6e
  TPixel color = ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg
Shinya Kitaoka 120a6e
                     ? TPixel32::White
Shinya Kitaoka 120a6e
                     : TPixel32::Black;
Shinya Kitaoka 120a6e
  tglColor(color);
Shinya Kitaoka 120a6e
  m_viewer->startForegroundDrawing();
Shinya Kitaoka 120a6e
  glPushMatrix();
Shinya Kitaoka 120a6e
  tglMultMatrix(getMatrix());
Shinya Kitaoka 120a6e
  glScaled(dpiScale.x, dpiScale.y, 1);
Shinya Kitaoka 120a6e
  m_track.drawLastFragments();
Shinya Kitaoka 120a6e
  glPopMatrix();
Shinya Kitaoka 120a6e
  m_viewer->endForegroundDrawing();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Viene aggiunto \b pos a \b m_track e disegnato un altro pezzetto del lazzo.
Shinya Kitaoka 120a6e
void EraserTool::freehandDrag(const TPointD &pos) {
Toshihiro Shimizu 890ddd
#if defined(MACOSX)
Toshihiro Shimizu 890ddd
//		m_viewer->enableRedraw(false);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_viewer->startForegroundDrawing();
Shinya Kitaoka 120a6e
  TPixel color = ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg
Shinya Kitaoka 120a6e
                     ? TPixel32::White
Shinya Kitaoka 120a6e
                     : TPixel32::Black;
Shinya Kitaoka 120a6e
  tglColor(color);
Shinya Kitaoka 120a6e
  glPushMatrix();
Shinya Kitaoka 120a6e
  tglMultMatrix(getMatrix());
Shinya Kitaoka 120a6e
  TPointD dpiScale = m_viewer->getDpiScale();
Shinya Kitaoka 120a6e
  glScaled(dpiScale.x, dpiScale.y, 1);
Shinya Kitaoka 120a6e
  m_track.add(TThickPoint(pos, m_thick), getPixelSize() * getPixelSize());
Shinya Kitaoka 120a6e
  m_track.drawLastFragments();
Shinya Kitaoka 120a6e
  glPopMatrix();
Shinya Kitaoka 120a6e
  m_viewer->endForegroundDrawing();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Viene chiuso il lazzo (si aggiunge l'ultimo punto ad m_track) e viene creato
Shinya Kitaoka 120a6e
//! lo stroke rappresentante il lazzo.
Shinya Kitaoka 120a6e
void EraserTool::closeFreehand(const TPointD &pos) {
Toshihiro Shimizu 890ddd
#if defined(MACOSX)
Toshihiro Shimizu 890ddd
//		m_viewer->enableRedraw(true);
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  if (m_track.isEmpty()) return;
Shinya Kitaoka 120a6e
  m_track.add(TThickPoint(m_firstPos, m_thick),
Shinya Kitaoka 120a6e
              getPixelSize() * getPixelSize());
Shinya Kitaoka 120a6e
  m_track.filterPoints();
Shinya Kitaoka 120a6e
  double error = (30.0 / 11) * sqrt(getPixelSize() * getPixelSize());
Shinya Kitaoka 120a6e
  m_stroke     = m_track.makeStroke(error);
Shinya Kitaoka 120a6e
  m_stroke->setStyle(1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Viene aggiunto un punto al vettore m_polyline.
Shinya Kitaoka 120a6e
void EraserTool::addPointPolyline(const TPointD &pos) {
Shinya Kitaoka 120a6e
  m_firstPos = pos;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TPointD dpiScale = m_viewer->getDpiScale();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined(MACOSX)
Toshihiro Shimizu 890ddd
//		 m_viewer->prepareForegroundDrawing();
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  //      m_viewer->makeCurrent();
Shinya Kitaoka 120a6e
  TPixel color = ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg
Shinya Kitaoka 120a6e
                     ? TPixel32::White
Shinya Kitaoka 120a6e
                     : TPixel32::Black;
Shinya Kitaoka 120a6e
  tglColor(color);
Toshihiro Shimizu 890ddd
//	  m_viewer->startForegroundDrawing();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined(MACOSX)
Shinya Kitaoka 120a6e
//		m_viewer->enableRedraw(m_eraseType.getValue() ==
Shinya Kitaoka 120a6e
//POLYLINE_ERASE);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glPushMatrix();
Shinya Kitaoka 120a6e
  glScaled(dpiScale.x, dpiScale.y, 1);
Shinya Kitaoka 120a6e
  m_polyline.push_back(pos);
Shinya Kitaoka 120a6e
  glPopMatrix();
Shinya Kitaoka 120a6e
  //	  m_viewer->endForegroundDrawing();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Agginge l'ultimo pos a \b m_polyline e chiude la spezzata (aggiunge \b
Shinya Kitaoka 120a6e
//! m_polyline.front() alla fine del vettore)
Shinya Kitaoka 120a6e
void EraserTool::closePolyline(const TPointD &pos) {
Shinya Kitaoka 120a6e
  if (m_polyline.size() <= 1) return;
Shinya Kitaoka 120a6e
  if (m_polyline.back() != pos) m_polyline.push_back(pos);
Shinya Kitaoka 120a6e
  if (m_polyline.back() != m_polyline.front())
Shinya Kitaoka 120a6e
    m_polyline.push_back(m_polyline.front());
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Cancella stroke presenti in \b vi e contenuti nella regione delimitata da \b
Shinya Kitaoka 120a6e
//! stroke.
Shinya Kitaoka 120a6e
/*!Vengono cercati gli stroke da cancellare facendo i dovuti controlli sui
Shinya Kitaoka 120a6e
   parametri \b m_invertOption e \b m_selective.
Shinya Kitaoka 120a6e
        Se uno stroke deve essere cancellato viene inserito in \b eraseStrokes.
Shinya Kitaoka 120a6e
        Gli stroke vengono cancellati tutti alla fine.*/
Shinya Kitaoka 120a6e
void EraserTool::eraseRegion(
Shinya Kitaoka 120a6e
    const TVectorImageP vi,
Shinya Kitaoka 120a6e
    TStroke *stroke)  //, const TImageLocation &imageLocation)
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 120a6e
  if (!vi || !stroke) return;
Shinya Kitaoka 120a6e
  TVectorImage eraseImg;
Shinya Kitaoka 120a6e
  TStroke *eraseStroke = new TStroke(*stroke);
Shinya Kitaoka 120a6e
  eraseImg.addStroke(eraseStroke);
Shinya Kitaoka 120a6e
  eraseImg.findRegions();
Shinya Kitaoka 120a6e
  int strokeIndex, regionIndex, colorStyle;
Shinya Kitaoka 120a6e
  colorStyle = TTool::getApplication()->getCurrentLevelStyleIndex();
Shinya Kitaoka 120a6e
  std::vector<int> eraseStrokes;</int>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TXshSimpleLevel *level =
Shinya Kitaoka 120a6e
      TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Shinya Kitaoka 120a6e
  m_undo = new UndoEraser(level, getCurrentFid());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_invertOption.getValue()) {
Shinya Kitaoka 120a6e
    for (strokeIndex = 0; strokeIndex < (int)vi->getStrokeCount();
Shinya Kitaoka 120a6e
         strokeIndex++) {
Shinya Kitaoka 120a6e
      if (!vi->inCurrentGroup(strokeIndex)) continue;
Shinya Kitaoka 120a6e
      TStroke *currentStroke = vi->getStroke(strokeIndex);
Shinya Kitaoka 120a6e
      for (regionIndex = 0; regionIndex < (int)eraseImg.getRegionCount();
Shinya Kitaoka 120a6e
           regionIndex++) {
Shinya Kitaoka 120a6e
        TRegion *region = eraseImg.getRegion(regionIndex);
Shinya Kitaoka 120a6e
        if ((!m_selective.getValue() ||
Shinya Kitaoka 120a6e
             (m_selective.getValue() &&
Shinya Kitaoka 120a6e
              currentStroke->getStyle() == colorStyle)) &&
Shinya Kitaoka 120a6e
            region->contains(*currentStroke, true)) {
Shinya Kitaoka 120a6e
          eraseStrokes.push_back(strokeIndex);
Shinya Kitaoka 120a6e
          m_undo->addOldStroke(strokeIndex, vi->getVIStroke(strokeIndex));
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    for (strokeIndex = 0; strokeIndex < (int)vi->getStrokeCount();
Shinya Kitaoka 120a6e
         strokeIndex++) {
Shinya Kitaoka 120a6e
      TStroke *currentStroke = vi->getStroke(strokeIndex);
Shinya Kitaoka 120a6e
      bool eraseIt           = false;
Shinya Kitaoka 120a6e
      for (regionIndex = 0; regionIndex < (int)eraseImg.getRegionCount();
Shinya Kitaoka 120a6e
           regionIndex++) {
Shinya Kitaoka 120a6e
        TRegion *region = eraseImg.getRegion(regionIndex);
Shinya Kitaoka 120a6e
        if (!m_selective.getValue() ||
Shinya Kitaoka 120a6e
            (m_selective.getValue() && currentStroke->getStyle() == colorStyle))
Shinya Kitaoka 120a6e
          eraseIt = true;
Shinya Kitaoka 120a6e
        if (region->contains(*currentStroke, true)) {
Shinya Kitaoka 120a6e
          eraseIt = false;
Shinya Kitaoka 120a6e
          break;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      if (eraseIt) {
Shinya Kitaoka 120a6e
        m_undo->addOldStroke(strokeIndex, vi->getVIStroke(strokeIndex));
Shinya Kitaoka 120a6e
        eraseStrokes.push_back(strokeIndex);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = (int)eraseStrokes.size() - 1; i >= 0; i--)
Shinya Kitaoka 120a6e
    vi->deleteStroke(eraseStrokes[i]);
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(m_undo);
Shinya Kitaoka 120a6e
  m_undo = 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Viene richiamata la doErase sui frame compresi tra \b firstFrameId e \b
Shinya Kitaoka 120a6e
//! lastFrameId.
Shinya Kitaoka 120a6e
/*!Viene caricato il vettore \b fids con i TFrameId delle immagini sulle quali
Shinya Kitaoka 120a6e
 * si deve effettuare una cancellazione.*/
Toshihiro Shimizu 890ddd
void EraserTool::doMultiErase(TFrameId &firstFrameId, TFrameId &lastFrameId,
Shinya Kitaoka 120a6e
                              const TStroke *firstStroke,
Shinya Kitaoka 120a6e
                              const TStroke *lastStroke) {
Shinya Kitaoka 120a6e
  TXshSimpleLevel *sl =
Shinya Kitaoka 120a6e
      TTool::getApplication()->getCurrentLevel()->getLevel()->getSimpleLevel();
Shinya Kitaoka 120a6e
  TStroke *first           = new TStroke();
Shinya Kitaoka 120a6e
  TStroke *last            = new TStroke();
Shinya Kitaoka 120a6e
  *first                   = *firstStroke;
Shinya Kitaoka 120a6e
  *last                    = *lastStroke;
Shinya Kitaoka 120a6e
  TVectorImageP firstImage = new TVectorImage();
Shinya Kitaoka 120a6e
  TVectorImageP lastImage  = new TVectorImage();
Shinya Kitaoka 120a6e
  firstImage->addStroke(first);
Shinya Kitaoka 120a6e
  lastImage->addStroke(last);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool backward = false;
Shinya Kitaoka 120a6e
  if (firstFrameId > lastFrameId) {
Shinya Kitaoka 120a6e
    tswap(firstFrameId, lastFrameId);
Shinya Kitaoka 120a6e
    backward = true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  assert(firstFrameId <= lastFrameId);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<tframeid> allFids;</tframeid>
Shinya Kitaoka 120a6e
  sl->getFids(allFids);
Shinya Kitaoka 120a6e
  std::vector<tframeid>::iterator i0 = allFids.begin();</tframeid>
Shinya Kitaoka 120a6e
  while (i0 != allFids.end() && *i0 < firstFrameId) i0++;
Shinya Kitaoka 120a6e
  if (i0 == allFids.end()) return;
Shinya Kitaoka 120a6e
  std::vector<tframeid>::iterator i1 = i0;</tframeid>
Shinya Kitaoka 120a6e
  while (i1 != allFids.end() && *i1 <= lastFrameId) i1++;
Shinya Kitaoka 120a6e
  assert(i0 < i1);
Shinya Kitaoka 120a6e
  std::vector<tframeid> fids(i0, i1);</tframeid>
Shinya Kitaoka 120a6e
  int m = fids.size();
Shinya Kitaoka 120a6e
  assert(m > 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TUndoManager::manager()->beginBlock();
Shinya Kitaoka 120a6e
  for (int i = 0; i < m; ++i) {
Shinya Kitaoka 120a6e
    TFrameId fid = fids[i];
Shinya Kitaoka 120a6e
    assert(firstFrameId <= fid && fid <= lastFrameId);
Shinya Kitaoka 120a6e
    double t = m > 1 ? (double)i / (double)(m - 1) : 0.5;
Shinya Kitaoka 120a6e
    // Setto il fid come corrente per notificare il cambiamento dell'immagine
Shinya Kitaoka 120a6e
    TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
    if (app) {
Shinya Kitaoka 120a6e
      if (app->getCurrentFrame()->isEditingScene())
Shinya Kitaoka 120a6e
        app->getCurrentFrame()->setFrame(fid.getNumber() - 1);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        app->getCurrentFrame()->setFid(fid);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    doErase(backward ? 1 - t : t, sl, fid, firstImage, lastImage);
Shinya Kitaoka 120a6e
    notifyImageChanged();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  TUndoManager::manager()->endBlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Viene richiamata la \b eraseRegion per il frame giusto nel caso della
Shinya Kitaoka 120a6e
//! modalita' "Frame Range".
Shinya Kitaoka 120a6e
/*!Nei casi in cui \b t e' diverso da zero e uno, viene generata una nuova \b
Shinya Kitaoka 120a6e
   TVectorImageP richiamando la \b TInbetween.
Shinya Kitaoka 120a6e
        La nuova immagine contiene lo stroke da dare alla eraseRegion. \b fid e'
Shinya Kitaoka 120a6e
   il TFrameId dell'immagine sulla quale
Shinya Kitaoka 120a6e
        bisogna effettuare la cancellazione.*/
Shinya Kitaoka 120a6e
void EraserTool::doErase(double t, const TXshSimpleLevelP &sl,
Shinya Kitaoka 120a6e
                         const TFrameId &fid, const TVectorImageP &firstImage,
Shinya Kitaoka 120a6e
                         const TVectorImageP &lastImage) {
Shinya Kitaoka 120a6e
  //	TImageLocation imageLocation(m_level->getName(),fid);
Shinya Kitaoka 120a6e
  TVectorImageP img = sl->getFrame(fid, true);
Shinya Kitaoka 120a6e
  if (t == 0)
Shinya Kitaoka 120a6e
    eraseRegion(img, firstImage->getStroke(0));  //,imageLocation);
Shinya Kitaoka 120a6e
  else if (t == 1)
Shinya Kitaoka 120a6e
    eraseRegion(img, lastImage->getStroke(0));  //,imageLocation);
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    assert(firstImage->getStrokeCount() == 1);
Shinya Kitaoka 120a6e
    assert(lastImage->getStrokeCount() == 1);
Shinya Kitaoka 120a6e
    TVectorImageP vi = TInbetween(firstImage, lastImage).tween(t);
Shinya Kitaoka 120a6e
    assert(vi->getStrokeCount() == 1);
Shinya Kitaoka 120a6e
    eraseRegion(img, vi->getStroke(0));  //,imageLocation);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Effettua la cancellazione nella modalita' "Frame range".
Shinya Kitaoka 120a6e
/*! Se il primo frame e' gia stato selezionato richiama la \b doMultiErase;
Shinya Kitaoka 120a6e
 altrimenti viene inizializzato
Toshihiro Shimizu 890ddd
 \b m_firstStroke.*/
Shinya Kitaoka 120a6e
void EraserTool::multiEreserRegion(TStroke *stroke, const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  TTool::Application *application = TTool::getApplication();
Shinya Kitaoka 120a6e
  if (!application) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_firstFrameSelected) {
Shinya Kitaoka 120a6e
    if (m_firstStroke && stroke) {
Shinya Kitaoka 120a6e
      TFrameId tmpFrameId = getCurrentFid();
Shinya Kitaoka 120a6e
      doMultiErase(m_firstFrameId, tmpFrameId, m_firstStroke, stroke);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (e.isShiftPressed()) {
Shinya Kitaoka 120a6e
      m_firstStroke  = new TStroke(*stroke);
Shinya Kitaoka 120a6e
      m_firstFrameId = getCurrentFid();
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      if (application->getCurrentFrame()->isEditingScene()) {
Shinya Kitaoka 120a6e
        application->getCurrentColumn()->setColumnIndex(m_currCell.first);
Shinya Kitaoka 120a6e
        application->getCurrentFrame()->setFrame(m_currCell.second);
Shinya Kitaoka 120a6e
      } else
Shinya Kitaoka 120a6e
        application->getCurrentFrame()->setFid(m_veryFirstFrameId);
Shinya Kitaoka 120a6e
      resetMulti();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    m_firstStroke = new TStroke(*stroke);
Shinya Kitaoka 120a6e
    if (application->getCurrentFrame()->isEditingScene())
Shinya Kitaoka 120a6e
      m_currCell =
Shinya Kitaoka 120a6e
          std::pair<int, int="">(application->getCurrentColumn()->getColumnIndex(),</int,>
Shinya Kitaoka 120a6e
                              application->getCurrentFrame()->getFrame());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! ドラッグ中にツールが切り替わった場合、Erase終了処理を行う
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
void EraserTool::onDeactivate() {
Shinya Kitaoka 120a6e
  if (!m_active) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_active = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // TODO : finishing erase procedure is only available for normal type.
Shinya Kitaoka 120a6e
  // Supporting other types is needed. 2016/1/22 shun_iwasawa
Shinya Kitaoka 120a6e
  if (m_eraseType.getValue() != NORMAL_ERASE) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TImageP image(getImage(true));
Shinya Kitaoka 120a6e
  TVectorImageP vi                = image;
Shinya Kitaoka 120a6e
  TTool::Application *application = TTool::getApplication();
Shinya Kitaoka 120a6e
  if (!vi || !application) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  stopErase(vi);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TTool *getEraserTool() {return &eraserTool;}