Auto fill/close - Raster levels
This commit is contained in:
parent
d7e641b113
commit
a8d743be18
6 changed files with 241 additions and 28 deletions
|
@ -502,10 +502,21 @@ protected slots:
|
||||||
class FullColorFillToolOptionsBox final : public ToolOptionsBox {
|
class FullColorFillToolOptionsBox final : public ToolOptionsBox {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
ToolOptionCombo *m_rasterGapSettings;
|
||||||
|
ToolOptionSlider *m_rasterGapSlider;
|
||||||
|
StyleIndexFieldAndChip *m_styleIndex;
|
||||||
|
|
||||||
|
QLabel *m_gapSliderLabel, *m_styleIndexLabel, *m_rasterGapLabel;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FullColorFillToolOptionsBox(QWidget *parent, TTool *tool,
|
FullColorFillToolOptionsBox(QWidget *parent, TTool *tool,
|
||||||
TPaletteHandle *pltHandle,
|
TPaletteHandle *pltHandle,
|
||||||
ToolHandle *toolHandle);
|
ToolHandle *toolHandle);
|
||||||
|
|
||||||
|
void checkGapSettingsVisibility();
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
void onGapSettingChanged(int);
|
||||||
};
|
};
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
|
@ -99,7 +99,9 @@ void DVAPI fillautoInks(TRasterCM32P &r, TRect &rect,
|
||||||
|
|
||||||
void DVAPI fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
void DVAPI fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
||||||
TTileSaverFullColor *saver = 0, TXsheet *xsheet = 0,
|
TTileSaverFullColor *saver = 0, TXsheet *xsheet = 0,
|
||||||
int frameIndex = -1);
|
int frameIndex = -1, bool fillGaps = false,
|
||||||
|
bool closeGaps = false, int closeStyleIndex = -1,
|
||||||
|
double autoCloseDistance = -1.0);
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//! The class AreaFiller allows to fill a raster area, delimited by rect or
|
//! The class AreaFiller allows to fill a raster area, delimited by rect or
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#include "toonz/preferences.h"
|
#include "toonz/preferences.h"
|
||||||
#include "toonz/txsheethandle.h"
|
#include "toonz/txsheethandle.h"
|
||||||
#include "toonz/tframehandle.h"
|
#include "toonz/tframehandle.h"
|
||||||
|
#include "toonz/tonionskinmaskhandle.h"
|
||||||
|
#include "toonz/tpalettehandle.h"
|
||||||
|
|
||||||
#include "tools/toolhandle.h"
|
#include "tools/toolhandle.h"
|
||||||
#include "tools/toolutils.h"
|
#include "tools/toolutils.h"
|
||||||
|
@ -25,6 +27,10 @@ TEnv::IntVar FullColorMinFillDepth("InknpaintFullColorMinFillDepth", 4);
|
||||||
TEnv::IntVar FullColorMaxFillDepth("InknpaintFullColorMaxFillDepth", 12);
|
TEnv::IntVar FullColorMaxFillDepth("InknpaintFullColorMaxFillDepth", 12);
|
||||||
TEnv::IntVar FullColorFillReferenced("InknpaintFullColorFillReferenced", 0);
|
TEnv::IntVar FullColorFillReferenced("InknpaintFullColorFillReferenced", 0);
|
||||||
|
|
||||||
|
TEnv::StringVar FullColorRasterGapSetting("InknpaintFullColorRasterGapSetting",
|
||||||
|
"Ignore Gaps");
|
||||||
|
extern TEnv::DoubleVar AutocloseDistance;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
@ -84,7 +90,8 @@ public:
|
||||||
|
|
||||||
void doFill(const TImageP &img, const TPointD &pos, FillParameters ¶ms,
|
void doFill(const TImageP &img, const TPointD &pos, FillParameters ¶ms,
|
||||||
bool isShiftFill, TXshSimpleLevel *sl, const TFrameId &fid,
|
bool isShiftFill, TXshSimpleLevel *sl, const TFrameId &fid,
|
||||||
TXsheet *xsheet, int frameIndex) {
|
TXsheet *xsheet, int frameIndex, bool fillGaps = false,
|
||||||
|
bool closeGaps = false, int closeStyleIndex = -1) {
|
||||||
TTool::Application *app = TTool::getApplication();
|
TTool::Application *app = TTool::getApplication();
|
||||||
if (!app || !sl) return;
|
if (!app || !sl) return;
|
||||||
|
|
||||||
|
@ -115,7 +122,8 @@ void doFill(const TImageP &img, const TPointD &pos, FillParameters ¶ms,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fullColorFill(ras, params, &tileSaver, xsheet, frameIndex);
|
fullColorFill(ras, params, &tileSaver, xsheet, frameIndex, fillGaps,
|
||||||
|
closeGaps, closeStyleIndex, AutocloseDistance);
|
||||||
|
|
||||||
if (tileSaver.getTileSet()->getTileCount() != 0) {
|
if (tileSaver.getTileSet()->getTileCount() != 0) {
|
||||||
static int count = 0;
|
static int count = 0;
|
||||||
|
@ -149,15 +157,35 @@ void doFill(const TImageP &img, const TPointD &pos, FillParameters ¶ms,
|
||||||
FullColorFillTool::FullColorFillTool()
|
FullColorFillTool::FullColorFillTool()
|
||||||
: TTool("T_Fill")
|
: TTool("T_Fill")
|
||||||
, m_fillDepth("Fill Depth", 0, 15, 4, 12)
|
, m_fillDepth("Fill Depth", 0, 15, 4, 12)
|
||||||
, m_referenced("Refer Visible", false) {
|
, m_referenced("Refer Visible", false)
|
||||||
|
, m_closeStyleIndex("Style Index:", L"current") // W_ToolOptions_InkIndex
|
||||||
|
, m_rasterGapDistance("Distance:", 1, 100, 10)
|
||||||
|
, m_closeRasterGaps("Gaps:") {
|
||||||
bind(TTool::RasterImage);
|
bind(TTool::RasterImage);
|
||||||
m_prop.bind(m_fillDepth);
|
m_prop.bind(m_fillDepth);
|
||||||
|
m_prop.bind(m_closeRasterGaps);
|
||||||
|
m_prop.bind(m_rasterGapDistance);
|
||||||
|
m_prop.bind(m_closeStyleIndex);
|
||||||
m_prop.bind(m_referenced);
|
m_prop.bind(m_referenced);
|
||||||
|
|
||||||
|
m_closeRasterGaps.setId("CloseGaps");
|
||||||
|
m_rasterGapDistance.setId("RasterGapDistance");
|
||||||
|
m_closeStyleIndex.setId("RasterGapInkIndex");
|
||||||
|
|
||||||
|
m_closeRasterGaps.addValue(IGNOREGAPS);
|
||||||
|
m_closeRasterGaps.addValue(FILLGAPS);
|
||||||
|
m_closeRasterGaps.addValue(CLOSEANDFILLGAPS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FullColorFillTool::updateTranslation() {
|
void FullColorFillTool::updateTranslation() {
|
||||||
m_fillDepth.setQStringName(tr("Fill Depth"));
|
m_fillDepth.setQStringName(tr("Fill Depth"));
|
||||||
m_referenced.setQStringName(tr("Refer Visible"));
|
m_referenced.setQStringName(tr("Refer Visible"));
|
||||||
|
m_rasterGapDistance.setQStringName(tr("Distance:"));
|
||||||
|
m_closeStyleIndex.setQStringName(tr("Style Index:"));
|
||||||
|
m_closeRasterGaps.setQStringName(tr("Gaps:"));
|
||||||
|
m_closeRasterGaps.setItemUIName(IGNOREGAPS, tr("Ignore Gaps"));
|
||||||
|
m_closeRasterGaps.setItemUIName(FILLGAPS, tr("Fill Gaps"));
|
||||||
|
m_closeRasterGaps.setItemUIName(CLOSEANDFILLGAPS, tr("Close and Fill"));
|
||||||
}
|
}
|
||||||
|
|
||||||
FillParameters FullColorFillTool::getFillParameters() const {
|
FillParameters FullColorFillTool::getFillParameters() const {
|
||||||
|
@ -180,6 +208,11 @@ void FullColorFillTool::leftButtonDown(const TPointD &pos,
|
||||||
m_level = xl ? xl->getSimpleLevel() : 0;
|
m_level = xl ? xl->getSimpleLevel() : 0;
|
||||||
FillParameters params = getFillParameters();
|
FillParameters params = getFillParameters();
|
||||||
|
|
||||||
|
int closeStyleIndex = m_closeStyleIndex.getStyleIndex();
|
||||||
|
if (closeStyleIndex == -1) {
|
||||||
|
closeStyleIndex = app->getCurrentPalette()->getStyleIndex();
|
||||||
|
}
|
||||||
|
|
||||||
int frameIndex = app->getCurrentFrame()->getFrameIndex();
|
int frameIndex = app->getCurrentFrame()->getFrameIndex();
|
||||||
|
|
||||||
TXsheetHandle *xsh = app->getCurrentXsheet();
|
TXsheetHandle *xsh = app->getCurrentXsheet();
|
||||||
|
@ -188,8 +221,10 @@ void FullColorFillTool::leftButtonDown(const TPointD &pos,
|
||||||
? xsh->getXsheet()
|
? xsh->getXsheet()
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
applyFill(getImage(true), pos, params, e.isShiftPressed(), m_level.getPointer(),
|
applyFill(getImage(true), pos, params, e.isShiftPressed(),
|
||||||
getCurrentFid(), xsheet, frameIndex);
|
m_level.getPointer(), getCurrentFid(), xsheet, frameIndex,
|
||||||
|
m_closeRasterGaps.getIndex() > 0, m_closeRasterGaps.getIndex() > 1,
|
||||||
|
closeStyleIndex);
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,8 +259,15 @@ void FullColorFillTool::leftButtonDrag(const TPointD &pos,
|
||||||
? xsh->getXsheet()
|
? xsh->getXsheet()
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
|
int closeStyleIndex = m_closeStyleIndex.getStyleIndex();
|
||||||
|
if (closeStyleIndex == -1) {
|
||||||
|
closeStyleIndex = app->getCurrentPalette()->getStyleIndex();
|
||||||
|
}
|
||||||
|
|
||||||
applyFill(img, pos, params, e.isShiftPressed(), m_level.getPointer(),
|
applyFill(img, pos, params, e.isShiftPressed(), m_level.getPointer(),
|
||||||
getCurrentFid(), xsheet, frameIndex);
|
getCurrentFid(), xsheet, frameIndex,
|
||||||
|
m_closeRasterGaps.getIndex() > 0, m_closeRasterGaps.getIndex() > 1,
|
||||||
|
closeStyleIndex);
|
||||||
|
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
@ -235,7 +277,20 @@ bool FullColorFillTool::onPropertyChanged(std::string propertyName) {
|
||||||
if (propertyName == m_fillDepth.getName()) {
|
if (propertyName == m_fillDepth.getName()) {
|
||||||
FullColorMinFillDepth = (int)m_fillDepth.getValue().first;
|
FullColorMinFillDepth = (int)m_fillDepth.getValue().first;
|
||||||
FullColorMaxFillDepth = (int)m_fillDepth.getValue().second;
|
FullColorMaxFillDepth = (int)m_fillDepth.getValue().second;
|
||||||
|
} else if (propertyName == m_rasterGapDistance.getName()) {
|
||||||
|
AutocloseDistance = m_rasterGapDistance.getValue();
|
||||||
|
TTool::Application *app = TTool::getApplication();
|
||||||
|
// This is a hack to get the viewer to update with the distance.
|
||||||
|
app->getCurrentOnionSkin()->notifyOnionSkinMaskChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (propertyName == m_closeStyleIndex.getName()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (propertyName == m_closeRasterGaps.getName()) {
|
||||||
|
FullColorRasterGapSetting = ::to_string(m_closeRasterGaps.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,6 +301,10 @@ void FullColorFillTool::onActivate() {
|
||||||
FullColorMaxFillDepth));
|
FullColorMaxFillDepth));
|
||||||
firstTime = false;
|
firstTime = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_closeRasterGaps.setValue(
|
||||||
|
::to_wstring(FullColorRasterGapSetting.getValue()));
|
||||||
|
m_rasterGapDistance.setValue(AutocloseDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
int FullColorFillTool::getCursorId() const {
|
int FullColorFillTool::getCursorId() const {
|
||||||
|
@ -258,7 +317,8 @@ int FullColorFillTool::getCursorId() const {
|
||||||
void FullColorFillTool::applyFill(const TImageP &img, const TPointD &pos,
|
void FullColorFillTool::applyFill(const TImageP &img, const TPointD &pos,
|
||||||
FillParameters ¶ms, bool isShiftFill,
|
FillParameters ¶ms, bool isShiftFill,
|
||||||
TXshSimpleLevel *sl, const TFrameId &fid,
|
TXshSimpleLevel *sl, const TFrameId &fid,
|
||||||
TXsheet *xsheet, int frameIndex) {
|
TXsheet *xsheet, int frameIndex, bool fillGap,
|
||||||
|
bool closeGap, int closeStyleIndex) {
|
||||||
TRasterImageP ri = TRasterImageP(img);
|
TRasterImageP ri = TRasterImageP(img);
|
||||||
|
|
||||||
SymmetryTool *symmetryTool = dynamic_cast<SymmetryTool *>(
|
SymmetryTool *symmetryTool = dynamic_cast<SymmetryTool *>(
|
||||||
|
@ -267,21 +327,21 @@ void FullColorFillTool::applyFill(const TImageP &img, const TPointD &pos,
|
||||||
TUndoManager::manager()->beginBlock();
|
TUndoManager::manager()->beginBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
doFill(img, pos, params, isShiftFill, m_level.getPointer(), getCurrentFid(),
|
doFill(img, pos, params, isShiftFill, sl, fid, xsheet, frameIndex, fillGap,
|
||||||
xsheet, frameIndex);
|
closeGap, closeStyleIndex);
|
||||||
|
|
||||||
if (ri && symmetryTool && symmetryTool->isGuideEnabled()) {
|
if (ri && symmetryTool && symmetryTool->isGuideEnabled()) {
|
||||||
TPointD dpiScale = getViewer()->getDpiScale();
|
TPointD dpiScale = getViewer()->getDpiScale();
|
||||||
TRasterP ras = ri->getRaster();
|
TRasterP ras = ri->getRaster();
|
||||||
TPointD rasCenter = ras ? ras->getCenterD() : TPointD(0, 0);
|
TPointD rasCenter = ras ? ras->getCenterD() : TPointD(0, 0);
|
||||||
TPointD fillPt = pos + rasCenter;
|
TPointD fillPt = pos + rasCenter;
|
||||||
std::vector<TPointD> symmPts =
|
std::vector<TPointD> symmPts =
|
||||||
symmetryTool->getSymmetryPoints(fillPt, rasCenter, dpiScale);
|
symmetryTool->getSymmetryPoints(fillPt, rasCenter, dpiScale);
|
||||||
|
|
||||||
for (int i = 0; i < symmPts.size(); i++) {
|
for (int i = 0; i < symmPts.size(); i++) {
|
||||||
if (symmPts[i] == fillPt) continue;
|
if (symmPts[i] == fillPt) continue;
|
||||||
doFill(img, symmPts[i] - rasCenter, params, isShiftFill,
|
doFill(img, symmPts[i] - rasCenter, params, isShiftFill, sl, fid, xsheet,
|
||||||
m_level.getPointer(), getCurrentFid(), xsheet, frameIndex);
|
frameIndex, fillGap, closeGap, closeStyleIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
TUndoManager::manager()->endBlock();
|
TUndoManager::manager()->endBlock();
|
||||||
|
|
|
@ -14,6 +14,10 @@
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
#define IGNOREGAPS L"Ignore Gaps"
|
||||||
|
#define FILLGAPS L"Fill Gaps"
|
||||||
|
#define CLOSEANDFILLGAPS L"Close and Fill"
|
||||||
|
|
||||||
class FullColorFillTool final : public QObject, public TTool {
|
class FullColorFillTool final : public QObject, public TTool {
|
||||||
Q_DECLARE_TR_FUNCTIONS(FullColorFillTool)
|
Q_DECLARE_TR_FUNCTIONS(FullColorFillTool)
|
||||||
|
|
||||||
|
@ -22,6 +26,9 @@ class FullColorFillTool final : public QObject, public TTool {
|
||||||
TPropertyGroup m_prop;
|
TPropertyGroup m_prop;
|
||||||
TPointD m_clickPoint;
|
TPointD m_clickPoint;
|
||||||
TBoolProperty m_referenced;
|
TBoolProperty m_referenced;
|
||||||
|
TDoubleProperty m_rasterGapDistance;
|
||||||
|
TEnumProperty m_closeRasterGaps;
|
||||||
|
TStyleIndexProperty m_closeStyleIndex;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FullColorFillTool();
|
FullColorFillTool();
|
||||||
|
@ -45,7 +52,8 @@ public:
|
||||||
private:
|
private:
|
||||||
void applyFill(const TImageP &img, const TPointD &pos, FillParameters ¶ms,
|
void applyFill(const TImageP &img, const TPointD &pos, FillParameters ¶ms,
|
||||||
bool isShiftFill, TXshSimpleLevel *sl, const TFrameId &fid,
|
bool isShiftFill, TXshSimpleLevel *sl, const TFrameId &fid,
|
||||||
TXsheet *xsheet, int frameInde);
|
TXsheet *xsheet, int frameIndex, bool fillGap, bool closeGap,
|
||||||
|
int closeStyleIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FULLCOLORFILLTOOL_H
|
#endif // FULLCOLORFILLTOOL_H
|
|
@ -1749,9 +1749,67 @@ FullColorFillToolOptionsBox::FullColorFillToolOptionsBox(
|
||||||
ToolOptionControlBuilder builder(this, tool, pltHandle, toolHandle);
|
ToolOptionControlBuilder builder(this, tool, pltHandle, toolHandle);
|
||||||
if (tool && tool->getProperties(0)) tool->getProperties(0)->accept(builder);
|
if (tool && tool->getProperties(0)) tool->getProperties(0)->accept(builder);
|
||||||
|
|
||||||
|
m_rasterGapSettings =
|
||||||
|
dynamic_cast<ToolOptionCombo *>(m_controls.value("Gaps:"));
|
||||||
|
m_rasterGapSlider =
|
||||||
|
dynamic_cast<ToolOptionSlider *>(m_controls.value("Distance:"));
|
||||||
|
m_styleIndex =
|
||||||
|
dynamic_cast<StyleIndexFieldAndChip *>(m_controls.value("Style Index:"));
|
||||||
|
m_rasterGapLabel = m_labels.value(m_rasterGapSettings->propertyName());
|
||||||
|
m_styleIndexLabel = m_labels.value(m_styleIndex->propertyName());
|
||||||
|
m_gapSliderLabel = m_labels.value(m_rasterGapSlider->propertyName());
|
||||||
|
|
||||||
|
bool ret = connect(m_rasterGapSettings, SIGNAL(currentIndexChanged(int)),
|
||||||
|
this, SLOT(onGapSettingChanged(int)));
|
||||||
|
|
||||||
|
checkGapSettingsVisibility();
|
||||||
|
|
||||||
m_layout->addStretch(0);
|
m_layout->addStretch(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void FullColorFillToolOptionsBox::checkGapSettingsVisibility() {
|
||||||
|
if (m_rasterGapSettings->getProperty()->getValue() == L"Ignore Gaps") {
|
||||||
|
m_styleIndex->hide();
|
||||||
|
m_styleIndexLabel->hide();
|
||||||
|
m_rasterGapSlider->hide();
|
||||||
|
m_gapSliderLabel->hide();
|
||||||
|
} else if (m_rasterGapSettings->getProperty()->getValue() == L"Fill Gaps") {
|
||||||
|
m_styleIndex->hide();
|
||||||
|
m_styleIndexLabel->hide();
|
||||||
|
m_rasterGapSlider->show();
|
||||||
|
m_gapSliderLabel->show();
|
||||||
|
} else if (m_rasterGapSettings->getProperty()->getValue() ==
|
||||||
|
L"Close and Fill") {
|
||||||
|
m_styleIndex->show();
|
||||||
|
m_styleIndexLabel->show();
|
||||||
|
m_rasterGapSlider->show();
|
||||||
|
m_gapSliderLabel->show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void FullColorFillToolOptionsBox::onGapSettingChanged(int index) {
|
||||||
|
if (index == 0) {
|
||||||
|
m_styleIndex->hide();
|
||||||
|
m_styleIndexLabel->hide();
|
||||||
|
m_rasterGapSlider->hide();
|
||||||
|
m_gapSliderLabel->hide();
|
||||||
|
} else if (index == 1) {
|
||||||
|
m_styleIndex->hide();
|
||||||
|
m_styleIndexLabel->hide();
|
||||||
|
m_rasterGapSlider->show();
|
||||||
|
m_gapSliderLabel->hide();
|
||||||
|
} else if (index == 2) {
|
||||||
|
m_styleIndex->show();
|
||||||
|
m_styleIndexLabel->show();
|
||||||
|
m_rasterGapSlider->show();
|
||||||
|
m_gapSliderLabel->show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
// FillToolOptionsBox
|
// FillToolOptionsBox
|
||||||
|
|
|
@ -920,10 +920,12 @@ void inkFill(const TRasterCM32P &r, const TPoint &pin, int ink, int searchRay,
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
||||||
TTileSaverFullColor *saver, TXsheet *xsheet,
|
TTileSaverFullColor *saver, TXsheet *xsheet, int frameIndex,
|
||||||
int frameIndex) {
|
bool fillGaps, bool closeGaps, int closeStyleIndex,
|
||||||
|
double autoCloseDistance) {
|
||||||
int oldy, xa, xb, xc, xd, dy, oldxd, oldxc;
|
int oldy, xa, xb, xc, xd, dy, oldxd, oldxc;
|
||||||
TPixel32 *pix, *limit, *pix0, *oldpix, *refpix, *oldrefpix;
|
TPixel32 *pix, *limit, *pix0, *oldpix, *refpix, *oldrefpix;
|
||||||
|
TPixelCM32 *refCMpix;
|
||||||
int x = params.m_p.x, y = params.m_p.y;
|
int x = params.m_p.x, y = params.m_p.y;
|
||||||
|
|
||||||
TRect bbbox = ras->getBounds();
|
TRect bbbox = ras->getBounds();
|
||||||
|
@ -938,6 +940,10 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
||||||
|
|
||||||
TRaster32P refRas(bbbox.getSize());
|
TRaster32P refRas(bbbox.getSize());
|
||||||
|
|
||||||
|
TPixel32 gapColor = plt->getStyle(closeStyleIndex)->getMainColor();
|
||||||
|
int styleIndex = 4094;
|
||||||
|
int fakeStyleIndex = 4095;
|
||||||
|
|
||||||
if (xsheet) {
|
if (xsheet) {
|
||||||
ToonzScene *scene = xsheet->getScene();
|
ToonzScene *scene = xsheet->getScene();
|
||||||
TCamera *camera = scene->getCurrentCamera();
|
TCamera *camera = scene->getCurrentCamera();
|
||||||
|
@ -952,6 +958,34 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
||||||
refRas->copy(tmpRaster, offset);
|
refRas->copy(tmpRaster, offset);
|
||||||
|
|
||||||
clickedPosColor = *(refRas->pixels(y) + x);
|
clickedPosColor = *(refRas->pixels(y) + x);
|
||||||
|
} else if (fillGaps) {
|
||||||
|
refRas->lock();
|
||||||
|
TPoint offset((refRas->getLx() - ras->getLx()) / 2,
|
||||||
|
(refRas->getLy() - ras->getLy()) / 2);
|
||||||
|
refRas->fill(color);
|
||||||
|
refRas->copy(ras, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
TRasterCM32P refCMRaster;
|
||||||
|
|
||||||
|
if (fillGaps) {
|
||||||
|
TRasterCM32P cr = convertRaster2CM(refRas);
|
||||||
|
refCMRaster = cr->clone();
|
||||||
|
fillGaps = TAutocloser(refCMRaster, autoCloseDistance, AutocloseAngle,
|
||||||
|
styleIndex, AutocloseOpacity)
|
||||||
|
.exec();
|
||||||
|
if (fillGaps) {
|
||||||
|
// Transfer the gap segments to the refRaster
|
||||||
|
refCMpix = refCMRaster->pixels(0);
|
||||||
|
TPixel32 *refPix = refRas->pixels(0);
|
||||||
|
for (int refCMY = 0; refCMY < refCMRaster->getLy(); refCMY++) {
|
||||||
|
for (int refCMX = 0; refCMX < refCMRaster->getLx();
|
||||||
|
refCMX++, refCMpix++, refPix++) {
|
||||||
|
if (refCMpix->getInk() != styleIndex) continue;
|
||||||
|
*refPix = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int fillDepth =
|
int fillDepth =
|
||||||
|
@ -966,7 +1000,7 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
||||||
std::stack<FillSeed> seeds;
|
std::stack<FillSeed> seeds;
|
||||||
std::map<int, std::vector<std::pair<int, int>>> segments;
|
std::map<int, std::vector<std::pair<int, int>>> segments;
|
||||||
|
|
||||||
if (!xsheet)
|
if (!xsheet && !fillGaps)
|
||||||
fullColorFindSegment(ras, params.m_p, xa, xb, color, clickedPosColor,
|
fullColorFindSegment(ras, params.m_p, xa, xb, color, clickedPosColor,
|
||||||
fillDepth);
|
fillDepth);
|
||||||
else
|
else
|
||||||
|
@ -977,6 +1011,20 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
||||||
seeds.push(FillSeed(xa, xb, y, 1));
|
seeds.push(FillSeed(xa, xb, y, 1));
|
||||||
seeds.push(FillSeed(xa, xb, y, -1));
|
seeds.push(FillSeed(xa, xb, y, -1));
|
||||||
|
|
||||||
|
if (fillGaps && closeGaps) {
|
||||||
|
// Set the ink on gaps that were used to 4095
|
||||||
|
TPixelCM32 *tempPix = refCMRaster->pixels(0);
|
||||||
|
tempPix += (y * refCMRaster->getLx()) + xa - 1;
|
||||||
|
int i = xa;
|
||||||
|
while (i <= xb) {
|
||||||
|
if (tempPix->getInk() == styleIndex) {
|
||||||
|
tempPix->setInk(fakeStyleIndex);
|
||||||
|
}
|
||||||
|
tempPix++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (!seeds.empty()) {
|
while (!seeds.empty()) {
|
||||||
FillSeed fs = seeds.top();
|
FillSeed fs = seeds.top();
|
||||||
seeds.pop();
|
seeds.pop();
|
||||||
|
@ -995,7 +1043,7 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
||||||
// left end of the fill seed pixels
|
// left end of the fill seed pixels
|
||||||
oldpix = ras->pixels(oldy) + xa;
|
oldpix = ras->pixels(oldy) + xa;
|
||||||
|
|
||||||
if (xsheet) {
|
if (xsheet || fillGaps) {
|
||||||
refpix = refRas->pixels(y) + xa;
|
refpix = refRas->pixels(y) + xa;
|
||||||
oldrefpix = refRas->pixels(oldy) + xa;
|
oldrefpix = refRas->pixels(oldy) + xa;
|
||||||
}
|
}
|
||||||
|
@ -1011,7 +1059,7 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
||||||
if (segments.find(y) != segments.end())
|
if (segments.find(y) != segments.end())
|
||||||
test = isPixelInSegment(segments[y], x);
|
test = isPixelInSegment(segments[y], x);
|
||||||
bool canPaint = false;
|
bool canPaint = false;
|
||||||
if (!xsheet)
|
if (!xsheet && !fillGaps)
|
||||||
canPaint = *pix != color && !test &&
|
canPaint = *pix != color && !test &&
|
||||||
floodCheck(clickedPosColor, pix, oldpix, fillDepth);
|
floodCheck(clickedPosColor, pix, oldpix, fillDepth);
|
||||||
else
|
else
|
||||||
|
@ -1019,7 +1067,7 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
||||||
floodCheck(clickedPosColor, refpix, oldrefpix, fillDepth);
|
floodCheck(clickedPosColor, refpix, oldrefpix, fillDepth);
|
||||||
if (canPaint) {
|
if (canPaint) {
|
||||||
// compute horizontal range to be filled
|
// compute horizontal range to be filled
|
||||||
if (!xsheet)
|
if (!xsheet && !fillGaps)
|
||||||
fullColorFindSegment(ras, TPoint(x, y), xc, xd, color,
|
fullColorFindSegment(ras, TPoint(x, y), xc, xd, color,
|
||||||
clickedPosColor, fillDepth);
|
clickedPosColor, fillDepth);
|
||||||
else
|
else
|
||||||
|
@ -1027,6 +1075,20 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
||||||
clickedPosColor, fillDepth);
|
clickedPosColor, fillDepth);
|
||||||
// insert segment to be filled
|
// insert segment to be filled
|
||||||
insertSegment(segments[y], std::pair<int, int>(xc, xd));
|
insertSegment(segments[y], std::pair<int, int>(xc, xd));
|
||||||
|
if (fillGaps && closeGaps) {
|
||||||
|
// Set the ink on gaps that were used to 4095
|
||||||
|
TPixelCM32 *tempPix = refCMRaster->pixels(0);
|
||||||
|
tempPix += (y * refCMRaster->getLx()) + xa - 1;
|
||||||
|
int i = xa;
|
||||||
|
while (i <= xb) {
|
||||||
|
if (tempPix->getInk() == styleIndex) {
|
||||||
|
tempPix->setInk(fakeStyleIndex);
|
||||||
|
}
|
||||||
|
tempPix++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// create new fillSeed to invert direction, if needed
|
// create new fillSeed to invert direction, if needed
|
||||||
if (xc < xa) seeds.push(FillSeed(xc, xa - 1, y, -dy));
|
if (xc < xa) seeds.push(FillSeed(xc, xa - 1, y, -dy));
|
||||||
if (xd > xb) seeds.push(FillSeed(xb + 1, xd, y, -dy));
|
if (xd > xb) seeds.push(FillSeed(xb + 1, xd, y, -dy));
|
||||||
|
@ -1040,7 +1102,7 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
||||||
// jump to the next pixel to the right end of the range
|
// jump to the next pixel to the right end of the range
|
||||||
pix += xd - x + 1;
|
pix += xd - x + 1;
|
||||||
oldpix += xd - x + 1;
|
oldpix += xd - x + 1;
|
||||||
if (xsheet) {
|
if (xsheet || fillGaps) {
|
||||||
refpix += xd - x + 1;
|
refpix += xd - x + 1;
|
||||||
oldrefpix += xd - x + 1;
|
oldrefpix += xd - x + 1;
|
||||||
}
|
}
|
||||||
|
@ -1048,7 +1110,7 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
||||||
} else {
|
} else {
|
||||||
pix++;
|
pix++;
|
||||||
oldpix++, x++;
|
oldpix++, x++;
|
||||||
if (xsheet) {
|
if (xsheet || fillGaps) {
|
||||||
refpix++;
|
refpix++;
|
||||||
oldrefpix++;
|
oldrefpix++;
|
||||||
}
|
}
|
||||||
|
@ -1058,15 +1120,14 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
||||||
if (oldxd > 0) seeds.push(FillSeed(oldxc, oldxd, y, dy));
|
if (oldxd > 0) seeds.push(FillSeed(oldxc, oldxd, y, dy));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xsheet) refRas->unlock();
|
if (xsheet || fillGaps) refRas->unlock();
|
||||||
|
|
||||||
// pixels are actually filled here
|
// pixels are actually filled here
|
||||||
TPixel32 premultiColor = premultiply(color);
|
TPixel32 premultiColor = premultiply(color);
|
||||||
|
|
||||||
std::map<int, std::vector<std::pair<int, int>>>::iterator it;
|
std::map<int, std::vector<std::pair<int, int>>>::iterator it;
|
||||||
for (it = segments.begin(); it != segments.end(); it++) {
|
for (it = segments.begin(); it != segments.end(); it++) {
|
||||||
TPixel32 *line = ras->pixels(it->first);
|
TPixel32 *line = ras->pixels(it->first);
|
||||||
TPixel32 *refLine = 0;
|
|
||||||
std::vector<std::pair<int, int>> segmentVector = it->second;
|
std::vector<std::pair<int, int>> segmentVector = it->second;
|
||||||
for (int i = 0; i < (int)segmentVector.size(); i++) {
|
for (int i = 0; i < (int)segmentVector.size(); i++) {
|
||||||
std::pair<int, int> segment = segmentVector[i];
|
std::pair<int, int> segment = segmentVector[i];
|
||||||
|
@ -1088,4 +1149,17 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fillGaps && closeGaps) {
|
||||||
|
TPixelCM32 *tempPix = refCMRaster->pixels();
|
||||||
|
TPixel32 *keepPix = ras->pixels();
|
||||||
|
for (int tempY = 0; tempY < refCMRaster->getLy(); tempY++) {
|
||||||
|
for (int tempX = 0; tempX < refCMRaster->getLx();
|
||||||
|
tempX++, tempPix++, keepPix++) {
|
||||||
|
if (tempPix->getInk() == fakeStyleIndex) {
|
||||||
|
*keepPix = gapColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue