shun-iwasawa 14c787
#include "fullcolorfilltool.h"
shun-iwasawa 14c787
shun-iwasawa 14c787
#include "toonz/stage2.h"
shun-iwasawa 14c787
#include "tools/cursors.h"
shun-iwasawa 14c787
#include "toonz/txshlevelhandle.h"
shun-iwasawa 14c787
#include "toonz/trasterimageutils.h"
shun-iwasawa 14c787
#include "toonz/ttileset.h"
shun-iwasawa 14c787
#include "toonz/ttilesaver.h"
shun-iwasawa 14c787
#include "toonz/levelproperties.h"
shun-iwasawa 14c787
#include "toonz/preferences.h"
shun-iwasawa 14c787
#include "toonz/txsheethandle.h"
shun-iwasawa 14c787
shun-iwasawa 14c787
#include "tools/toolhandle.h"
shun-iwasawa 14c787
#include "tools/toolutils.h"
shun-iwasawa 14c787
shun-iwasawa 14c787
#include "tenv.h"
shun-iwasawa 14c787
#include "tpalette.h"
shun-iwasawa 14c787
#include "tsystem.h"
shun-iwasawa 14c787
shun-iwasawa 14c787
using namespace ToolUtils;
shun-iwasawa 14c787
shun-iwasawa 14c787
TEnv::IntVar FullColorMinFillDepth("InknpaintFullColorMinFillDepth", 4);
shun-iwasawa 14c787
TEnv::IntVar FullColorMaxFillDepth("InknpaintFullColorMaxFillDepth", 12);
shun-iwasawa 14c787
shun-iwasawa 14c787
namespace {
shun-iwasawa 14c787
shun-iwasawa 14c787
//=============================================================================
shun-iwasawa 14c787
// FullColorFillUndo
shun-iwasawa 14c787
//-----------------------------------------------------------------------------
shun-iwasawa 14c787
shun-iwasawa 14c787
class FullColorFillUndo final : public TFullColorRasterUndo {
shun-iwasawa 14c787
  FillParameters m_params;
shun-iwasawa 14c787
  bool m_saveboxOnly;
shun-iwasawa 14c787
shun-iwasawa 14c787
public:
shun-iwasawa 14c787
  FullColorFillUndo(TTileSetFullColor *tileSet, const FillParameters &params,
shun-iwasawa 14c787
                    TXshSimpleLevel *sl, const TFrameId &fid, bool saveboxOnly)
shun-iwasawa 14c787
      : TFullColorRasterUndo(tileSet, sl, fid, false, false, 0)
shun-iwasawa 14c787
      , m_params(params)
shun-iwasawa 14c787
      , m_saveboxOnly(saveboxOnly) {}
shun-iwasawa 14c787
shun-iwasawa 14c787
  void redo() const override {
shun-iwasawa 14c787
    TRasterImageP image = getImage();
shun-iwasawa 14c787
    if (!image) return;
shun-iwasawa 14c787
    TRaster32P r;
shun-iwasawa 14c787
    if (m_saveboxOnly) {
shun-iwasawa 14c787
      TRectD temp = image->getBBox();
shun-iwasawa 14c787
      TRect ttemp = convert(temp);
shun-iwasawa 14c787
      r           = image->getRaster()->extract(ttemp);
shun-iwasawa 14c787
    } else
shun-iwasawa 14c787
      r = image->getRaster();
shun-iwasawa 14c787
shun-iwasawa 14c787
    fullColorFill(r, m_params);
shun-iwasawa 14c787
shun-iwasawa 14c787
    TTool::Application *app = TTool::getApplication();
shun-iwasawa 14c787
    if (app) {
shun-iwasawa 14c787
      app->getCurrentXsheet()->notifyXsheetChanged();
shun-iwasawa 14c787
      notifyImageChanged();
shun-iwasawa 14c787
    }
shun-iwasawa 14c787
  }
shun-iwasawa 14c787
shun-iwasawa 14c787
  int getSize() const override {
shun-iwasawa 14c787
    return sizeof(*this) + TFullColorRasterUndo::getSize();
shun-iwasawa 14c787
  }
shun-iwasawa 14c787
shun-iwasawa 14c787
  QString getToolName() override {
shun-iwasawa 14c787
    return QString("Fill Tool : %1")
shun-iwasawa 14c787
        .arg(QString::fromStdWString(m_params.m_fillType));
shun-iwasawa 14c787
  }
shun-iwasawa 14c787
  int getHistoryType() override { return HistoryType::FillTool; }
shun-iwasawa 14c787
};
shun-iwasawa 14c787
shun-iwasawa 14c787
//=============================================================================
shun-iwasawa 14c787
// doFill
shun-iwasawa 14c787
//-----------------------------------------------------------------------------
shun-iwasawa 14c787
shun-iwasawa 14c787
void doFill(const TImageP &img, const TPointD &pos, FillParameters &params,
shun-iwasawa 14c787
            bool isShiftFill, TXshSimpleLevel *sl, const TFrameId &fid) {
shun-iwasawa 14c787
  TTool::Application *app = TTool::getApplication();
shun-iwasawa 14c787
  if (!app || !sl) return;
shun-iwasawa 14c787
shun-iwasawa 14c787
  if (TRasterImageP ri = TRasterImageP(img)) {
shun-iwasawa 14c787
    TPoint offs(0, 0);
shun-iwasawa 14c787
    TRaster32P ras = ri->getRaster();
shun-iwasawa 14c787
    // only accept 32bpp images for now
shun-iwasawa 14c787
    if (!ras.getPointer() || ras->isEmpty()) return;
shun-iwasawa 14c787
shun-iwasawa 14c787
    ras->lock();
shun-iwasawa 14c787
shun-iwasawa 14c787
    TTileSetFullColor *tileSet = new TTileSetFullColor(ras->getSize());
shun-iwasawa 14c787
    TTileSaverFullColor tileSaver(ras, tileSet);
shun-iwasawa 14c787
    TDimension imageSize = ras->getSize();
shun-iwasawa 14c787
    TPointD p(imageSize.lx % 2 ? 0.0 : 0.5, imageSize.ly % 2 ? 0.0 : 0.5);
shun-iwasawa 14c787
shun-iwasawa 14c787
    /*-- params.m_p = convert(pos-p)では、マイナス座標でずれが生じる --*/
shun-iwasawa 14c787
    TPointD tmp_p = pos - p;
shun-iwasawa 14c787
    params.m_p = TPoint((int)floor(tmp_p.x + 0.5), (int)floor(tmp_p.y + 0.5));
shun-iwasawa 14c787
shun-iwasawa 14c787
    params.m_p += ras->getCenter();
shun-iwasawa 14c787
    params.m_p -= offs;
shun-iwasawa 14c787
    params.m_shiftFill = isShiftFill;
shun-iwasawa 14c787
shun-iwasawa 14c787
    TRect rasRect(ras->getSize());
shun-iwasawa 14c787
    if (!rasRect.contains(params.m_p)) {
shun-iwasawa 14c787
      ras->unlock();
shun-iwasawa 14c787
      return;
shun-iwasawa 14c787
    }
shun-iwasawa 14c787
shun-iwasawa 14c787
    fullColorFill(ras, params, &tileSaver);
shun-iwasawa 14c787
shun-iwasawa 14c787
    if (tileSaver.getTileSet()->getTileCount() != 0) {
shun-iwasawa 14c787
      static int count = 0;
shun-iwasawa 14c787
      TSystem::outputDebug("RASTERFILL" + std::to_string(count++) + "\n");
shun-iwasawa 14c787
      if (offs != TPoint())
shun-iwasawa 14c787
        for (int i = 0; i < tileSet->getTileCount(); i++) {
shun-iwasawa 14c787
          TTileSet::Tile *t = tileSet->editTile(i);
shun-iwasawa 14c787
          t->m_rasterBounds = t->m_rasterBounds + offs;
shun-iwasawa 14c787
        }
shun-iwasawa 14c787
      TUndoManager::manager()->add(
shun-iwasawa 14c787
          new FullColorFillUndo(tileSet, params, sl, fid,
shun-iwasawa 14c787
                                Preferences::instance()->getFillOnlySavebox()));
shun-iwasawa 14c787
    }
shun-iwasawa 14c787
shun-iwasawa 14c787
    sl->getProperties()->setDirtyFlag(true);
shun-iwasawa 14c787
shun-iwasawa 14c787
    ras->unlock();
shun-iwasawa 14c787
  }
shun-iwasawa 14c787
shun-iwasawa 14c787
  TTool *t = app->getCurrentTool()->getTool();
shun-iwasawa 14c787
  if (t) t->notifyImageChanged();
shun-iwasawa 14c787
}
shun-iwasawa 14c787
};
shun-iwasawa 14c787
shun-iwasawa 14c787
//=============================================================================
shun-iwasawa 14c787
// FullColorFillTool
shun-iwasawa 14c787
//-----------------------------------------------------------------------------
shun-iwasawa 14c787
shun-iwasawa 14c787
//-----------------------------------------------------------------------------
shun-iwasawa 14c787
shun-iwasawa 14c787
FullColorFillTool::FullColorFillTool()
shun-iwasawa 14c787
    : TTool("T_Fill"), m_fillDepth("Fill Depth", 0, 15, 4, 12) {
shun-iwasawa 14c787
  bind(TTool::RasterImage);
shun-iwasawa 14c787
  m_prop.bind(m_fillDepth);
shun-iwasawa 14c787
}
shun-iwasawa 14c787
shun-iwasawa 14c787
void FullColorFillTool::updateTranslation() {
shun-iwasawa 14c787
  m_fillDepth.setQStringName(tr("Fill Depth"));
shun-iwasawa 14c787
}
shun-iwasawa 14c787
shun-iwasawa 14c787
FillParameters FullColorFillTool::getFillParameters() const {
shun-iwasawa 14c787
  FillParameters params;
shun-iwasawa 14c787
  int styleId           = TTool::getApplication()->getCurrentLevelStyleIndex();
shun-iwasawa 14c787
  params.m_styleId      = styleId;
shun-iwasawa 14c787
  params.m_minFillDepth = (int)m_fillDepth.getValue().first;
shun-iwasawa 14c787
  params.m_maxFillDepth = (int)m_fillDepth.getValue().second;
shun-iwasawa 14c787
shun-iwasawa 14c787
  if (m_level) params.m_palette = m_level->getPalette();
shun-iwasawa 14c787
  return params;
shun-iwasawa 14c787
}
shun-iwasawa 14c787
shun-iwasawa 14c787
void FullColorFillTool::leftButtonDown(const TPointD &pos,
shun-iwasawa 14c787
                                       const TMouseEvent &e) {
shun-iwasawa 14c787
  m_clickPoint  = pos;
shun-iwasawa 14c787
  TXshLevel *xl = TTool::getApplication()->getCurrentLevel()->getLevel();
shun-iwasawa 14c787
  m_level       = xl ? xl->getSimpleLevel() : 0;
shun-iwasawa 14c787
  FillParameters params = getFillParameters();
shun-iwasawa 14c787
  doFill(getImage(true), pos, params, e.isShiftPressed(), m_level.getPointer(),
shun-iwasawa 14c787
         getCurrentFid());
shun-iwasawa 14c787
  invalidate();
shun-iwasawa 14c787
}
shun-iwasawa 14c787
shun-iwasawa 14c787
void FullColorFillTool::leftButtonDrag(const TPointD &pos,
shun-iwasawa 14c787
                                       const TMouseEvent &e) {
shun-iwasawa 14c787
  FillParameters params = getFillParameters();
shun-iwasawa 14c787
  if (m_clickPoint == pos) return;
shun-iwasawa 14c787
  if (!m_level || !params.m_palette) return;
shun-iwasawa 14c787
  TImageP img = getImage(true);
shun-iwasawa 14c787
  TPixel32 fillColor =
shun-iwasawa 14c787
      params.m_palette->getStyle(params.m_styleId)->getMainColor();
shun-iwasawa 14c787
  if (TRasterImageP ri = img) {
shun-iwasawa 14c787
    TRaster32P ras = ri->getRaster();
shun-iwasawa 14c787
    if (!ras) return;
shun-iwasawa 14c787
    TPointD center = ras->getCenterD();
shun-iwasawa 14c787
    TPoint ipos    = convert(pos + center);
shun-iwasawa 14c787
    if (!ras->getBounds().contains(ipos)) return;
shun-iwasawa 14c787
    TPixel32 pix = ras->pixels(ipos.y)[ipos.x];
shun-iwasawa 14c787
    if (pix == fillColor) {
shun-iwasawa 14c787
      invalidate();
shun-iwasawa 14c787
      return;
shun-iwasawa 14c787
    }
shun-iwasawa 14c787
  } else
shun-iwasawa 14c787
    return;
shun-iwasawa 14c787
  doFill(img, pos, params, e.isShiftPressed(), m_level.getPointer(),
shun-iwasawa 14c787
         getCurrentFid());
shun-iwasawa 14c787
  invalidate();
shun-iwasawa 14c787
}
shun-iwasawa 14c787
shun-iwasawa 14c787
bool FullColorFillTool::onPropertyChanged(std::string propertyName) {
shun-iwasawa 14c787
  // Fill Depth
shun-iwasawa 14c787
  if (propertyName == m_fillDepth.getName()) {
shun-iwasawa 14c787
    FullColorMinFillDepth = (int)m_fillDepth.getValue().first;
shun-iwasawa 14c787
    FullColorMaxFillDepth = (int)m_fillDepth.getValue().second;
shun-iwasawa 14c787
  }
shun-iwasawa 14c787
  return true;
shun-iwasawa 14c787
}
shun-iwasawa 14c787
shun-iwasawa 14c787
void FullColorFillTool::onActivate() {
shun-iwasawa 14c787
  static bool firstTime = true;
shun-iwasawa 14c787
  if (firstTime) {
shun-iwasawa 14c787
    m_fillDepth.setValue(TDoublePairProperty::Value(FullColorMinFillDepth,
shun-iwasawa 14c787
                                                    FullColorMaxFillDepth));
shun-iwasawa 14c787
    firstTime = false;
shun-iwasawa 14c787
  }
shun-iwasawa 14c787
}
shun-iwasawa 14c787
shun-iwasawa 14c787
int FullColorFillTool::getCursorId() const {
shun-iwasawa 14c787
  int ret = ToolCursor::FillCursor;
shun-iwasawa 14c787
  if (ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg)
shun-iwasawa 14c787
    ret = ret | ToolCursor::Ex_Negate;
shun-iwasawa 14c787
  return ret;
shun-iwasawa 14c787
}
shun-iwasawa 14c787
shun-iwasawa 14c787
FullColorFillTool FullColorRasterFillTool;