Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzTools includes
Toshihiro Shimizu 890ddd
#include "tools/toolutils.h"
Toshihiro Shimizu 890ddd
#include "tools/cursors.h"
Toshihiro Shimizu 890ddd
#include "tools/tool.h"
Toshihiro Shimizu 890ddd
#include "tools/toolutils.h"
Toshihiro Shimizu 890ddd
#include "tools/toolhandle.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "bluredbrush.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzQt includes
Toshihiro Shimizu 890ddd
#include "toonzqt/icongenerator.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzLib includes
Toshihiro Shimizu 890ddd
#include "toonz/strokegenerator.h"
Toshihiro Shimizu 890ddd
#include "toonz/ttilesaver.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshsimplelevel.h"
Toshihiro Shimizu 890ddd
#include "toonz/observer.h"
Toshihiro Shimizu 890ddd
#include "toonz/toonzimageutils.h"
Toshihiro Shimizu 890ddd
#include "toonz/levelproperties.h"
Toshihiro Shimizu 890ddd
#include "toonz/stage2.h"
Toshihiro Shimizu 890ddd
#include "toonz/ttileset.h"
Toshihiro Shimizu 890ddd
#include "toonz/rasterstrokegenerator.h"
Toshihiro Shimizu 890ddd
#include "toonz/txsheethandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tframehandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshlevelhandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tpalettehandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tobjecthandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnhandle.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 "tstroke.h"
Toshihiro Shimizu 890ddd
#include "tmathutil.h"
Toshihiro Shimizu 890ddd
#include "drawutil.h"
Toshihiro Shimizu 890ddd
#include "tcolorstyles.h"
Toshihiro Shimizu 890ddd
#include "tundo.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 "trop.h"
Toshihiro Shimizu 890ddd
#include "tinbetween.h"
Toshihiro Shimizu 890ddd
#include "ttile.h"
Toshihiro Shimizu 890ddd
#include "tropcm.h"
Toshihiro Shimizu 890ddd
#include "timage_io.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Qt includes
Shinya Kitaoka 120a6e
#include <qcoreapplication>  // For Qt translation support</qcoreapplication>
Toshihiro Shimizu 890ddd
#include <qpainter></qpainter>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace ToolUtils;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define LINES L"Lines"
Toshihiro Shimizu 890ddd
#define AREAS L"Areas"
Toshihiro Shimizu 890ddd
#define ALL L"Lines & Areas"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define NORMALERASE L"Normal"
Toshihiro Shimizu 890ddd
#define RECTERASE L"Rectangular"
Toshihiro Shimizu 890ddd
#define FREEHANDERASE L"Freehand"
Toshihiro Shimizu 890ddd
#define POLYLINEERASE L"Polyline"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TEnv::DoubleVar EraseSize("InknpaintEraseSize", 10);
Toshihiro Shimizu 890ddd
TEnv::StringVar EraseType("InknpaintEraseType", "Normal");
Toshihiro Shimizu 890ddd
TEnv::IntVar EraseSelective("InknpaintEraseSelective", 0);
Toshihiro Shimizu 890ddd
TEnv::IntVar EraseInvert("InknpaintEraseInvert", 0);
Toshihiro Shimizu 890ddd
TEnv::IntVar EraseRange("InknpaintEraseRange", 0);
Toshihiro Shimizu 890ddd
TEnv::StringVar EraseColorType("InknpaintEraseColorType", "Lines");
Toshihiro Shimizu 890ddd
TEnv::DoubleVar EraseHardness("EraseHardness", 100);
Toshihiro Shimizu 890ddd
TEnv::IntVar ErasePencil("InknpaintErasePencil", 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
//   Undo dei Tools
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Shinya Kitaoka 120a6e
        Viene realizzata la funzione di "UNDO" per il cancellino nell'opzione
Shinya Kitaoka 120a6e
   RECTERASE
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class RectRasterUndo final : public TRasterUndo {
Shinya Kitaoka 120a6e
  TRectD m_modifyArea;
Shinya Kitaoka 120a6e
  TStroke *m_stroke;
Shinya Kitaoka 120a6e
  int m_styleId;
Shinya Kitaoka 120a6e
  std::wstring m_colorType;
Shinya Kitaoka 120a6e
  std::wstring m_eraseType;
Shinya Kitaoka 120a6e
  bool m_selective;
Shinya Kitaoka 120a6e
  bool m_invert;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  RectRasterUndo(TTileSetCM32 *tileSet, const TRectD &modifyArea,
Shinya Kitaoka 120a6e
                 TStroke stroke, int styleId, std::wstring eraseType,
Shinya Kitaoka 120a6e
                 std::wstring colorType, TXshSimpleLevel *level, bool selective,
Shinya Kitaoka 120a6e
                 bool invert, const TFrameId &frameId)
Shinya Kitaoka 120a6e
      : TRasterUndo(tileSet, level, frameId, false, false, 0)
Shinya Kitaoka 120a6e
      , m_modifyArea(modifyArea)
Shinya Kitaoka 120a6e
      , m_styleId(styleId)
Shinya Kitaoka 120a6e
      , m_eraseType(eraseType)
Shinya Kitaoka 120a6e
      , m_colorType(colorType)
Shinya Kitaoka 120a6e
      , m_selective(selective)
Shinya Kitaoka 120a6e
      , m_invert(invert) {
Shinya Kitaoka 120a6e
    m_stroke = new TStroke(stroke);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void redo() const override {
Shinya Kitaoka 120a6e
    TToonzImageP ti = getImage();
Shinya Kitaoka 120a6e
    if (!ti) return;
Shinya Kitaoka 120a6e
    bool eraseInk   = m_colorType == LINES || m_colorType == ALL;
Shinya Kitaoka 120a6e
    bool erasePaint = m_colorType == AREAS || m_colorType == ALL;
Shinya Kitaoka 120a6e
    if (m_eraseType == RECTERASE) {
Shinya Kitaoka 120a6e
      TRect rect = ToonzImageUtils::eraseRect(ti, m_modifyArea, m_styleId,
Shinya Kitaoka 120a6e
                                              eraseInk, erasePaint);
Shinya Kitaoka 120a6e
      if (!rect.isEmpty()) ToolUtils::updateSaveBox(m_level, m_frameId);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    } else if (m_eraseType == FREEHANDERASE || m_eraseType == POLYLINEERASE) {
Shinya Kitaoka 120a6e
      if (m_level) {
Shinya Kitaoka 120a6e
        TPoint pos;
Shinya Kitaoka 120a6e
        TRaster32P ras =
Shinya Kitaoka 120a6e
            convertStrokeToImage(m_stroke, ti->getRaster()->getBounds(), pos);
Shinya Kitaoka 120a6e
        if (!ras) return;
Shinya Kitaoka 120a6e
        ToonzImageUtils::eraseImage(ti, ras, pos, m_invert, eraseInk,
Shinya Kitaoka 120a6e
                                    erasePaint, m_selective, m_styleId);
Shinya Kitaoka 120a6e
        ToolUtils::updateSaveBox(m_level, m_frameId);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
    notifyImageChanged();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  int getSize() const override {
Shinya Kitaoka 120a6e
    return TRasterUndo::getSize() + sizeof(this) +
Shinya Kitaoka 120a6e
           m_stroke->getControlPointCount() * sizeof(TThickPoint) + 100;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~RectRasterUndo() {
Shinya Kitaoka 120a6e
    if (m_stroke) delete m_stroke;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  QString getToolName() override { return QString("Eraser Tool (Rect)"); }
Shinya Kitaoka 473e70
  int getHistoryType() override { return HistoryType::EraserTool; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=====================================================================
Toshihiro Shimizu 890ddd
/*!
Shinya Kitaoka 120a6e
        Viene realizzata la funzione di "UNDO" per il cancellino nell'opzione
Shinya Kitaoka 120a6e
   NORMALERAS
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka d1f6c4
class RasterEraserUndo final : public TRasterUndo {
Shinya Kitaoka 120a6e
  std::vector<tthickpoint> m_points;</tthickpoint>
Shinya Kitaoka 120a6e
  int m_styleId;
Shinya Kitaoka 120a6e
  bool m_selective;
Shinya Kitaoka 120a6e
  bool m_isPencil;
Shinya Kitaoka 120a6e
  ColorType m_colorType;
Shinya Kitaoka 120a6e
  int m_colorSelected;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  RasterEraserUndo(TTileSetCM32 *tileSet,
Shinya Kitaoka 120a6e
                   const std::vector<tthickpoint> &points, ColorType colorType,</tthickpoint>
Shinya Kitaoka 120a6e
                   int styleId, bool selective, int colorSelected,
Shinya Kitaoka 120a6e
                   TXshSimpleLevel *level, const TFrameId &frameId,
Shinya Kitaoka 120a6e
                   bool isPencil)
Shinya Kitaoka 120a6e
      : TRasterUndo(tileSet, level, frameId, false, false, 0)
Shinya Kitaoka 120a6e
      , m_points(points)
Shinya Kitaoka 120a6e
      , m_styleId(styleId)
Shinya Kitaoka 120a6e
      , m_selective(selective)
Shinya Kitaoka 120a6e
      , m_colorType(colorType)
Shinya Kitaoka 120a6e
      , m_colorSelected(colorSelected)
Shinya Kitaoka 120a6e
      , m_isPencil(isPencil) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void redo() const override {
Shinya Kitaoka 120a6e
    TToonzImageP image = m_level->getFrame(m_frameId, true);
Shinya Kitaoka 120a6e
    TRasterCM32P ras   = image->getRaster();
Shinya Kitaoka 120a6e
    RasterStrokeGenerator m_rasterTrack(ras, ERASE, m_colorType, 0, m_points[0],
Shinya Kitaoka 120a6e
                                        m_selective, m_colorSelected,
Shinya Kitaoka 120a6e
                                        !m_isPencil);
Shinya Kitaoka 120a6e
    m_rasterTrack.setPointsSequence(m_points);
Shinya Kitaoka 120a6e
    m_rasterTrack.generateStroke(m_isPencil);
Shinya Kitaoka 120a6e
    image->setSavebox(image->getSavebox() +
Shinya Kitaoka 120a6e
                      m_rasterTrack.getBBox(m_rasterTrack.getPointsSequence()));
Shinya Kitaoka 120a6e
    ToolUtils::updateSaveBox();
Shinya Kitaoka 120a6e
    TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
    notifyImageChanged();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 38fd86
  int getSize() const override {
Shinya Kitaoka 38fd86
    return sizeof(*this) + TRasterUndo::getSize();
Shinya Kitaoka 38fd86
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  QString getToolName() override { return QString("Eraser Tool"); }
Shinya Kitaoka 473e70
  int getHistoryType() override { return HistoryType::EraserTool; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=====================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class RasterBluredEraserUndo final : public TRasterUndo {
Shinya Kitaoka 120a6e
  std::vector<tthickpoint> m_points;</tthickpoint>
Shinya Kitaoka 120a6e
  int m_styleId;
Shinya Kitaoka 120a6e
  bool m_selective;
Shinya Kitaoka 120a6e
  int m_size;
Shinya Kitaoka 120a6e
  double m_hardness;
Shinya Kitaoka 120a6e
  std::wstring m_mode;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  RasterBluredEraserUndo(TTileSetCM32 *tileSet,
Shinya Kitaoka 120a6e
                         const std::vector<tthickpoint> &points, int styleId,</tthickpoint>
Shinya Kitaoka 120a6e
                         bool selective, TXshSimpleLevel *level,
Shinya Kitaoka 120a6e
                         const TFrameId &frameId, int size, double hardness,
Shinya Kitaoka 120a6e
                         const std::wstring &mode)
Shinya Kitaoka 120a6e
      : TRasterUndo(tileSet, level, frameId, false, false, 0)
Shinya Kitaoka 120a6e
      , m_points(points)
Shinya Kitaoka 120a6e
      , m_styleId(styleId)
Shinya Kitaoka 120a6e
      , m_selective(selective)
Shinya Kitaoka 120a6e
      , m_size(size)
Shinya Kitaoka 120a6e
      , m_hardness(hardness)
Shinya Kitaoka 120a6e
      , m_mode(mode) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void redo() const override {
Shinya Kitaoka 120a6e
    if (m_points.size() == 0) return;
Shinya Kitaoka 120a6e
    TToonzImageP image     = getImage();
Shinya Kitaoka 120a6e
    TRasterCM32P ras       = image->getRaster();
Shinya Kitaoka 120a6e
    TRasterCM32P backupRas = ras->clone();
Shinya Kitaoka 120a6e
    TRaster32P workRaster(ras->getSize());
Shinya Kitaoka 120a6e
    QRadialGradient brushPad = ToolUtils::getBrushPad(m_size, m_hardness);
Shinya Kitaoka 120a6e
    workRaster->clear();
Shinya Kitaoka 120a6e
    BluredBrush brush(workRaster, m_size, brushPad, false);
Shinya Kitaoka 120a6e
    std::vector<tthickpoint> points;</tthickpoint>
Shinya Kitaoka 120a6e
    points.push_back(m_points[0]);
Shinya Kitaoka 120a6e
    TRect bbox = brush.getBoundFromPoints(points);
Shinya Kitaoka 120a6e
    brush.addPoint(m_points[0], 1);
Shinya Kitaoka 120a6e
    brush.eraseDrawing(ras, ras, bbox, m_selective, m_styleId, m_mode);
Shinya Kitaoka 120a6e
    if (m_points.size() > 1) {
Shinya Kitaoka 120a6e
      points.clear();
Shinya Kitaoka 120a6e
      points.push_back(m_points[0]);
Shinya Kitaoka 120a6e
      points.push_back(m_points[1]);
Shinya Kitaoka 120a6e
      bbox = brush.getBoundFromPoints(points);
Shinya Kitaoka 120a6e
      brush.addArc(m_points[0], (m_points[0] + m_points[1]) * 0.5, m_points[1],
Shinya Kitaoka 120a6e
                   1, 1);
Shinya Kitaoka 120a6e
      brush.eraseDrawing(ras, backupRas, bbox, m_selective, m_styleId, m_mode);
Shinya Kitaoka 120a6e
      int i;
Shinya Kitaoka 120a6e
      for (i = 1; i + 2 < (int)m_points.size(); i = i + 2) {
Shinya Kitaoka 120a6e
        points.clear();
Shinya Kitaoka 120a6e
        points.push_back(m_points[i]);
Shinya Kitaoka 120a6e
        points.push_back(m_points[i + 1]);
Shinya Kitaoka 120a6e
        points.push_back(m_points[i + 2]);
Shinya Kitaoka 120a6e
        bbox = brush.getBoundFromPoints(points);
Shinya Kitaoka 120a6e
        brush.addArc(m_points[i], m_points[i + 1], m_points[i + 2], 1, 1);
Shinya Kitaoka 120a6e
        brush.eraseDrawing(ras, backupRas, bbox, m_selective, m_styleId,
Shinya Kitaoka 120a6e
                           m_mode);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    ToolUtils::updateSaveBox();
Shinya Kitaoka 120a6e
    TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
    notifyImageChanged();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 38fd86
  int getSize() const override {
Shinya Kitaoka 38fd86
    return sizeof(*this) + TRasterUndo::getSize();
Shinya Kitaoka 38fd86
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  QString getToolName() override { return QString("Eraser Tool"); }
Shinya Kitaoka 473e70
  int getHistoryType() override { return HistoryType::EraserTool; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void eraseStroke(const TToonzImageP &ti, TStroke *stroke,
Shinya Kitaoka 120a6e
                 std::wstring eraseType, std::wstring colorType, bool invert,
Shinya Kitaoka 120a6e
                 bool selective, int styleId, const TXshSimpleLevelP &level,
Shinya Kitaoka 120a6e
                 const TFrameId &frameId) {
Shinya Kitaoka 120a6e
  assert(stroke);
Shinya Kitaoka 120a6e
  TPoint pos;
Shinya Kitaoka 120a6e
  TRasterCM32P ras = ti->getRaster();
Shinya Kitaoka 120a6e
  TRaster32P image = convertStrokeToImage(stroke, ras->getBounds(), pos);
Shinya Kitaoka 120a6e
  if (!image) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRect rasterErasedArea = image->getBounds() + pos;
Shinya Kitaoka 120a6e
  TRect area;
Shinya Kitaoka 120a6e
  if (!invert)
Shinya Kitaoka 120a6e
    area = rasterErasedArea.enlarge(2);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    area                = ras->getBounds();
Shinya Kitaoka 120a6e
  TTileSetCM32 *tileSet = new TTileSetCM32(ras->getSize());
Shinya Kitaoka 120a6e
  tileSet->add(ras, area);
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(new RectRasterUndo(
Shinya Kitaoka 120a6e
      tileSet, convert(area), *stroke, selective ? styleId : -1, eraseType,
Shinya Kitaoka 120a6e
      colorType, level.getPointer(), selective, invert, frameId));
Shinya Kitaoka 120a6e
  bool eraseInk   = colorType == LINES || colorType == ALL;
Shinya Kitaoka 120a6e
  bool erasePaint = colorType == AREAS || colorType == ALL;
Shinya Kitaoka 120a6e
  ToonzImageUtils::eraseImage(ti, image, pos, invert, eraseInk, erasePaint,
Shinya Kitaoka 120a6e
                              selective, styleId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void drawLine(const TPointD &point, const TPointD ¢re, bool horizontal,
Shinya Kitaoka 120a6e
              bool isDecimal) {
Shinya Kitaoka 120a6e
  if (!isDecimal) {
Shinya Kitaoka 120a6e
    if (horizontal) {
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 1.5, point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x - 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y - 0.5, -point.x + 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y - 0.5, -point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x + 0.5, -point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x - 0.5, -point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 0.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y - 0.5, point.x + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y - 0.5, point.x - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 0.5, -point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x - 1.5, -point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 0.5, -point.x + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, -point.x + 1.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x - 0.5, point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x + 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 1.5, point.y + 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x - 1.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 1.5, point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x - 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y + 0.5, -point.x + 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y - 0.5, -point.x + 1.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y - 0.5, -point.x + 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y - 0.5, -point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x + 0.5, -point.y - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x + 0.5, -point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x + 0.5, -point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x - 0.5, -point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 1.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, point.x - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 0.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y + 0.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y - 0.5, point.x - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y - 0.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y - 0.5, point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 1.5, -point.y - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x - 1.5, -point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 1.5, -point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x - 0.5, -point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 1.5, -point.x + 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, -point.x + 1.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 0.5, -point.x + 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, -point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x + 0.5, point.y + 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x + 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x + 0.5, point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x - 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    if (horizontal) {
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 0.5, point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x + 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y + 0.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y + 0.5, point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y + 0.5, -point.x + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y + 0.5, -point.x - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x + 0.5, -point.y - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x - 0.5, -point.y - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x - 0.5, -point.y - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x + 0.5, -point.y - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 0.5, -point.x + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, -point.x - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 0.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x + 0.5, point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x - 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 0.5, point.y + 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x - 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 0.5, point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x + 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y + 1.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y + 0.5, point.x - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y + 0.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y + 0.5, point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y + 1.5, -point.x + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y + 0.5, -point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.y + 0.5, -point.x + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.y + 0.5, -point.x - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 0.5, -point.y - 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x - 0.5, -point.y - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(point.x - 0.5, -point.y - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(point.x + 0.5, -point.y - 0.5) + centre);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x + 0.5, -point.y - 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x + 0.5, -point.y - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x + 0.5, -point.y - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x - 0.5, -point.y - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 1.5, -point.x + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, -point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 0.5, -point.x + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, -point.x - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 1.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, point.x - 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.y - 0.5, point.x - 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.y - 0.5, point.x + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x + 0.5, point.y + 1.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x + 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
      tglDrawSegment(TPointD(-point.x + 0.5, point.y + 0.5) + centre,
Shinya Kitaoka 120a6e
                     TPointD(-point.x - 0.5, point.y + 0.5) + centre);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void drawEmptyCircle(int thick, const TPointD &mousePos, bool isPencil,
Shinya Kitaoka 120a6e
                     bool isLxEven, bool isLyEven) {
Shinya Kitaoka 120a6e
  TPointD pos = mousePos;
Shinya Kitaoka 120a6e
  if (isLxEven) pos.x += 0.5;
Shinya Kitaoka 120a6e
  if (isLyEven) pos.y += 0.5;
Shinya Kitaoka 120a6e
  if (!isPencil)
Shinya Kitaoka 120a6e
    tglDrawCircle(pos, (thick)*0.5);
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    int x = 0, y = tround((thick * 0.5) - 0.5);
Shinya Kitaoka 120a6e
    int d           = 3 - 2 * (int)(thick * 0.5);
Shinya Kitaoka 120a6e
    bool horizontal = true, isDecimal = thick % 2 != 0;
Shinya Kitaoka 120a6e
    drawLine(TPointD(x, y), pos, horizontal, isDecimal);
Shinya Kitaoka 120a6e
    while (y > x) {
Shinya Kitaoka 120a6e
      if (d < 0) {
Shinya Kitaoka 120a6e
        d          = d + 4 * x + 6;
Shinya Kitaoka 120a6e
        horizontal = true;
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        d          = d + 4 * (x - y) + 10;
Shinya Kitaoka 120a6e
        horizontal = false;
Shinya Kitaoka 120a6e
        y--;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      x++;
Shinya Kitaoka 120a6e
      drawLine(TPointD(x, y), pos, horizontal, isDecimal);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==================================================================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//  InkPaintTool class declaration
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class EraserTool final : public TTool {
Shinya Kitaoka 120a6e
  Q_DECLARE_TR_FUNCTIONS(EraserTool)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  EraserTool(std::string name);
Shinya Kitaoka 120a6e
  ~EraserTool() {
Shinya Kitaoka 120a6e
    if (m_firstStroke) delete m_firstStroke;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  ToolType getToolType() const override { return TTool::LevelWriteTool; }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void updateTranslation() override;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void draw() override;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void update(const TToonzImageP &ti, const TPointD &pos);
Shinya Kitaoka 120a6e
  void saveUndo();
Shinya Kitaoka 120a6e
  void update(const TToonzImageP &ti, TRectD selArea,
Shinya Kitaoka 120a6e
              const TXshSimpleLevelP &level, bool multi = false,
Shinya Kitaoka 120a6e
              const TFrameId &frameId = -1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void leftButtonDown(const TPointD &pos, const TMouseEvent &e) override;
Shinya Kitaoka 473e70
  void leftButtonDrag(const TPointD &pos, const TMouseEvent &e) override;
Shinya Kitaoka 473e70
  void leftButtonUp(const TPointD &pos, const TMouseEvent &) override;
Shinya Kitaoka 473e70
  void leftButtonDoubleClick(const TPointD &pos, const TMouseEvent &e) override;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void multiAreaEraser(const TXshSimpleLevelP &sl, TFrameId &firstFid,
Shinya Kitaoka 120a6e
                       TFrameId &lastFid, TStroke *firstStroke,
Shinya Kitaoka 120a6e
                       TStroke *lastStroke);
Shinya Kitaoka 120a6e
  void doMultiEraser(const TImageP &img, double t, const TXshSimpleLevelP &sl,
Shinya Kitaoka 120a6e
                     const TFrameId &fid, const TVectorImageP &firstImage,
Shinya Kitaoka 120a6e
                     const TVectorImageP &lastImage);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void mouseMove(const TPointD &pos, const TMouseEvent &e) override;
Shinya Kitaoka 473e70
  void onEnter() override;
Shinya Kitaoka 473e70
  void onLeave() override;
Shinya Kitaoka 473e70
  void onActivate() override;
Shinya Kitaoka 473e70
  bool onPropertyChanged(std::string propertyName) override;
Shinya Kitaoka 473e70
  void onImageChanged() override;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void multiUpdate(const TXshSimpleLevelP &level, TFrameId firstFrameId,
Shinya Kitaoka 120a6e
                   TFrameId lastFrameId, TRectD firstRect, TRectD lastRect);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  TPropertyGroup *getProperties(int targetType) override { return &m_prop; }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  int getCursorId() const override;
Shinya Kitaoka 120a6e
  void resetMulti();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /*-- ドラッグ中にツールが切り替わった場合、処理を終了させる--*/
Shinya Kitaoka 473e70
  void onDeactivate() override;
Shinya Kitaoka 120a6e
  /*-- Brush、PaintBrush、EraserToolがPencilModeのときにTrueを返す --*/
Shinya Kitaoka 473e70
  bool isPencilModeActive() override;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  /*-- 終了処理 --*/
Shinya Kitaoka 120a6e
  void storeUndoAndRefresh();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  enum Type { NONE = 0, BRUSH, INKCHANGE, ERASER };
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
  TIntProperty m_toolSize;
Shinya Kitaoka 120a6e
  TDoubleProperty m_hardness;
Shinya Kitaoka 120a6e
  TBoolProperty m_invertOption;
Shinya Kitaoka 120a6e
  TBoolProperty m_currentStyle;
Shinya Kitaoka 120a6e
  TBoolProperty m_multi;
Shinya Kitaoka 120a6e
  TBoolProperty m_pencil;
Shinya Kitaoka 120a6e
  TEnumProperty m_colorType;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  Type m_type;
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
  TFrameId m_firstFrameId, m_veryFirstFrameId;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  StrokeGenerator m_track;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TStroke *m_firstStroke;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TTileSaverCM32 *m_tileSaver;
Shinya Kitaoka 120a6e
  TTileSetCM32 *m_tileSet;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  RasterStrokeGenerator *m_normalEraser;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRectD m_selectingRect, m_firstRect;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ColorType m_colorTypeEraser;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TPointD m_mousePos, m_brushPos, m_firstPos;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::vector<tpointd> m_polyline;</tpointd>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // gestione cancellino blurato
Shinya Kitaoka 120a6e
  TRasterCM32P m_backupRas;
Shinya Kitaoka 120a6e
  TRaster32P m_workRas;
Shinya Kitaoka 120a6e
  QRadialGradient m_brushPad;
Shinya Kitaoka 120a6e
  std::vector<tthickpoint> m_points;</tthickpoint>
Shinya Kitaoka 120a6e
  BluredBrush *m_bluredBrush;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double m_pointSize, m_distance2, m_cleanerSize, m_thick;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool m_isXsheetCell, m_active, m_enabled, m_selecting, m_firstFrameSelected,
Shinya Kitaoka 120a6e
      m_firstTime;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /*---  消しゴム開始時のFrameIdを保存し、マウスリリース時(Undoの登録時)に
Shinya Kitaoka 120a6e
          別のフレームに移動していた場合に備える
Shinya Kitaoka 120a6e
  ---*/
Shinya Kitaoka 120a6e
  TFrameId m_workingFrameId;
Shinya Kitaoka 120a6e
  /*--- マウスボタンDown→プロパティ変更→マウスボタンUpのように、
Shinya Kitaoka 120a6e
          ボタンDownからUpまでストレートに来なかった場合は処理を行わないようにする。
Shinya Kitaoka 120a6e
  ---*/
Shinya Kitaoka 120a6e
  bool m_isLeftButtonPressed;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
EraserTool inkPaintEraserTool("T_Eraser");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==================================================================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//  InkPaintTool implemention
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
EraserTool::EraserTool(std::string name)
Shinya Kitaoka 120a6e
    : TTool(name)
Shinya Kitaoka 120a6e
    , m_toolSize("Size:", 1, 100, 10, false)  // W_ToolOptions_EraserToolSize
Shinya Kitaoka 120a6e
    , m_hardness("Hardness:", 0, 100, 100)
Shinya Kitaoka 120a6e
    , m_eraseType("Type:")                // W_ToolOptions_Erasetype
Shinya Kitaoka 120a6e
    , m_colorType("Mode:")                // W_ToolOptions_InkOrPaint
Shinya Kitaoka 120a6e
    , m_currentStyle("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_pencil("Pencil Mode", false)
Shinya Kitaoka 120a6e
    , m_currCell(-1, -1)
Shinya Kitaoka 120a6e
    , m_tileSaver(0)
Shinya Kitaoka 120a6e
    , m_bluredBrush(0)
Shinya Kitaoka 120a6e
    , m_pointSize(-1)
Shinya Kitaoka 120a6e
    , m_thick(0.5)
Shinya Kitaoka 120a6e
    , m_firstFrameSelected(false)
Shinya Kitaoka 120a6e
    , m_selecting(false)
Shinya Kitaoka 120a6e
    , m_active(false)
Shinya Kitaoka 120a6e
    , m_enabled(false)
Shinya Kitaoka 120a6e
    , m_isXsheetCell(false)
Shinya Kitaoka 120a6e
    , m_firstTime(true)
Shinya Kitaoka 120a6e
    , m_workingFrameId(TFrameId())
Shinya Kitaoka 120a6e
    , m_isLeftButtonPressed(false) {
Shinya Kitaoka 120a6e
  bind(TTool::ToonzImage);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_prop.bind(m_toolSize);
Shinya Kitaoka 120a6e
  m_prop.bind(m_hardness);
Shinya Kitaoka 120a6e
  m_prop.bind(m_eraseType);
Shinya Kitaoka 120a6e
  m_eraseType.addValue(NORMALERASE);
Shinya Kitaoka 120a6e
  m_eraseType.addValue(RECTERASE);
Shinya Kitaoka 120a6e
  m_eraseType.addValue(FREEHANDERASE);
Shinya Kitaoka 120a6e
  m_eraseType.addValue(POLYLINEERASE);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_colorType.addValue(LINES);
Shinya Kitaoka 120a6e
  m_colorType.addValue(AREAS);
Shinya Kitaoka 120a6e
  m_colorType.addValue(ALL);
Shinya Kitaoka 120a6e
  m_prop.bind(m_colorType);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_prop.bind(m_currentStyle);
Shinya Kitaoka 120a6e
  m_prop.bind(m_invertOption);
Shinya Kitaoka 120a6e
  m_prop.bind(m_multi);
Shinya Kitaoka 120a6e
  m_prop.bind(m_pencil);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_currentStyle.setId("Selective");
Shinya Kitaoka 120a6e
  m_invertOption.setId("Invert");
Shinya Kitaoka 120a6e
  m_multi.setId("FrameRange");
Shinya Kitaoka 120a6e
  m_pencil.setId("PencilMode");
Shinya Kitaoka 120a6e
  m_colorType.setId("Mode");
Shinya Kitaoka 120a6e
  m_eraseType.setId("Type");
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_hardness.setQStringName(tr("Hardness:"));
Shinya Kitaoka 120a6e
  m_eraseType.setQStringName(tr("Type:"));
Shinya Kitaoka 120a6e
  m_colorType.setQStringName(tr("Mode:"));
Shinya Kitaoka 120a6e
  m_currentStyle.setQStringName(tr("Selective"));
Shinya Kitaoka 120a6e
  m_invertOption.setQStringName(tr("Invert"));
Shinya Kitaoka 120a6e
  m_multi.setQStringName(tr("Frame Range"));
Shinya Kitaoka 120a6e
  m_pencil.setQStringName(tr("Pencil Mode"));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::draw() {
Shinya Kitaoka 120a6e
  /*-- MouseLeave時に赤点が描かれるのを防ぐ --*/
Shinya Kitaoka 120a6e
  if (m_pointSize == -1 && m_cleanerSize == 0) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double pixelSize2 = getPixelSize() * getPixelSize();
Shinya Kitaoka 120a6e
  m_thick           = sqrt(pixelSize2) / 2.0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TImageP img = getImage(false);
Shinya Kitaoka 120a6e
  if (!img) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_eraseType.getValue() == RECTERASE) {
Shinya Kitaoka 120a6e
    TPixel color = TPixel32::Red;
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_selecting || (m_multi.getValue() && !m_firstFrameSelected))
Shinya Kitaoka 120a6e
      drawRect(m_selectingRect, color, 0xFFFF, true);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (m_eraseType.getValue() == NORMALERASE) {
Shinya Kitaoka 120a6e
    TToonzImageP image(img);
Shinya Kitaoka 120a6e
    TRasterP ras = image->getRaster();
Shinya Kitaoka 120a6e
    int lx       = ras->getLx();
Shinya Kitaoka 120a6e
    int ly       = ras->getLy();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /*-- InkCheck, PaintCheck, Ink#1CheckがONのときは、BrushTipの描画色を変える
Shinya Kitaoka 120a6e
     * --*/
Shinya Kitaoka 120a6e
    if ((ToonzCheck::instance()->getChecks() & ToonzCheck::eInk) ||
Shinya Kitaoka 120a6e
        (ToonzCheck::instance()->getChecks() & ToonzCheck::ePaint) ||
Shinya Kitaoka 120a6e
        (ToonzCheck::instance()->getChecks() & ToonzCheck::eInk1))
Shinya Kitaoka 120a6e
      glColor3d(0.5, 0.8, 0.8);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      glColor3d(1.0, 0.0, 0.0);
Shinya Kitaoka 120a6e
    drawEmptyCircle(tround(m_cleanerSize), m_brushPos,
Shinya Kitaoka 120a6e
                    (m_pencil.getValue() || m_colorType.getValue() == AREAS),
Shinya Kitaoka 120a6e
                    lx % 2 == 0, ly % 2 == 0);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if ((m_eraseType.getValue() == FREEHANDERASE ||
Shinya Kitaoka 120a6e
       m_eraseType.getValue() == POLYLINEERASE) &&
Shinya Kitaoka 120a6e
      m_multi.getValue()) {
Shinya Kitaoka 120a6e
    TPixel color = TPixel32::Red;
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() == POLYLINEERASE && !m_polyline.empty()) {
Shinya Kitaoka 120a6e
    TPixel color = TPixel32::Red;
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();
shun-iwasawa c189d1
  } else if (m_eraseType.getValue() == FREEHANDERASE && !m_track.isEmpty()) {
shun-iwasawa c189d1
    TPixel color = ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg
shun-iwasawa c189d1
                       ? TPixel32::White
shun-iwasawa c189d1
                       : TPixel32::Black;
shun-iwasawa c189d1
    tglColor(color);
shun-iwasawa c189d1
    glPushMatrix();
shun-iwasawa c189d1
    m_track.drawAllFragments();
shun-iwasawa c189d1
    glPopMatrix();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int EraserTool::getCursorId() const {
shun_iwasawa 009457
  int ret;
Shinya Kitaoka 120a6e
  if (m_eraseType.getValue() == NORMALERASE)
shun_iwasawa 009457
    ret = ToolCursor::NormalEraserCursor;
shun_iwasawa 009457
  else {
shun_iwasawa 009457
    ret = ToolCursor::RectEraserCursor;
shun_iwasawa 009457
shun_iwasawa 009457
    if (m_eraseType.getValue() == FREEHANDERASE)
shun_iwasawa 009457
      ret = ret | ToolCursor::Ex_FreeHand;
shun_iwasawa 009457
    else if (m_eraseType.getValue() == POLYLINEERASE)
shun_iwasawa 009457
      ret = ret | ToolCursor::Ex_PolyLine;
shun_iwasawa 009457
    else if (m_eraseType.getValue() == RECTERASE)
shun_iwasawa 009457
      ret = ret | ToolCursor::Ex_Rectangle;
shun_iwasawa 009457
  }
shun_iwasawa 009457
shun_iwasawa 009457
  if (m_colorType.getValue() == LINES)
shun_iwasawa 009457
    ret = ret | ToolCursor::Ex_Line;
shun_iwasawa 009457
  else if (m_colorType.getValue() == AREAS)
shun_iwasawa 009457
    ret = ret | ToolCursor::Ex_Area;
shun_iwasawa 009457
shun_iwasawa 009457
  if (ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg)
shun_iwasawa 009457
    ret = ret | ToolCursor::Ex_Negate;
shun_iwasawa 009457
  return ret;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::resetMulti() {
Shinya Kitaoka 120a6e
  m_isXsheetCell       = false;
Shinya Kitaoka 120a6e
  m_firstFrameSelected = false;
Shinya Kitaoka 120a6e
  m_firstRect.empty();
Shinya Kitaoka 120a6e
  m_selectingRect.empty();
Shinya Kitaoka 120a6e
  TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
  m_level                 = app->getCurrentLevel()->getLevel()
Shinya Kitaoka 120a6e
                ? app->getCurrentLevel()->getSimpleLevel()
Shinya Kitaoka 120a6e
                : 0;
Shinya Kitaoka 120a6e
  m_firstFrameId = m_veryFirstFrameId = getFrameId();
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::multiUpdate(const TXshSimpleLevelP &level, TFrameId firstFid,
Shinya Kitaoka 120a6e
                             TFrameId lastFid, TRectD firstRect,
Shinya Kitaoka 120a6e
                             TRectD lastRect) {
Shinya Kitaoka 120a6e
  bool backward = false;
Shinya Kitaoka 120a6e
  if (firstFid > lastFid) {
Shinya Kitaoka 120a6e
    tswap(firstFid, lastFid);
Shinya Kitaoka 120a6e
    backward = true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  assert(firstFid <= lastFid);
Shinya Kitaoka 120a6e
  std::vector<tframeid> allFids;</tframeid>
Shinya Kitaoka 120a6e
  level->getFids(allFids);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*-- フレーム範囲に対応するFIdを取得 --*/
Shinya Kitaoka 120a6e
  std::vector<tframeid>::iterator i0 = allFids.begin();</tframeid>
Shinya Kitaoka 120a6e
  while (i0 != allFids.end() && *i0 < firstFid) 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 <= lastFid) 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
  std::wstring levelName = level->getName();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*-- FrameRangeの各フレームについて --*/
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(firstFid <= fid && fid <= lastFid);
Shinya Kitaoka 120a6e
    TToonzImageP ti = level->getFrame(fid, true);
Shinya Kitaoka 120a6e
    if (!ti) continue;
Shinya Kitaoka 120a6e
    /*--補間の係数を取得 --*/
Shinya Kitaoka 120a6e
    double t = m > 1 ? (double)i / (double)(m - 1) : 0.5;
Shinya Kitaoka 120a6e
    /*--invertがONのとき、外側領域を4つのRectに分けてupdate--*/
Shinya Kitaoka 120a6e
    if (m_invertOption.getValue()) {
Shinya Kitaoka 120a6e
      TRect rect =
Shinya Kitaoka 120a6e
          convert(interpolateRect(firstRect, lastRect, backward ? 1 - t : t));
Shinya Kitaoka 120a6e
      TRectD rect01 = TRectD(TPointD(-100000., -100000.),
Shinya Kitaoka 120a6e
                             TPointD((double)rect.x0, 100000.));
Shinya Kitaoka 120a6e
      update(ti, rect01, level, true, fid);
Shinya Kitaoka 120a6e
      TRectD rect02 =
Shinya Kitaoka 120a6e
          TRectD(convert(rect.getP01()), TPointD((double)rect.x1, 100000.));
Shinya Kitaoka 120a6e
      update(ti, rect02, level, true, fid);
Shinya Kitaoka 120a6e
      TRectD rect03 =
Shinya Kitaoka 120a6e
          TRectD(TPointD((double)rect.x0, -100000.), convert(rect.getP10()));
Shinya Kitaoka 120a6e
      update(ti, rect03, level, true, fid);
Shinya Kitaoka 120a6e
      TRectD rect04 =
Shinya Kitaoka 120a6e
          TRectD(TPointD((double)rect.x1, -100000.), TPointD(100000., 100000.));
Shinya Kitaoka 120a6e
      update(ti, rect04, level, true, fid);
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      update(ti, interpolateRect(firstRect, lastRect, backward ? 1 - t : t),
Shinya Kitaoka 120a6e
             level, true, fid);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRect savebox;
Shinya Kitaoka 120a6e
    TRop::computeBBox(ti->getRaster(), savebox);
Shinya Kitaoka 120a6e
    ti->setSavebox(savebox);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    level->getProperties()->setDirtyFlag(true);
Shinya Kitaoka 120a6e
    notifyImageChanged(fid);
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::update(const TToonzImageP &ti, TRectD selArea,
Shinya Kitaoka 120a6e
                        const TXshSimpleLevelP &level, bool multi,
Shinya Kitaoka 120a6e
                        const TFrameId &frameId) {
Shinya Kitaoka 120a6e
  if (m_selectingRect.x0 > m_selectingRect.x1) {
Shinya Kitaoka 120a6e
    selArea.x1 = m_selectingRect.x0;
Shinya Kitaoka 120a6e
    selArea.x0 = m_selectingRect.x1;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (m_selectingRect.y0 > m_selectingRect.y1) {
Shinya Kitaoka 120a6e
    selArea.y1 = m_selectingRect.y0;
Shinya Kitaoka 120a6e
    selArea.y0 = m_selectingRect.y1;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (selArea.getLx() < 1 || selArea.getLy() < 1) return;
Shinya Kitaoka 120a6e
  bool selective = m_currentStyle.getValue();
Shinya Kitaoka 120a6e
  int styleId    = TTool::getApplication()->getCurrentLevelStyleIndex();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRasterCM32P raster   = ti->getRaster();
Shinya Kitaoka 120a6e
  TTileSetCM32 *tileSet = new TTileSetCM32(raster->getSize());
Shinya Kitaoka 120a6e
  tileSet->add(raster, ToonzImageUtils::convertWorldToRaster(selArea, ti));
Shinya Kitaoka 120a6e
  TUndo *undo;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::wstring inkPaint = m_colorType.getValue();
Shinya Kitaoka 120a6e
  undo =
Shinya Kitaoka 120a6e
      new RectRasterUndo(tileSet, selArea, TStroke(), selective ? styleId : -1,
Shinya Kitaoka 120a6e
                         m_eraseType.getValue(), inkPaint, level.getPointer(),
Shinya Kitaoka 120a6e
                         selective, m_invertOption.getValue(), frameId);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ToonzImageUtils::eraseRect(ti, selArea, selective ? styleId : -1,
Shinya Kitaoka 120a6e
                             inkPaint == LINES || inkPaint == ALL,
Shinya Kitaoka 120a6e
                             inkPaint == AREAS || inkPaint == ALL);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(undo);
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_selecting = true;
Shinya Kitaoka 120a6e
  TImageP image(getImage(true));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRectD invalidateRect;
Shinya Kitaoka 120a6e
  if (TToonzImageP ti = image) {
Shinya Kitaoka 120a6e
    if (m_eraseType.getValue() == RECTERASE) {
Shinya Kitaoka 120a6e
      if (m_multi.getValue() && m_firstRect.isEmpty()) {
Shinya Kitaoka 120a6e
        invalidateRect = m_selectingRect;
Shinya Kitaoka 120a6e
        m_selectingRect.empty();
Shinya Kitaoka 120a6e
        invalidate(invalidateRect.enlarge(2));
Shinya Kitaoka 120a6e
      }
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
      invalidateRect     = m_selectingRect.enlarge(2);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (m_eraseType.getValue() == NORMALERASE) {
Shinya Kitaoka 120a6e
      TRasterCM32P raster = ti->getRaster();
Shinya Kitaoka 120a6e
      TThickPoint intPos;
Shinya Kitaoka 120a6e
      /*--Areasタイプの時は常にPencilと同じ消し方にする--*/
Shinya Kitaoka 120a6e
      if (m_pencil.getValue() || m_colorType.getValue() == AREAS)
Shinya Kitaoka 120a6e
        intPos = TThickPoint(pos + convert(raster->getCenter()),
Shinya Kitaoka 120a6e
                             m_toolSize.getValue());
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        intPos = TThickPoint(pos + convert(raster->getCenter()),
Shinya Kitaoka 120a6e
                             m_toolSize.getValue() - 1);
Shinya Kitaoka 120a6e
      int currentStyle = 0;
Shinya Kitaoka 120a6e
      if (m_currentStyle.getValue())
Shinya Kitaoka 120a6e
        currentStyle = TTool::getApplication()->getCurrentLevelStyleIndex();
Shinya Kitaoka 120a6e
      m_tileSet      = new TTileSetCM32(raster->getSize());
Shinya Kitaoka 120a6e
      m_tileSaver    = new TTileSaverCM32(raster, m_tileSet);
Shinya Kitaoka 120a6e
      TPointD halfThick(m_toolSize.getValue() * 0.5,
Shinya Kitaoka 120a6e
                        m_toolSize.getValue() * 0.5);
Shinya Kitaoka 120a6e
      invalidateRect = TRectD(pos - halfThick, pos + halfThick);
Shinya Kitaoka 120a6e
      if (m_hardness.getValue() == 100 || m_pencil.getValue() ||
Shinya Kitaoka 120a6e
          m_colorType.getValue() == AREAS) {
Shinya Kitaoka 120a6e
        if (m_colorType.getValue() == LINES) {
Shinya Kitaoka 120a6e
          m_colorTypeEraser = INK;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        if (m_colorType.getValue() == AREAS) m_colorTypeEraser = PAINT;
Shinya Kitaoka 120a6e
        if (m_colorType.getValue() == ALL) m_colorTypeEraser   = INKNPAINT;
Shinya Kitaoka 120a6e
        m_normalEraser = new RasterStrokeGenerator(
Shinya Kitaoka 120a6e
            raster, ERASE, m_colorTypeEraser, 0, intPos,
Shinya Kitaoka 120a6e
            m_currentStyle.getValue(), currentStyle,
Shinya Kitaoka 120a6e
            !(m_pencil.getValue() || m_colorType.getValue() == AREAS));
Shinya Kitaoka 120a6e
        m_tileSaver->save(m_normalEraser->getLastRect());
Shinya Kitaoka 120a6e
        m_normalEraser->generateLastPieceOfStroke(
Shinya Kitaoka 120a6e
            m_pencil.getValue() || m_colorType.getValue() == AREAS);
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        m_points.clear();
Shinya Kitaoka 120a6e
        m_backupRas = raster->clone();
Shinya Kitaoka 120a6e
        m_workRas   = TRaster32P(raster->getSize());
Shinya Kitaoka 120a6e
        m_workRas->clear();
Shinya Kitaoka 120a6e
        TPointD center = raster->getCenterD();
Shinya Kitaoka 120a6e
        TThickPoint point(pos + center, m_toolSize.getValue());
Shinya Kitaoka 120a6e
        m_points.push_back(point);
Shinya Kitaoka 120a6e
        m_bluredBrush = new BluredBrush(m_workRas, m_toolSize.getValue(),
Shinya Kitaoka 120a6e
                                        m_brushPad, false);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        TRect bbox = m_bluredBrush->getBoundFromPoints(m_points);
Shinya Kitaoka 120a6e
        m_tileSaver->save(bbox);
Shinya Kitaoka 120a6e
        m_bluredBrush->addPoint(point, 1);
Shinya Kitaoka 120a6e
        m_bluredBrush->eraseDrawing(raster, m_backupRas, bbox,
Shinya Kitaoka 120a6e
                                    m_currentStyle.getValue(), currentStyle,
Shinya Kitaoka 120a6e
                                    m_colorType.getValue());
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      /*--- 現在のFidを記憶する ---*/
Shinya Kitaoka 120a6e
      m_workingFrameId = getFrameId();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (m_eraseType.getValue() == FREEHANDERASE ||
Shinya Kitaoka 120a6e
        m_eraseType.getValue() == POLYLINEERASE) {
Shinya Kitaoka 120a6e
      int col   = getColumnIndex();
Shinya Kitaoka 120a6e
      m_enabled = col >= 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (!m_enabled) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (m_multi.getValue() && m_firstStroke && !m_firstFrameSelected) {
Shinya Kitaoka 120a6e
        invalidateRect = m_firstStroke->getBBox();
Shinya Kitaoka 120a6e
        delete m_firstStroke;
Shinya Kitaoka 120a6e
        m_firstStroke = 0;
Shinya Kitaoka 120a6e
        invalidate(invalidateRect.enlarge(2));
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      m_active = true;
Shinya Kitaoka 120a6e
      m_track.clear();
Shinya Kitaoka 120a6e
      m_firstPos        = pos;
Shinya Kitaoka 120a6e
      double pixelSize2 = getPixelSize() * getPixelSize();
Shinya Kitaoka 120a6e
      m_track.add(TThickPoint(pos, m_thick), pixelSize2);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (m_eraseType.getValue() == POLYLINEERASE) {
Shinya Kitaoka 120a6e
        if (m_polyline.empty() || m_polyline.back() != pos)
Shinya Kitaoka 120a6e
          m_polyline.push_back(pos);
shun-iwasawa c189d1
      }
shun-iwasawa c189d1
Shinya Kitaoka 120a6e
      int maxThick = 2 * m_thick;
Shinya Kitaoka 120a6e
      TPointD halfThick(maxThick * 0.5, maxThick * 0.5);
Shinya Kitaoka 120a6e
      invalidateRect = TRectD(pos - halfThick, pos + halfThick);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  invalidate(invalidateRect.enlarge(2));
Shinya Kitaoka 120a6e
  m_isLeftButtonPressed = true;
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
  /*-- 先にLeftButtonDownに入っていなければreturn --*/
Shinya Kitaoka 120a6e
  if (!m_isLeftButtonPressed) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double pixelSize2 = getPixelSize() * getPixelSize();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_brushPos = m_mousePos = pos;
Shinya Kitaoka 120a6e
  if (!m_selecting) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TImageP image(getImage(true));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (TToonzImageP ti = image) {
Shinya Kitaoka 120a6e
    TRectD invalidateRect;
Shinya Kitaoka 120a6e
    TPointD rasCenter = ti->getRaster()->getCenterD();
Shinya Kitaoka 120a6e
    if (m_eraseType.getValue() == RECTERASE) {
Shinya Kitaoka 120a6e
      TRectD oldRect = m_selectingRect;
Shinya Kitaoka 120a6e
      if (oldRect.x0 > oldRect.x1) tswap(oldRect.x1, oldRect.x0);
Shinya Kitaoka 120a6e
      if (oldRect.y0 > oldRect.y1) tswap(oldRect.y1, oldRect.y0);
Shinya Kitaoka 120a6e
      m_selectingRect.x1 = pos.x;
Shinya Kitaoka 120a6e
      m_selectingRect.y1 = pos.y;
Shinya Kitaoka 120a6e
      invalidateRect     = m_selectingRect;
Shinya Kitaoka 120a6e
      if (invalidateRect.x0 > invalidateRect.x1)
Shinya Kitaoka 120a6e
        tswap(invalidateRect.x1, invalidateRect.x0);
Shinya Kitaoka 120a6e
      if (invalidateRect.y0 > invalidateRect.y1)
Shinya Kitaoka 120a6e
        tswap(invalidateRect.y1, invalidateRect.y0);
Shinya Kitaoka 120a6e
      invalidateRect += oldRect;
Shinya Kitaoka 120a6e
      invalidate(invalidateRect.enlarge(2));
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (m_eraseType.getValue() == NORMALERASE) {
Shinya Kitaoka 120a6e
      if (m_normalEraser &&
Shinya Kitaoka 120a6e
          (m_hardness.getValue() == 100 || m_pencil.getValue() ||
Shinya Kitaoka 120a6e
           m_colorType.getValue() == AREAS)) {
Shinya Kitaoka 120a6e
        TPointD pp(pos.x, pos.y);
Shinya Kitaoka 120a6e
        TThickPoint intPos;
Shinya Kitaoka 120a6e
        if (m_pencil.getValue() || m_colorType.getValue() == AREAS)
Shinya Kitaoka 120a6e
          intPos = TThickPoint(pp + convert(ti->getRaster()->getCenter()),
Shinya Kitaoka 120a6e
                               m_toolSize.getValue());
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          intPos = TThickPoint(pp + convert(ti->getRaster()->getCenter()),
Shinya Kitaoka 120a6e
                               m_toolSize.getValue() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        bool isAdded = m_normalEraser->add(intPos);
Shinya Kitaoka 120a6e
        if (ti && isAdded) {
Shinya Kitaoka 120a6e
          m_tileSaver->save(m_normalEraser->getLastRect());
Shinya Kitaoka 120a6e
          m_normalEraser->generateLastPieceOfStroke(
Shinya Kitaoka 120a6e
              m_pencil.getValue() || m_colorType.getValue() == AREAS);
Shinya Kitaoka 120a6e
          std::vector<tthickpoint> brushPoints =</tthickpoint>
Shinya Kitaoka 120a6e
              m_normalEraser->getPointsSequence();
Shinya Kitaoka 120a6e
          int m = (int)brushPoints.size();
Shinya Kitaoka 120a6e
          std::vector<tthickpoint> points;</tthickpoint>
Shinya Kitaoka 120a6e
          if (m == 3) {
Shinya Kitaoka 120a6e
            points.push_back(brushPoints[0]);
Shinya Kitaoka 120a6e
            points.push_back(brushPoints[1]);
Shinya Kitaoka 120a6e
          } else {
Shinya Kitaoka 120a6e
            points.push_back(brushPoints[m - 4]);
Shinya Kitaoka 120a6e
            points.push_back(brushPoints[m - 3]);
Shinya Kitaoka 120a6e
            points.push_back(brushPoints[m - 2]);
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
          invalidateRect = ToolUtils::getBounds(points, m_toolSize.getValue());
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        assert(m_workRas.getPointer() && m_backupRas.getPointer());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        TThickPoint old = m_points.back();
Shinya Kitaoka 120a6e
        if (norm2(pos - old) < 4) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        int thickness = m_toolSize.getValue();
Shinya Kitaoka 120a6e
        TThickPoint point(pos + rasCenter, thickness);
Shinya Kitaoka 120a6e
        TThickPoint mid((old + point) * 0.5, (point.thick + old.thick) * 0.5);
Shinya Kitaoka 120a6e
        m_points.push_back(mid);
Shinya Kitaoka 120a6e
        m_points.push_back(point);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        int currentStyle = 0;
Shinya Kitaoka 120a6e
        if (m_currentStyle.getValue())
Shinya Kitaoka 120a6e
          currentStyle = TTool::getApplication()->getCurrentLevelStyleIndex();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        TRect bbox;
Shinya Kitaoka 120a6e
        int m = (int)m_points.size();
Shinya Kitaoka 120a6e
        if (m == 3) {
Shinya Kitaoka 120a6e
          // ho appena cominciato. devo disegnare un segmento
Shinya Kitaoka 120a6e
          TThickPoint pa = m_points.front();
Shinya Kitaoka 120a6e
          std::vector<tthickpoint> points;</tthickpoint>
Shinya Kitaoka 120a6e
          points.push_back(pa);
Shinya Kitaoka 120a6e
          points.push_back(mid);
Shinya Kitaoka 120a6e
          invalidateRect = ToolUtils::getBounds(points, thickness);
Shinya Kitaoka 120a6e
          bbox           = m_bluredBrush->getBoundFromPoints(points);
Shinya Kitaoka 120a6e
          m_bluredBrush->addArc(pa, (mid + pa) * 0.5, mid, 1, 1);
Shinya Kitaoka 120a6e
        } else {
Shinya Kitaoka 120a6e
          std::vector<tthickpoint> points;</tthickpoint>
Shinya Kitaoka 120a6e
          points.push_back(m_points[m - 4]);
Shinya Kitaoka 120a6e
          points.push_back(old);
Shinya Kitaoka 120a6e
          points.push_back(mid);
Shinya Kitaoka 120a6e
          invalidateRect = ToolUtils::getBounds(points, thickness);
Shinya Kitaoka 120a6e
          bbox           = m_bluredBrush->getBoundFromPoints(points);
Shinya Kitaoka 120a6e
          m_bluredBrush->addArc(m_points[m - 4], old, mid, 1, 1);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        m_tileSaver->save(bbox);
Shinya Kitaoka 120a6e
        m_bluredBrush->eraseDrawing(ti->getRaster(), m_backupRas, bbox,
Shinya Kitaoka 120a6e
                                    m_currentStyle.getValue(), currentStyle,
Shinya Kitaoka 120a6e
                                    m_colorType.getValue());
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      invalidate(invalidateRect.enlarge(2) - rasCenter);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (m_eraseType.getValue() == FREEHANDERASE) {
Shinya Kitaoka 120a6e
      if (!m_enabled || !m_active) return;
Shinya Kitaoka 120a6e
      m_track.add(TThickPoint(pos, m_thick), pixelSize2);
shun-iwasawa c189d1
      invalidate(m_track.getModifiedRegion());
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
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 *app = TTool::getApplication();
Shinya Kitaoka 120a6e
  TXshSimpleLevel *xshl   = 0;
Shinya Kitaoka 120a6e
  if (app->getCurrentLevel()->getLevel())
Shinya Kitaoka 120a6e
    xshl = app->getCurrentLevel()->getSimpleLevel();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!xshl || m_level.getPointer() != xshl ||
Shinya Kitaoka 120a6e
      (m_selectingRect.isEmpty() && !m_firstStroke))
Shinya Kitaoka 120a6e
    resetMulti();
Shinya Kitaoka 120a6e
  else if (m_firstFrameId == getFrameId())
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 38fd86
  else {                           // cambio stato.
Shinya Kitaoka 120a6e
    m_firstFrameSelected = true;
Shinya Kitaoka 120a6e
    if (m_eraseType.getValue() != FREEHANDERASE &&
Shinya Kitaoka 120a6e
        m_eraseType.getValue() != POLYLINEERASE) {
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
  /*--先にLeftButtonDownに入っていなければ処理をしない--*/
Shinya Kitaoka 120a6e
  if (!m_isLeftButtonPressed) return;
Shinya Kitaoka 120a6e
  m_isLeftButtonPressed = false;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_selecting) return;
Shinya Kitaoka 120a6e
  TImageP image(getImage(true));
Shinya Kitaoka 120a6e
  if (TToonzImageP ti = image) {
Shinya Kitaoka 120a6e
    if (m_eraseType.getValue() == RECTERASE) {
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
        TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
        if (m_firstFrameSelected) {
Shinya Kitaoka 120a6e
          multiUpdate(m_level, m_firstFrameId, getFrameId(), m_firstRect,
Shinya Kitaoka 120a6e
                      m_selectingRect);
Shinya Kitaoka 120a6e
          if (e.isShiftPressed()) {
Shinya Kitaoka 120a6e
            m_firstRect    = m_selectingRect;
Shinya Kitaoka 120a6e
            m_firstFrameId = getFrameId();
Shinya Kitaoka 120a6e
            invalidate();
Shinya Kitaoka 120a6e
          } else {
Shinya Kitaoka 120a6e
            if (m_isXsheetCell) {
Shinya Kitaoka 120a6e
              app->getCurrentColumn()->setColumnIndex(m_currCell.first);
Shinya Kitaoka 120a6e
              app->getCurrentFrame()->setFrame(m_currCell.second);
Shinya Kitaoka 120a6e
            } else
Shinya Kitaoka 120a6e
              app->getCurrentFrame()->setFid(m_veryFirstFrameId);
Shinya Kitaoka 120a6e
            resetMulti();
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        } else {
Shinya Kitaoka 120a6e
          m_isXsheetCell = app->getCurrentFrame()->isEditingScene();
Shinya Kitaoka 120a6e
          m_currCell     = std::pair<int, int="">(getColumnIndex(), getFrame());</int,>
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        TTool::Application *app   = TTool::getApplication();
Shinya Kitaoka 120a6e
        TXshLevel *level          = app->getCurrentLevel()->getLevel();
Shinya Kitaoka 120a6e
        TXshSimpleLevelP simLevel = level->getSimpleLevel();
Shinya Kitaoka 120a6e
        TFrameId frameId          = getFrameId();
Shinya Kitaoka 120a6e
        if (m_invertOption.getValue()) {
Shinya Kitaoka 120a6e
          TUndoManager::manager()->beginBlock();
Shinya Kitaoka 120a6e
          TRectD rect      = m_selectingRect;
Shinya Kitaoka 120a6e
          TRectD worldBBox = ToonzImageUtils::convertRasterToWorld(
Shinya Kitaoka 120a6e
              ti->getRaster()->getBounds(), ti);
Shinya Kitaoka 120a6e
          rect *= ToonzImageUtils::convertRasterToWorld(ti->getSavebox(), ti);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          TRectD rect01 =
Shinya Kitaoka 120a6e
              TRectD(worldBBox.getP00(), TPointD(rect.x0, worldBBox.y1));
Shinya Kitaoka 120a6e
          if (rect01.getLx() > 0 && rect01.getLy() > 0)
Shinya Kitaoka 120a6e
            update(ti, rect01, simLevel, false, frameId);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          TRectD rect02 = TRectD(rect.getP01(), TPointD(rect.x1, worldBBox.y1));
Shinya Kitaoka 120a6e
          if (rect02.getLx() > 0 && rect02.getLy() > 0)
Shinya Kitaoka 120a6e
            update(ti, rect02, simLevel, false, frameId);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          TRectD rect03 = TRectD(TPointD(rect.x0, worldBBox.y0), rect.getP10());
Shinya Kitaoka 120a6e
          if (rect03.getLx() > 0 && rect03.getLy() > 0)
Shinya Kitaoka 120a6e
            update(ti, rect03, simLevel, false, frameId);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          TRectD rect04 = TRectD(TPointD(rect.x1, worldBBox.y0),
Shinya Kitaoka 120a6e
                                 TPointD(worldBBox.x1, worldBBox.y1));
Shinya Kitaoka 120a6e
          if (rect04.getLx() > 0 && rect04.getLy() > 0)
Shinya Kitaoka 120a6e
            update(ti, rect04, simLevel, false, frameId);
Shinya Kitaoka 120a6e
          TUndoManager::manager()->endBlock();
Shinya Kitaoka 120a6e
          invalidate();
Shinya Kitaoka 120a6e
        } else {
Shinya Kitaoka 120a6e
          update(ti, m_selectingRect, simLevel, false, frameId);
Shinya Kitaoka 120a6e
          invalidate(m_selectingRect.enlarge(2));
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        m_selectingRect.empty();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
        notifyImageChanged();
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (m_eraseType.getValue() == NORMALERASE) {
Shinya Kitaoka 120a6e
      TTool::Application *app   = TTool::getApplication();
Shinya Kitaoka 120a6e
      int currentStyle          = app->getCurrentLevelStyleIndex();
Shinya Kitaoka 120a6e
      TXshLevel *level          = app->getCurrentLevel()->getLevel();
Shinya Kitaoka 120a6e
      TXshSimpleLevelP simLevel = level->getSimpleLevel();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /*--Erase中にフレームが動いても、クリック時のFidに対してUndoを記録する--*/
Shinya Kitaoka 120a6e
      TFrameId frameId =
Shinya Kitaoka 120a6e
          m_workingFrameId.isEmptyFrame() ? getCurrentFid() : m_workingFrameId;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (m_normalEraser &&
Shinya Kitaoka 120a6e
          (m_hardness.getValue() == 100 || m_pencil.getValue() ||
Shinya Kitaoka 120a6e
           m_colorType.getValue() == AREAS)) {
Shinya Kitaoka 120a6e
        TUndoManager::manager()->add(new RasterEraserUndo(
Shinya Kitaoka 120a6e
            m_tileSet, m_normalEraser->getPointsSequence(), m_colorTypeEraser,
Shinya Kitaoka 120a6e
            0, m_normalEraser->isSelective(), currentStyle,
Shinya Kitaoka 120a6e
            simLevel.getPointer(), frameId,
Shinya Kitaoka 120a6e
            (m_pencil.getValue() || m_colorType.getValue() == AREAS)));
Shinya Kitaoka 120a6e
        app->getCurrentTool()->getTool()->notifyImageChanged(frameId);
Shinya Kitaoka 120a6e
        app->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
        delete m_normalEraser;
Shinya Kitaoka 120a6e
        m_normalEraser = 0;
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        if (m_points.size() != 1) {
Shinya Kitaoka 120a6e
          TPointD rasCenter = ti->getRaster()->getCenterD();
Shinya Kitaoka 120a6e
          TThickPoint point(pos + rasCenter, m_toolSize.getValue());
Shinya Kitaoka 120a6e
          m_points.push_back(point);
Shinya Kitaoka 120a6e
          int m = m_points.size();
Shinya Kitaoka 120a6e
          std::vector<tthickpoint> points;</tthickpoint>
Shinya Kitaoka 120a6e
          points.push_back(m_points[m - 3]);
Shinya Kitaoka 120a6e
          points.push_back(m_points[m - 2]);
Shinya Kitaoka 120a6e
          points.push_back(m_points[m - 1]);
Shinya Kitaoka 120a6e
          TRect bbox = m_bluredBrush->getBoundFromPoints(points);
Shinya Kitaoka 120a6e
          m_tileSaver->save(bbox);
Shinya Kitaoka 120a6e
          m_bluredBrush->addArc(points[0], points[1], points[2], 1, 1);
Shinya Kitaoka 120a6e
          m_bluredBrush->eraseDrawing(ti->getRaster(), m_backupRas, bbox,
Shinya Kitaoka 120a6e
                                      m_currentStyle.getValue(), currentStyle,
Shinya Kitaoka 120a6e
                                      m_colorType.getValue());
Shinya Kitaoka 120a6e
          TRectD invalidateRect =
Shinya Kitaoka 120a6e
              ToolUtils::getBounds(points, m_toolSize.getValue());
Shinya Kitaoka 120a6e
          invalidate(invalidateRect.enlarge(2) - rasCenter);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        m_backupRas = TRasterCM32P();
Shinya Kitaoka 120a6e
        m_workRas   = TRaster32P();
Shinya Kitaoka 120a6e
        delete m_bluredBrush;
Shinya Kitaoka 120a6e
        m_bluredBrush = 0;
Shinya Kitaoka 120a6e
        TUndoManager::manager()->add(new RasterBluredEraserUndo(
Shinya Kitaoka 120a6e
            m_tileSet, m_points, currentStyle, m_currentStyle.getValue(),
Shinya Kitaoka 120a6e
            simLevel.getPointer(), frameId, m_toolSize.getValue(),
Shinya Kitaoka 120a6e
            m_hardness.getValue() * 0.01, m_colorType.getValue()));
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      delete m_tileSaver;
Shinya Kitaoka 120a6e
      m_tileSaver = 0;
Shinya Kitaoka 120a6e
      /*-- 作業したフレームをシグナルで知らせる --*/
Shinya Kitaoka 120a6e
      notifyImageChanged(frameId);
Shinya Kitaoka 120a6e
      /*-- 作業フレームをリセット --*/
Shinya Kitaoka 120a6e
      m_workingFrameId = TFrameId();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (m_eraseType.getValue() == FREEHANDERASE) {
Shinya Kitaoka 120a6e
      bool isValid = m_enabled && m_active;
Shinya Kitaoka 120a6e
      m_enabled = m_active = false;
Shinya Kitaoka 120a6e
      if (!isValid) return;
Shinya Kitaoka 120a6e
      if (m_track.isEmpty()) return;
Shinya Kitaoka 120a6e
      double pixelSize2 = getPixelSize() * getPixelSize();
Shinya Kitaoka 120a6e
      m_track.add(TThickPoint(m_firstPos, m_thick), pixelSize2);
Shinya Kitaoka 120a6e
      m_track.filterPoints();
Shinya Kitaoka 120a6e
      double error    = (30.0 / 11) * sqrt(pixelSize2);
Shinya Kitaoka 120a6e
      TStroke *stroke = m_track.makeStroke(error);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      stroke->setStyle(1);
Shinya Kitaoka 120a6e
      m_track.clear();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
      int styleId             = app->getCurrentLevelStyleIndex();
Shinya Kitaoka 120a6e
      if (m_multi.getValue())  // stroke multi
Shinya Kitaoka 120a6e
      {
Shinya Kitaoka 120a6e
        if (m_firstFrameSelected) {
Shinya Kitaoka 120a6e
          TFrameId tmp = getFrameId();
Shinya Kitaoka 120a6e
          if (m_firstStroke && stroke)
Shinya Kitaoka 120a6e
            multiAreaEraser(m_level, m_firstFrameId, tmp, m_firstStroke,
Shinya Kitaoka 120a6e
                            stroke);
Shinya Kitaoka 120a6e
          notifyImageChanged();
Shinya Kitaoka 120a6e
          if (e.isShiftPressed()) {
Shinya Kitaoka 120a6e
            TRectD invalidateRect = m_firstStroke->getBBox();
Shinya Kitaoka 120a6e
            delete m_firstStroke;
Shinya Kitaoka 120a6e
            m_firstStroke = 0;
Shinya Kitaoka 120a6e
            invalidate(invalidateRect.enlarge(2));
Shinya Kitaoka 120a6e
            m_firstStroke  = stroke;
Shinya Kitaoka 120a6e
            invalidateRect = m_firstStroke->getBBox();
Shinya Kitaoka 120a6e
            invalidate(invalidateRect.enlarge(2));
Shinya Kitaoka 120a6e
            m_firstFrameId = getFrameId();
Shinya Kitaoka 120a6e
          } else {
Shinya Kitaoka 120a6e
            if (m_isXsheetCell) {
Shinya Kitaoka 120a6e
              app->getCurrentColumn()->setColumnIndex(m_currCell.first);
Shinya Kitaoka 120a6e
              app->getCurrentFrame()->setFrame(m_currCell.second);
Shinya Kitaoka 120a6e
            } else
Shinya Kitaoka 120a6e
              app->getCurrentFrame()->setFid(m_veryFirstFrameId);
Shinya Kitaoka 120a6e
            resetMulti();
Shinya Kitaoka 120a6e
            delete stroke;
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        } else  // primo frame
Shinya Kitaoka 120a6e
        {
Shinya Kitaoka 120a6e
          m_firstStroke  = stroke;
Shinya Kitaoka 120a6e
          m_isXsheetCell = app->getCurrentFrame()->isEditingScene();
Shinya Kitaoka 120a6e
          m_currCell     = std::pair<int, int="">(getColumnIndex(), getFrame());</int,>
Shinya Kitaoka 120a6e
          invalidate(m_firstStroke->getBBox().enlarge(2));
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      } else  // stroke non multi
Shinya Kitaoka 120a6e
      {
Shinya Kitaoka 120a6e
        if (!getImage(true)) return;
Shinya Kitaoka 120a6e
        TXshLevel *level          = app->getCurrentLevel()->getLevel();
Shinya Kitaoka 120a6e
        TXshSimpleLevelP simLevel = level->getSimpleLevel();
Shinya Kitaoka 120a6e
        TFrameId frameId          = getFrameId();
Shinya Kitaoka 120a6e
        eraseStroke(image, stroke, m_eraseType.getValue(),
Shinya Kitaoka 120a6e
                    m_colorType.getValue(), m_invertOption.getValue(),
Shinya Kitaoka 120a6e
                    m_currentStyle.getValue(), styleId, simLevel, frameId);
Shinya Kitaoka 120a6e
        notifyImageChanged();
Shinya Kitaoka 120a6e
        if (m_invertOption.getValue())
Shinya Kitaoka 120a6e
          invalidate();
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          invalidate(stroke->getBBox().enlarge(2));
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    ToolUtils::updateSaveBox();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_selecting = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::leftButtonDoubleClick(const TPointD &pos,
Shinya Kitaoka 120a6e
                                       const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  TStroke *stroke;
Shinya Kitaoka 120a6e
  TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
  if (m_polyline.size() <= 1) {
Shinya Kitaoka 120a6e
    resetMulti();
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
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
  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
  stroke = new TStroke(strokePoints);
Shinya Kitaoka 120a6e
  assert(stroke->getPoint(0) == stroke->getPoint(1));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int styleId = app->getCurrentLevelStyleIndex();
Shinya Kitaoka 120a6e
  if (m_multi.getValue())  // stroke multi
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    if (m_firstFrameSelected) {
Shinya Kitaoka 120a6e
      TFrameId tmp = getFrameId();
Shinya Kitaoka 120a6e
      if (m_firstStroke && stroke)
Shinya Kitaoka 120a6e
        multiAreaEraser(m_level, m_firstFrameId, tmp, m_firstStroke, stroke);
Shinya Kitaoka 120a6e
      if (e.isShiftPressed()) {
Shinya Kitaoka 120a6e
        TRectD invalidateRect = m_firstStroke->getBBox();
Shinya Kitaoka 120a6e
        delete m_firstStroke;
Shinya Kitaoka 120a6e
        m_firstStroke = 0;
Shinya Kitaoka 120a6e
        invalidate(invalidateRect.enlarge(2));
Shinya Kitaoka 120a6e
        m_firstStroke  = stroke;
Shinya Kitaoka 120a6e
        invalidateRect = m_firstStroke->getBBox();
Shinya Kitaoka 120a6e
        invalidate(invalidateRect.enlarge(2));
Shinya Kitaoka 120a6e
        m_firstFrameId = getFrameId();
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        if (m_isXsheetCell) {
Shinya Kitaoka 120a6e
          app->getCurrentColumn()->setColumnIndex(m_currCell.first);
Shinya Kitaoka 120a6e
          app->getCurrentFrame()->setFrame(m_currCell.second);
Shinya Kitaoka 120a6e
        } else
Shinya Kitaoka 120a6e
          app->getCurrentFrame()->setFid(m_veryFirstFrameId);
Shinya Kitaoka 120a6e
        resetMulti();
Shinya Kitaoka 120a6e
        delete stroke;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else  // primo frame
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      m_firstStroke  = stroke;
Shinya Kitaoka 120a6e
      m_isXsheetCell = app->getCurrentFrame()->isEditingScene();
Shinya Kitaoka 120a6e
      m_currCell     = std::pair<int, int="">(getColumnIndex(), getFrame());</int,>
Shinya Kitaoka 120a6e
      invalidate(m_firstStroke->getBBox().enlarge(2));
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    if (!getImage(true)) return;
Shinya Kitaoka 120a6e
    TXshLevel *level          = app->getCurrentLevel()->getLevel();
Shinya Kitaoka 120a6e
    TXshSimpleLevelP simLevel = level->getSimpleLevel();
Shinya Kitaoka 120a6e
    TFrameId frameId          = getFrameId();
Shinya Kitaoka 120a6e
    TToonzImageP ti           = (TToonzImageP)getImage(true);
Shinya Kitaoka 120a6e
    eraseStroke(ti, stroke, m_eraseType.getValue(), m_colorType.getValue(),
Shinya Kitaoka 120a6e
                m_invertOption.getValue(), m_currentStyle.getValue(), styleId,
Shinya Kitaoka 120a6e
                simLevel, frameId);
Shinya Kitaoka 120a6e
    notifyImageChanged();
Shinya Kitaoka 120a6e
    if (m_invertOption.getValue())
Shinya Kitaoka 120a6e
      invalidate();
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      invalidate(stroke->getBBox().enlarge(2));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool EraserTool::onPropertyChanged(std::string propertyName) {
Shinya Kitaoka 120a6e
  /*--- 変更されたPropertyに合わせて処理を分ける ---*/
Shinya Kitaoka 120a6e
  if (propertyName == m_eraseType.getName()) {
Shinya Kitaoka 120a6e
    /*--- polylineにした時、前回のpolyline選択をクリアする ---*/
Shinya Kitaoka 120a6e
    if (m_eraseType.getValue() == POLYLINEERASE && !m_polyline.empty())
Shinya Kitaoka 120a6e
      m_polyline.clear();
Shinya Kitaoka 120a6e
    EraseType = ::to_string(m_eraseType.getValue());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  else if (propertyName == m_toolSize.getName()) {
Shinya Kitaoka 120a6e
    EraseSize     = m_toolSize.getValue();
Shinya Kitaoka 120a6e
    m_cleanerSize = m_toolSize.getValue();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_brushPad = ToolUtils::getBrushPad(m_toolSize.getValue(),
Shinya Kitaoka 120a6e
                                        m_hardness.getValue() * 0.01);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  else if (propertyName == m_invertOption.getName())
Shinya Kitaoka 120a6e
    EraseInvert = m_invertOption.getValue();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  else if (propertyName == m_currentStyle.getName())
Shinya Kitaoka 120a6e
    EraseSelective = m_currentStyle.getValue();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  else if (propertyName == m_multi.getName()) {
Shinya Kitaoka 120a6e
    if (m_multi.getValue()) resetMulti();
Shinya Kitaoka 120a6e
    EraseRange = m_multi.getValue();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  else if (propertyName == m_pencil.getName()) {
Shinya Kitaoka 120a6e
    ErasePencil = m_pencil.getValue();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  else if (propertyName == m_colorType.getName()) {
Shinya Kitaoka 120a6e
    EraseColorType = ::to_string(m_colorType.getValue());
Shinya Kitaoka 120a6e
    /*-- ColorModelのCursor更新のためにSIGNALを出す --*/
Shinya Kitaoka 120a6e
    TTool::getApplication()->getCurrentTool()->notifyToolChanged();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  else if (propertyName == m_hardness.getName()) {
Shinya Kitaoka 120a6e
    EraseHardness = m_hardness.getValue();
Shinya Kitaoka 120a6e
    m_brushPad    = ToolUtils::getBrushPad(m_toolSize.getValue(),
Shinya Kitaoka 120a6e
                                        m_hardness.getValue() * 0.01);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (propertyName == m_hardness.getName() ||
Shinya Kitaoka 120a6e
      propertyName == m_toolSize.getName()) {
Shinya Kitaoka 120a6e
    m_brushPad = ToolUtils::getBrushPad(m_toolSize.getValue(),
Shinya Kitaoka 120a6e
                                        m_hardness.getValue() * 0.01);
Shinya Kitaoka 120a6e
    TRectD rect(m_brushPos - TPointD(EraseSize + 2, EraseSize + 2),
Shinya Kitaoka 120a6e
                m_brushPos + TPointD(EraseSize + 2, EraseSize + 2));
Shinya Kitaoka 120a6e
    invalidate(rect);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*--- Erase動作中にプロパティが変わったら、終了処理を行う ---*/
Shinya Kitaoka 120a6e
  if (m_isLeftButtonPressed) {
Shinya Kitaoka 120a6e
    storeUndoAndRefresh();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return true;
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
  qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  struct Locals {
Shinya Kitaoka 120a6e
    EraserTool *m_this;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    void setValue(TIntProperty &prop, int value) {
Shinya Kitaoka 120a6e
      prop.setValue(value);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      m_this->onPropertyChanged(prop.getName());
Shinya Kitaoka 120a6e
      TTool::getApplication()->getCurrentTool()->notifyToolChanged();
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    void addValue(TIntProperty &prop, double add) {
Shinya Kitaoka 120a6e
      const TIntProperty::Range &range = prop.getRange();
Shinya Kitaoka 120a6e
      setValue(prop,
Shinya Kitaoka 120a6e
               tcrop<double>(prop.getValue() + add, range.first, range.second));</double>
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  } locals = {this};
Toshihiro Shimizu 890ddd
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;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    locals.addValue(m_toolSize, add);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  default:
Shinya Kitaoka 120a6e
    m_brushPos = pos;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_mousePos = pos;
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::onEnter() {
Shinya Kitaoka 120a6e
  TToonzImageP ti(getImage(false));
Shinya Kitaoka 120a6e
  if (!ti) return;
Shinya Kitaoka 120a6e
  if (m_firstTime) {
Shinya Kitaoka 120a6e
    m_toolSize.setValue(EraseSize);
Shinya Kitaoka 120a6e
    m_eraseType.setValue(::to_wstring(EraseType.getValue()));
Shinya Kitaoka 120a6e
    m_currentStyle.setValue(EraseSelective ? 1 : 0);
Shinya Kitaoka 120a6e
    m_invertOption.setValue(EraseInvert ? 1 : 0);
Shinya Kitaoka 120a6e
    m_colorType.setValue(::to_wstring(EraseColorType.getValue()));
Shinya Kitaoka 120a6e
    m_multi.setValue(EraseRange ? 1 : 0);
Shinya Kitaoka 120a6e
    m_hardness.setValue(EraseHardness);
Shinya Kitaoka 120a6e
    m_pencil.setValue(ErasePencil);
Shinya Kitaoka 120a6e
    m_firstTime = false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  double x = m_toolSize.getValue();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double minRange = 1;
Shinya Kitaoka 120a6e
  double maxRange = 100;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double minSize = 0.1;
Shinya Kitaoka 120a6e
  double maxSize = 100;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_pointSize =
Shinya Kitaoka 120a6e
      (x - minRange) / (maxRange - minRange) * (maxSize - minSize) + minSize;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //  getApplication()->editImage();
Shinya Kitaoka 120a6e
  m_cleanerSize           = m_toolSize.getValue();
Shinya Kitaoka 120a6e
  TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
  m_level                 = app->getCurrentLevel()->getLevel()
Shinya Kitaoka 120a6e
                ? app->getCurrentLevel()->getSimpleLevel()
Shinya Kitaoka 120a6e
                : 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::onLeave() {
Shinya Kitaoka 120a6e
  m_pointSize   = -1;
Shinya Kitaoka 120a6e
  m_cleanerSize = 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::onActivate() {
Shinya Kitaoka 120a6e
  if (m_multi.getValue()) resetMulti();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /*-- 他のツールからpolylineに入った時、前回のpolyline選択をクリアする --*/
Shinya Kitaoka 120a6e
  if (m_eraseType.getValue() == POLYLINEERASE && !m_polyline.empty())
Shinya Kitaoka 120a6e
    m_polyline.clear();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  onEnter();
Shinya Kitaoka 120a6e
  m_brushPad = ToolUtils::getBrushPad(m_toolSize.getValue(),
Shinya Kitaoka 120a6e
                                      m_hardness.getValue() * 0.01);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::multiAreaEraser(const TXshSimpleLevelP &sl, TFrameId &firstFid,
Shinya Kitaoka 120a6e
                                 TFrameId &lastFid, TStroke *firstStroke,
Shinya Kitaoka 120a6e
                                 TStroke *lastStroke) {
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 (firstFid > lastFid) {
Shinya Kitaoka 120a6e
    tswap(firstFid, lastFid);
Shinya Kitaoka 120a6e
    backward = true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  assert(firstFid <= lastFid);
Shinya Kitaoka 120a6e
  std::vector<tframeid> allFids;</tframeid>
Shinya Kitaoka 120a6e
  sl->getFids(allFids);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<tframeid>::iterator i0 = allFids.begin();</tframeid>
Shinya Kitaoka 120a6e
  while (i0 != allFids.end() && *i0 < firstFid) 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 <= lastFid) 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
  TUndoManager::manager()->beginBlock();
Shinya Kitaoka 120a6e
  for (int i = 0; i < m; ++i) {
Shinya Kitaoka 120a6e
    TFrameId fid = fids[i];
Shinya Kitaoka 120a6e
    assert(firstFid <= fid && fid <= lastFid);
Shinya Kitaoka 120a6e
    TImageP img = sl->getFrame(fid, true);
Shinya Kitaoka 120a6e
    double t    = m > 1 ? (double)i / (double)(m - 1) : 0.5;
Shinya Kitaoka 120a6e
    doMultiEraser(img, backward ? 1 - t : t, sl, fid, firstImage, lastImage);
Shinya Kitaoka 120a6e
    sl->getProperties()->setDirtyFlag(true);
Shinya Kitaoka 120a6e
    notifyImageChanged(fid);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  TUndoManager::manager()->endBlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void EraserTool::doMultiEraser(const TImageP &img, double t,
Shinya Kitaoka 120a6e
                               const TXshSimpleLevelP &sl, const TFrameId &fid,
Shinya Kitaoka 120a6e
                               const TVectorImageP &firstImage,
Shinya Kitaoka 120a6e
                               const TVectorImageP &lastImage) {
Shinya Kitaoka 120a6e
  //  ColorController::instance()->switchToLevelPalette();
Shinya Kitaoka 120a6e
  int styleId = TTool::getApplication()->getCurrentLevelStyleIndex();
Shinya Kitaoka 120a6e
  if (t == 0)
Shinya Kitaoka 120a6e
    eraseStroke(img, firstImage->getStroke(0), m_eraseType.getValue(),
Shinya Kitaoka 120a6e
                m_colorType.getValue(), m_invertOption.getValue(),
Shinya Kitaoka 120a6e
                m_currentStyle.getValue(), styleId, sl, fid);
Shinya Kitaoka 120a6e
  else if (t == 1)
Shinya Kitaoka 120a6e
    eraseStroke(img, lastImage->getStroke(0), m_eraseType.getValue(),
Shinya Kitaoka 120a6e
                m_colorType.getValue(), m_invertOption.getValue(),
Shinya Kitaoka 120a6e
                m_currentStyle.getValue(), styleId, sl, fid);
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
    eraseStroke(img, vi->getStroke(0), m_eraseType.getValue(),
Shinya Kitaoka 120a6e
                m_colorType.getValue(), m_invertOption.getValue(),
Shinya Kitaoka 120a6e
                m_currentStyle.getValue(), styleId, sl, fid);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*!ドラッグ中にツールが切り替わった時、終了処理を行う
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EraserTool::onDeactivate() {
Shinya Kitaoka 120a6e
  if (!m_isLeftButtonPressed || !m_selecting) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  storeUndoAndRefresh();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*-- Erase終了処理 --*/
Shinya Kitaoka 120a6e
void EraserTool::storeUndoAndRefresh() {
Shinya Kitaoka 120a6e
  m_isLeftButtonPressed = false;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*-- 各データのリフレッシュ --*/
Shinya Kitaoka 120a6e
  if (m_firstStroke) {
Shinya Kitaoka 120a6e
    delete m_firstStroke;
Shinya Kitaoka 120a6e
    m_firstStroke = 0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (m_normalEraser) {
Shinya Kitaoka 120a6e
    TUndoManager::manager()->add(new RasterEraserUndo(
Shinya Kitaoka 120a6e
        m_tileSet, m_normalEraser->getPointsSequence(), m_colorTypeEraser, 0,
Shinya Kitaoka 120a6e
        m_normalEraser->isSelective(),
Shinya Kitaoka 120a6e
        TTool::getApplication()->getCurrentLevelStyleIndex(),
Shinya Kitaoka 120a6e
        TTool::getApplication()
Shinya Kitaoka 120a6e
            ->getCurrentLevel()
Shinya Kitaoka 120a6e
            ->getLevel()
Shinya Kitaoka 120a6e
            ->getSimpleLevel(),
Shinya Kitaoka 120a6e
        m_workingFrameId.isEmptyFrame() ? getCurrentFid() : m_workingFrameId,
Shinya Kitaoka 120a6e
        (m_pencil.getValue() || m_colorType.getValue() == AREAS)));
Shinya Kitaoka 120a6e
    delete m_normalEraser;
Shinya Kitaoka 120a6e
    m_normalEraser = 0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (m_bluredBrush) {
Shinya Kitaoka 120a6e
    m_backupRas = TRasterCM32P();
Shinya Kitaoka 120a6e
    m_workRas   = TRaster32P();
Shinya Kitaoka 120a6e
    delete m_bluredBrush;
Shinya Kitaoka 120a6e
    m_bluredBrush = 0;
Shinya Kitaoka 120a6e
    TUndoManager::manager()->add(new RasterBluredEraserUndo(
Shinya Kitaoka 120a6e
        m_tileSet, m_points,
Shinya Kitaoka 120a6e
        TTool::getApplication()->getCurrentLevelStyleIndex(),
Shinya Kitaoka 120a6e
        m_currentStyle.getValue(), TTool::getApplication()
Shinya Kitaoka 120a6e
                                       ->getCurrentLevel()
Shinya Kitaoka 120a6e
                                       ->getLevel()
Shinya Kitaoka 120a6e
                                       ->getSimpleLevel(),
Shinya Kitaoka 120a6e
        m_workingFrameId.isEmptyFrame() ? getCurrentFid() : m_workingFrameId,
Shinya Kitaoka 120a6e
        m_toolSize.getValue(), m_hardness.getValue() * 0.01,
Shinya Kitaoka 120a6e
        m_colorType.getValue()));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (m_tileSaver) {
Shinya Kitaoka 120a6e
    delete m_tileSaver;
Shinya Kitaoka 120a6e
    m_tileSaver = 0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRectD invalidateRect;
Shinya Kitaoka 120a6e
  if (m_firstRect != TRectD()) {
Shinya Kitaoka 120a6e
    invalidateRect += m_firstRect;
Shinya Kitaoka 120a6e
    m_firstRect.empty();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (m_selectingRect != TRectD()) {
Shinya Kitaoka 120a6e
    invalidateRect += m_selectingRect;
Shinya Kitaoka 120a6e
    m_selectingRect.empty();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (!m_track.isEmpty()) m_track.clear();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!invalidateRect.isEmpty()) invalidate(invalidateRect.enlarge(2));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Brush、PaintBrush、EraserToolがPencilModeのときにTrueを返す
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
bool EraserTool::isPencilModeActive() {
Shinya Kitaoka 120a6e
  return m_eraseType.getValue() == NORMALERASE && m_pencil.getValue();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace