2016-03-19 06:57:51 +13:00
# include "tools/tool.h"
# include "tools/toolutils.h"
# include "toonz/txshlevelhandle.h"
# include "toonz/tframehandle.h"
# include "toonz/tcolumnhandle.h"
# include "toonz/tpalettehandle.h"
# include "toonz/preferences.h"
# include "toonz/txsheethandle.h"
# include "toonz/tobjecthandle.h"
# include "tools/toolhandle.h"
# include "tools/toolutils.h"
# include "toonz/tonionskinmaskhandle.h"
# include "timagecache.h"
# include "tundo.h"
# include "tpalette.h"
# include "tcolorstyles.h"
# include "tvectorimage.h"
# include "tools/cursors.h"
# include "ttoonzimage.h"
# include "tproperty.h"
# include "tenv.h"
# include "tools/stylepicker.h"
# include "toonz/fill.h"
# include "toonz/stage2.h"
# include "tstroke.h"
# include "drawutil.h"
# include "tsystem.h"
# include "tinbetween.h"
# include "tregion.h"
# include "tgl.h"
# include "trop.h"
# include "toonz/txshsimplelevel.h"
# include "toonz/onionskinmask.h"
# include "toonz/ttileset.h"
# include "toonz/ttilesaver.h"
# include "toonz/toonzimageutils.h"
# include "toonz/levelproperties.h"
# include "toonz/strokegenerator.h"
# include "toonz/txshcell.h"
# include "toonzqt/imageutils.h"
# include "autofill.h"
# include "historytypes.h"
# include <stack>
// For Qt translation support
# include <QCoreApplication>
using namespace ToolUtils ;
# define LINES L"Lines"
# define AREAS L"Areas"
# define ALL L"Lines & Areas"
# define NORMALFILL L"Normal"
# define RECTFILL L"Rectangular"
# define FREEHANDFILL L"Freehand"
# define POLYLINEFILL L"Polyline"
TEnv : : IntVar MinFillDepth ( " InknpaintMinFillDepth " , 0 ) ;
TEnv : : IntVar MaxFillDepth ( " InknpaintMaxFillDepth " , 10 ) ;
TEnv : : StringVar FillType ( " InknpaintFillType " , " Normal " ) ;
TEnv : : StringVar FillColorType ( " InknpaintFillColorType " , " Areas " ) ;
TEnv : : IntVar FillSelective ( " InknpaintFillSelective " , 0 ) ;
TEnv : : IntVar FillOnion ( " InknpaintFillOnion " , 0 ) ;
TEnv : : IntVar FillSegment ( " InknpaintFillSegment " , 0 ) ;
TEnv : : IntVar FillRange ( " InknpaintFillRange " , 0 ) ;
//-----------------------------------------------------------------------------
namespace
{
2016-04-19 19:32:17 +12:00
inline int vectorFill ( const TVectorImageP & img , const std : : wstring & type , const TPointD & point , int style , bool emptyOnly = false )
2016-03-19 06:57:51 +13:00
{
if ( type = = ALL | | type = = LINES ) {
int oldStyleId = img - > fillStrokes ( point , style ) ;
if ( oldStyleId ! = - 1 )
return oldStyleId ;
}
if ( type = = ALL | | type = = AREAS )
return img - > fill ( point , style , emptyOnly ) ;
return - 1 ;
}
//=============================================================================
// VectorFillUndo
//-----------------------------------------------------------------------------
class VectorFillUndo : public TToolUndo
{
int m_oldColorStyle ;
int m_newColorStyle ;
TPointD m_point ;
2016-04-19 19:32:17 +12:00
std : : wstring m_type ;
2016-03-19 06:57:51 +13:00
int m_row ;
int m_column ;
public :
VectorFillUndo (
int newColorStyle ,
int oldColorStyle ,
2016-04-19 19:32:17 +12:00
std : : wstring fillType ,
2016-03-19 06:57:51 +13:00
TPointD clickPoint ,
TXshSimpleLevel * sl ,
const TFrameId & fid )
: TToolUndo ( sl , fid ) , m_newColorStyle ( newColorStyle ) , m_oldColorStyle ( oldColorStyle ) , m_point ( clickPoint ) , m_type ( fillType )
{
TTool : : Application * app = TTool : : getApplication ( ) ;
if ( app ) {
m_row = app - > getCurrentFrame ( ) - > getFrame ( ) ;
m_column = app - > getCurrentColumn ( ) - > getColumnIndex ( ) ;
}
}
void undo ( ) const
{
TTool : : Application * app = TTool : : getApplication ( ) ;
if ( ! app )
return ;
app - > getCurrentLevel ( ) - > setLevel ( m_level . getPointer ( ) ) ;
TVectorImageP img = m_level - > getFrame ( m_frameId , true ) ;
if ( app - > getCurrentFrame ( ) - > isEditingScene ( ) ) {
app - > getCurrentFrame ( ) - > setFrame ( m_row ) ;
app - > getCurrentColumn ( ) - > setColumnIndex ( m_column ) ;
} else
app - > getCurrentFrame ( ) - > setFid ( m_frameId ) ;
assert ( img ) ;
if ( ! img )
return ;
QMutexLocker lock ( img - > getMutex ( ) ) ;
vectorFill ( img , m_type , m_point , m_oldColorStyle ) ;
app - > getCurrentXsheet ( ) - > notifyXsheetChanged ( ) ;
notifyImageChanged ( ) ;
}
void redo ( ) const
{
TTool : : Application * app = TTool : : getApplication ( ) ;
if ( ! app )
return ;
app - > getCurrentLevel ( ) - > setLevel ( m_level . getPointer ( ) ) ;
TVectorImageP img = m_level - > getFrame ( m_frameId , true ) ;
if ( app - > getCurrentFrame ( ) - > isEditingScene ( ) ) {
app - > getCurrentFrame ( ) - > setFrame ( m_row ) ;
app - > getCurrentColumn ( ) - > setColumnIndex ( m_column ) ;
} else
app - > getCurrentFrame ( ) - > setFid ( m_frameId ) ;
assert ( img ) ;
if ( ! img )
return ;
QMutexLocker lock ( img - > getMutex ( ) ) ;
vectorFill ( img , m_type , m_point , m_newColorStyle ) ;
app - > getCurrentXsheet ( ) - > notifyXsheetChanged ( ) ;
notifyImageChanged ( ) ;
}
void onAdd ( )
{
}
int getSize ( ) const
{
return sizeof ( * this ) ;
}
virtual QString getToolName ( )
{
return QString ( " Fill Tool : %1 " ) . arg ( QString : : fromStdWString ( m_type ) ) ;
}
int getHistoryType ( )
{
return HistoryType : : FillTool ;
}
} ;
//=============================================================================
// VectorRectFillUndo
//-----------------------------------------------------------------------------
class VectorRectFillUndo : public TToolUndo
{
2016-04-19 19:32:17 +12:00
std : : vector < TFilledRegionInf > * m_regionFillInformation ;
std : : vector < std : : pair < int , int > > * m_strokeFillInformation ;
2016-03-19 06:57:51 +13:00
TRectD m_selectionArea ;
int m_styleId ;
bool m_unpaintedOnly ;
TStroke * m_stroke ;
public :
~ VectorRectFillUndo ( )
{
if ( m_regionFillInformation )
delete m_regionFillInformation ;
if ( m_strokeFillInformation )
delete m_strokeFillInformation ;
if ( m_stroke )
delete m_stroke ;
}
VectorRectFillUndo (
2016-04-19 19:32:17 +12:00
std : : vector < TFilledRegionInf > * regionFillInformation ,
std : : vector < std : : pair < int , int > > * strokeFillInformation ,
2016-03-19 06:57:51 +13:00
TRectD selectionArea ,
TStroke * stroke ,
int styleId ,
bool unpaintedOnly ,
TXshSimpleLevel * sl ,
const TFrameId & fid )
: TToolUndo ( sl , fid ) , m_regionFillInformation ( regionFillInformation ) , m_strokeFillInformation ( strokeFillInformation ) , m_selectionArea ( selectionArea ) , m_styleId ( styleId ) , m_unpaintedOnly ( unpaintedOnly ) , m_stroke ( 0 )
{
if ( stroke )
m_stroke = new TStroke ( * stroke ) ;
}
void undo ( ) const
{
TTool : : Application * app = TTool : : getApplication ( ) ;
if ( ! app )
return ;
TVectorImageP img = m_level - > getFrame ( m_frameId , true ) ;
assert ( ! ! img ) ;
if ( ! img )
return ;
if ( m_regionFillInformation ) {
for ( UINT i = 0 ; i < m_regionFillInformation - > size ( ) ; i + + ) {
TRegion * reg = img - > getRegion ( ( * m_regionFillInformation ) [ i ] . m_regionId ) ;
if ( reg )
reg - > setStyle ( ( * m_regionFillInformation ) [ i ] . m_styleId ) ;
}
}
if ( m_strokeFillInformation ) {
for ( UINT i = 0 ; i < m_strokeFillInformation - > size ( ) ; i + + ) {
TStroke * s = img - > getStroke ( ( * m_strokeFillInformation ) [ i ] . first ) ;
s - > setStyle ( ( * m_strokeFillInformation ) [ i ] . second ) ;
}
}
app - > getCurrentXsheet ( ) - > notifyXsheetChanged ( ) ;
notifyImageChanged ( ) ;
}
void redo ( ) const
{
TTool : : Application * app = TTool : : getApplication ( ) ;
if ( ! app )
return ;
TVectorImageP img = m_level - > getFrame ( m_frameId , true ) ;
assert ( img ) ;
if ( ! img )
return ;
img - > selectFill ( m_selectionArea , m_stroke , m_styleId , m_unpaintedOnly , m_regionFillInformation ! = 0 , m_strokeFillInformation ! = 0 ) ;
app - > getCurrentXsheet ( ) - > notifyXsheetChanged ( ) ;
notifyImageChanged ( ) ;
}
void onAdd ( )
{
}
int getSize ( ) const
{
int size1 = m_regionFillInformation ? m_regionFillInformation - > capacity ( ) * sizeof ( m_regionFillInformation ) : 0 ;
int size2 = m_strokeFillInformation ? m_strokeFillInformation - > capacity ( ) * sizeof ( m_strokeFillInformation ) : 0 ;
return sizeof ( * this ) + size1 + size2 + 500 ;
}
virtual QString getToolName ( )
{
return QString ( " Fill Tool : " ) ;
}
int getHistoryType ( )
{
return HistoryType : : FillTool ;
}
} ;
//=============================================================================
// RasterFillUndo
//-----------------------------------------------------------------------------
class RasterFillUndo : public TRasterUndo
{
FillParameters m_params ;
bool m_saveboxOnly ;
public :
/*RasterFillUndo(TTileSetCM32 *tileSet, TPoint fillPoint,
int paintId , int fillDepth ,
2016-04-19 19:32:17 +12:00
std : : wstring fillType , bool isSegment ,
2016-03-19 06:57:51 +13:00
bool selective , bool isShiftFill ,
TXshSimpleLevel * sl , const TFrameId & fid ) */
RasterFillUndo ( TTileSetCM32 * tileSet , const FillParameters & params ,
TXshSimpleLevel * sl , const TFrameId & fid , bool saveboxOnly )
: TRasterUndo ( tileSet , sl , fid , false , false , 0 ) , m_params ( params ) , m_saveboxOnly ( saveboxOnly )
{
}
void redo ( ) const
{
TToonzImageP image = getImage ( ) ;
if ( ! image )
return ;
bool recomputeSavebox = false ;
TRasterCM32P r ;
if ( m_saveboxOnly ) {
TRectD temp = image - > getBBox ( ) ;
TRect ttemp = convert ( temp ) ;
r = image - > getRaster ( ) - > extract ( ttemp ) ;
} else
r = image - > getRaster ( ) ;
if ( m_params . m_fillType = = ALL | | m_params . m_fillType = = AREAS ) {
if ( m_params . m_shiftFill ) {
FillParameters aux ( m_params ) ;
aux . m_styleId = ( m_params . m_styleId = = 0 ) ? 1 : 0 ;
recomputeSavebox = fill ( r , aux ) ;
}
recomputeSavebox = fill ( r , m_params ) ;
}
if ( m_params . m_fillType = = ALL | | m_params . m_fillType = = LINES ) {
if ( m_params . m_segment )
inkSegment ( r , m_params . m_p , m_params . m_styleId , 2.51 , true ) ;
else
inkFill ( r , m_params . m_p , m_params . m_styleId , 2 ) ;
}
if ( recomputeSavebox )
ToolUtils : : updateSaveBox ( ) ;
TTool : : Application * app = TTool : : getApplication ( ) ;
if ( app ) {
app - > getCurrentXsheet ( ) - > notifyXsheetChanged ( ) ;
notifyImageChanged ( ) ;
}
}
int getSize ( ) const
{
return sizeof ( * this ) + TRasterUndo : : getSize ( ) ;
}
virtual QString getToolName ( )
{
return QString ( " Fill Tool : %1 " ) . arg ( QString : : fromStdWString ( m_params . m_fillType ) ) ;
}
int getHistoryType ( )
{
return HistoryType : : FillTool ;
}
} ;
//=============================================================================
// RasterRectFillUndo
//-----------------------------------------------------------------------------
class RasterRectFillUndo : public TRasterUndo
{
TRect m_fillArea ;
int m_paintId ;
2016-04-19 19:32:17 +12:00
std : : wstring m_colorType ;
2016-03-19 06:57:51 +13:00
TStroke * m_s ;
bool m_onlyUnfilled ;
TPalette * m_palette ;
public :
~ RasterRectFillUndo ( )
{
if ( m_s )
delete m_s ;
}
RasterRectFillUndo ( TTileSetCM32 * tileSet , TStroke * s ,
TRect fillArea , int paintId ,
TXshSimpleLevel * level ,
2016-04-19 19:32:17 +12:00
std : : wstring colorType , bool onlyUnfilled ,
2016-03-19 06:57:51 +13:00
const TFrameId & fid , TPalette * palette )
: TRasterUndo ( tileSet , level , fid , false , false , 0 ) , m_fillArea ( fillArea ) , m_paintId ( paintId ) , m_colorType ( colorType ) , m_onlyUnfilled ( onlyUnfilled ) , m_palette ( palette )
{
m_s = s ? new TStroke ( * s ) : 0 ;
}
void redo ( ) const
{
TToonzImageP image = getImage ( ) ;
if ( ! image )
return ;
TRasterCM32P ras = image - > getRaster ( ) ;
AreaFiller filler ( ras ) ;
if ( ! m_s )
filler . rectFill ( m_fillArea , m_paintId , m_onlyUnfilled , m_colorType ! = LINES , m_colorType ! = AREAS ) ;
else
filler . strokeFill ( m_s , m_paintId , m_onlyUnfilled , m_colorType ! = LINES , m_colorType ! = AREAS ) ;
if ( m_palette ) {
TRect rect = m_fillArea ;
TRect bounds = ras - > getBounds ( ) ;
if ( bounds . overlaps ( rect ) ) {
rect * = bounds ;
const TTileSetCM32 : : Tile * tile = m_tiles - > getTile ( m_tiles - > getTileCount ( ) - 1 ) ;
TRasterCM32P rbefore ;
tile - > getRaster ( rbefore ) ;
fillautoInks ( ras , rect , rbefore , m_palette ) ;
}
}
TTool : : Application * app = TTool : : getApplication ( ) ;
if ( app ) {
app - > getCurrentXsheet ( ) - > notifyXsheetChanged ( ) ;
notifyImageChanged ( ) ;
}
}
int getSize ( ) const
{
int size = m_s ? m_s - > getControlPointCount ( ) * sizeof ( TThickPoint ) + 100 : 0 ;
return sizeof ( * this ) + TRasterUndo : : getSize ( ) + size ;
}
virtual QString getToolName ( )
{
return QString ( " Fill Tool : %1 " ) . arg ( QString : : fromStdWString ( m_colorType ) ) ;
}
int getHistoryType ( )
{
return HistoryType : : FillTool ;
}
} ;
//=============================================================================
// RasterRectAutoFillUndo
//-----------------------------------------------------------------------------
class RasterRectAutoFillUndo : public TRasterUndo
{
TRect m_rectToFill ;
TFrameId m_fidToLearn ;
bool m_onlyUnfilled ;
public :
~ RasterRectAutoFillUndo ( )
{
}
RasterRectAutoFillUndo ( TTileSetCM32 * tileSet ,
const TRect & rectToFill ,
TXshSimpleLevel * level ,
bool onlyUnfilled ,
const TFrameId & currentFid , const TFrameId & fidToLearn )
: TRasterUndo ( tileSet , level , currentFid , false , false , 0 ) , m_rectToFill ( rectToFill ) , m_onlyUnfilled ( onlyUnfilled ) , m_fidToLearn ( fidToLearn )
{
}
void redo ( ) const
{
TToonzImageP image = getImage ( ) ;
TToonzImageP imageToLearn = m_level - > getFrame ( m_fidToLearn , false ) ;
if ( ! image | | ! imageToLearn )
return ;
rect_autofill_learn ( imageToLearn ,
m_rectToFill . x0 ,
m_rectToFill . y0 ,
m_rectToFill . x1 ,
m_rectToFill . y1 ) ;
TTileSetCM32 tileSet ( image - > getRaster ( ) - > getSize ( ) ) ;
bool recomputeBBox = rect_autofill_apply ( image ,
m_rectToFill . x0 ,
m_rectToFill . y0 ,
m_rectToFill . x1 ,
m_rectToFill . y1 ,
m_onlyUnfilled , & tileSet ) ;
if ( recomputeBBox )
ToolUtils : : updateSaveBox ( ) ;
TTool : : Application * app = TTool : : getApplication ( ) ;
if ( app ) {
app - > getCurrentXsheet ( ) - > notifyXsheetChanged ( ) ;
notifyImageChanged ( ) ;
}
}
int getSize ( ) const
{
return sizeof ( * this ) + TRasterUndo : : getSize ( ) ;
}
} ;
//=============================================================================
// RasterStrokeAutoFillUndo
//-----------------------------------------------------------------------------
class RasterStrokeAutoFillUndo : public TRasterUndo
{
TTileSetCM32 * m_tileSet ;
public :
~ RasterStrokeAutoFillUndo ( )
{
if ( m_tileSet )
delete m_tileSet ;
}
RasterStrokeAutoFillUndo ( TTileSetCM32 * tileSet ,
TXshSimpleLevel * level ,
const TFrameId & currentFid )
: TRasterUndo ( tileSet , level , currentFid , false , false , 0 ) , m_tileSet ( 0 )
{
}
void setTileSet ( TTileSetCM32 * tileSet ) { m_tileSet = tileSet ; }
void redo ( ) const
{
TToonzImageP image = getImage ( ) ;
if ( ! image )
return ;
ToonzImageUtils : : paste ( image , m_tileSet ) ;
ToolUtils : : updateSaveBox ( m_level , m_frameId ) ;
TTool : : Application * app = TTool : : getApplication ( ) ;
if ( app ) {
app - > getCurrentXsheet ( ) - > notifyXsheetChanged ( ) ;
notifyImageChanged ( ) ;
}
}
int getSize ( ) const
{
return sizeof ( * this ) + TRasterUndo : : getSize ( ) + m_tileSet - > getMemorySize ( ) ;
}
} ;
//=============================================================================
// RasterRectAutoFillUndo
//-----------------------------------------------------------------------------
class VectorAutoFillUndo : public TToolUndo
{
2016-04-19 19:32:17 +12:00
std : : vector < TFilledRegionInf > * m_regionFillInformation ;
2016-03-19 06:57:51 +13:00
TRectD m_selectionArea ;
TStroke * m_selectingStroke ;
bool m_unpaintedOnly ;
TFrameId m_onionFid ;
int m_row ;
int m_column ;
public :
~ VectorAutoFillUndo ( )
{
if ( m_regionFillInformation )
delete m_regionFillInformation ;
if ( m_selectingStroke )
delete m_selectingStroke ;
}
VectorAutoFillUndo (
2016-04-19 19:32:17 +12:00
std : : vector < TFilledRegionInf > * regionFillInformation ,
2016-03-19 06:57:51 +13:00
TRectD selectionArea ,
TStroke * selectingStroke ,
bool unpaintedOnly ,
TXshSimpleLevel * sl ,
const TFrameId & fid ,
const TFrameId & onionFid )
: TToolUndo ( sl , fid ) , m_regionFillInformation ( regionFillInformation ) , m_selectionArea ( selectionArea ) , m_unpaintedOnly ( unpaintedOnly ) , m_onionFid ( onionFid )
{
m_selectingStroke = selectingStroke ? new TStroke ( * selectingStroke ) : 0 ;
}
void undo ( ) const
{
TTool : : Application * app = TTool : : getApplication ( ) ;
if ( ! app )
return ;
TVectorImageP img = m_level - > getFrame ( m_frameId , true ) ;
;
assert ( ! ! img ) ;
if ( ! img )
return ;
if ( m_regionFillInformation ) {
for ( UINT i = 0 ; i < m_regionFillInformation - > size ( ) ; i + + ) {
TRegion * reg = img - > getRegion ( ( * m_regionFillInformation ) [ i ] . m_regionId ) ;
if ( reg )
reg - > setStyle ( ( * m_regionFillInformation ) [ i ] . m_styleId ) ;
}
}
app - > getCurrentXsheet ( ) - > notifyXsheetChanged ( ) ;
notifyImageChanged ( ) ;
}
void redo ( ) const
{
TTool : : Application * app = TTool : : getApplication ( ) ;
if ( ! app )
return ;
TVectorImageP img = m_level - > getFrame ( m_frameId , true ) ;
assert ( img ) ;
if ( ! img )
return ;
TVectorImageP onionImg = m_level - > getFrame ( m_onionFid , false ) ;
if ( ! onionImg )
return ;
if ( m_selectingStroke ) {
stroke_autofill_learn ( onionImg , m_selectingStroke ) ;
stroke_autofill_apply ( img , m_selectingStroke , m_unpaintedOnly ) ;
} else {
rect_autofill_learn ( onionImg , m_selectionArea ) ;
rect_autofill_apply ( img , m_selectionArea , m_unpaintedOnly ) ;
}
app - > getCurrentXsheet ( ) - > notifyXsheetChanged ( ) ;
notifyImageChanged ( ) ;
}
int getSize ( ) const
{
int size = m_selectingStroke ? m_selectingStroke - > getControlPointCount ( ) * sizeof ( TThickPoint ) + 100 : 0 ;
return sizeof ( * this ) + m_regionFillInformation - > capacity ( ) * sizeof ( m_regionFillInformation ) + 500 + size ;
}
} ;
//-----------------------------------------------------------------------------
void doRectAutofill ( const TImageP & img , const TRectD selectingRect , bool onlyUnfilled , const OnionSkinMask & osMask ,
TXshSimpleLevel * sl , const TFrameId & currentFid )
{
TToonzImageP ti ( img ) ;
TVectorImageP vi ( img ) ;
if ( ! img | | ! sl )
return ;
std : : vector < int > rows ;
osMask . getAll ( sl - > guessIndex ( currentFid ) , rows ) ;
if ( rows . empty ( ) )
return ;
TFrameId onionFid ;
int i ;
for ( i = 0 ; i < ( int ) rows . size ( ) ; i + + ) {
const TFrameId & app = sl - > index2fid ( rows [ i ] ) ;
if ( app > currentFid )
break ;
onionFid = app ;
}
if ( onionFid . isEmptyFrame ( ) )
onionFid = sl - > index2fid ( rows [ 0 ] ) ;
if ( onionFid . isEmptyFrame ( ) | | onionFid = = currentFid | | ! sl - > isFid ( onionFid ) )
return ;
if ( ti ) {
TRect rect = ToonzImageUtils : : convertWorldToRaster ( selectingRect , ti ) ;
TToonzImageP onionImg ( sl - > getFrame ( onionFid , false ) ) ;
if ( ! onionImg )
return ;
TRect workRect = rect * ti - > getRaster ( ) - > getBounds ( ) ;
if ( workRect . isEmpty ( ) )
return ;
rect_autofill_learn ( onionImg ,
workRect . x0 ,
workRect . y0 ,
workRect . x1 ,
workRect . y1 ) ;
TTileSetCM32 * tileSet = new TTileSetCM32 ( ti - > getRaster ( ) - > getSize ( ) ) ;
bool recomputeBBox = rect_autofill_apply ( ti ,
workRect . x0 ,
workRect . y0 ,
workRect . x1 ,
workRect . y1 ,
onlyUnfilled , tileSet ) ;
if ( recomputeBBox )
ToolUtils : : updateSaveBox ( ) ;
if ( tileSet - > getTileCount ( ) > 0 )
TUndoManager : : manager ( ) - > add ( new RasterRectAutoFillUndo ( tileSet , workRect , sl , onlyUnfilled ,
currentFid , onionFid ) ) ;
} else if ( vi ) {
TVectorImageP onionImg ( sl - > getFrame ( onionFid , false ) ) ;
if ( ! onionImg )
return ;
2016-04-19 19:32:17 +12:00
std : : vector < TFilledRegionInf > * regionFillInformation = new std : : vector < TFilledRegionInf > ;
2016-03-19 06:57:51 +13:00
ImageUtils : : getFillingInformationInArea ( vi , * regionFillInformation , selectingRect ) ;
onionImg - > findRegions ( ) ;
vi - > findRegions ( ) ;
rect_autofill_learn ( onionImg , selectingRect ) ;
bool hasFilled = rect_autofill_apply ( vi , selectingRect , onlyUnfilled ) ;
if ( hasFilled )
TUndoManager : : manager ( ) - > add ( new VectorAutoFillUndo ( regionFillInformation , selectingRect , 0 ,
onlyUnfilled , sl , currentFid , onionFid ) ) ;
}
}
//-----------------------------------------------------------------------------
void doStrokeAutofill ( const TImageP & img , TStroke * selectingStroke , bool onlyUnfilled , const OnionSkinMask & osMask ,
TXshSimpleLevel * sl , const TFrameId & currentFid )
{
TToonzImageP ti ( img ) ;
TVectorImageP vi ( img ) ;
if ( ! img | | ! sl )
return ;
std : : vector < int > rows ;
osMask . getAll ( sl - > guessIndex ( currentFid ) , rows ) ;
if ( rows . empty ( ) )
return ;
TFrameId onionFid ;
int i ;
for ( i = 0 ; i < ( int ) rows . size ( ) ; i + + ) {
const TFrameId & app = sl - > index2fid ( rows [ i ] ) ;
if ( app > currentFid )
break ;
onionFid = app ;
}
if ( onionFid . isEmptyFrame ( ) )
onionFid = sl - > index2fid ( rows [ 0 ] ) ;
if ( onionFid . isEmptyFrame ( ) | | onionFid = = currentFid | | ! sl - > isFid ( onionFid ) )
return ;
if ( ti ) {
TToonzImageP onionImg ( sl - > getFrame ( onionFid , false ) ) ;
if ( ! onionImg )
return ;
TRasterCM32P ras = onionImg - > getRaster ( ) ;
TPointD center = ras - > getCenterD ( ) ;
TPoint pos ;
TRaster32P image = convertStrokeToImage ( selectingStroke , ras - > getBounds ( ) , pos ) ;
TRect bbox = ( image - > getBounds ( ) + pos ) . enlarge ( 2 ) ;
pos = bbox . getP00 ( ) ;
TRasterCM32P onionAppRas = ras - > extract ( bbox ) - > clone ( ) ;
TRasterCM32P tiAppRas = ti - > getRaster ( ) - > extract ( bbox ) - > clone ( ) ;
TRect workRect = onionAppRas - > getBounds ( ) . enlarge ( - 1 ) ;
TToonzImageP onionApp ( onionAppRas , workRect ) ;
TToonzImageP tiApp ( tiAppRas , workRect ) ;
ToonzImageUtils : : eraseImage ( onionApp , image , TPoint ( 2 , 2 ) , true , true , true , false , 1 ) ;
ToonzImageUtils : : eraseImage ( tiApp , image , TPoint ( 2 , 2 ) , true , true , true , false , 1 ) ;
rect_autofill_learn ( onionApp ,
workRect . x0 ,
workRect . y0 ,
workRect . x1 ,
workRect . y1 ) ;
TTileSetCM32 * tileSet = new TTileSetCM32 ( ti - > getRaster ( ) - > getSize ( ) ) ;
bool recomputeBBox = rect_autofill_apply ( tiApp ,
workRect . x0 ,
workRect . y0 ,
workRect . x1 ,
workRect . y1 ,
onlyUnfilled , tileSet ) ;
delete tileSet ;
tileSet = new TTileSetCM32 ( ti - > getRaster ( ) - > getSize ( ) ) ;
tileSet - > add ( ti - > getRaster ( ) , bbox ) ;
RasterStrokeAutoFillUndo * undo = new RasterStrokeAutoFillUndo ( tileSet , sl , currentFid ) ;
TRop : : over ( ti - > getRaster ( ) , tiAppRas , pos ) ;
TTileSetCM32 * newTileSet = new TTileSetCM32 ( ti - > getRaster ( ) - > getSize ( ) ) ;
newTileSet - > add ( ti - > getRaster ( ) , bbox ) ;
undo - > setTileSet ( newTileSet ) ;
TUndoManager : : manager ( ) - > add ( undo ) ;
} else if ( vi ) {
TVectorImageP onionImg ( sl - > getFrame ( onionFid , false ) ) ;
if ( ! onionImg )
return ;
2016-04-19 19:32:17 +12:00
std : : vector < TFilledRegionInf > * regionFillInformation = new std : : vector < TFilledRegionInf > ;
2016-03-19 06:57:51 +13:00
ImageUtils : : getFillingInformationInArea ( vi , * regionFillInformation , selectingStroke - > getBBox ( ) ) ;
onionImg - > findRegions ( ) ;
vi - > findRegions ( ) ;
stroke_autofill_learn ( onionImg , selectingStroke ) ;
bool hasFilled = stroke_autofill_apply ( vi , selectingStroke , onlyUnfilled ) ;
if ( hasFilled )
TUndoManager : : manager ( ) - > add ( new VectorAutoFillUndo ( regionFillInformation , TRectD ( ) , selectingStroke ,
onlyUnfilled , sl , currentFid , onionFid ) ) ;
}
}
//=============================================================================
// fillRectWithUndo
//-----------------------------------------------------------------------------
bool inline hasAutoInks ( const TPalette * plt )
{
for ( int i = 0 ; i < plt - > getStyleCount ( ) ; i + + )
if ( plt - > getStyle ( i ) - > getFlags ( ) ! = 0 )
return true ;
return false ;
}
//-----------------------------------------------------------------------------
void fillAreaWithUndo (
const TImageP & img ,
const TRectD & area ,
TStroke * stroke ,
bool onlyUnfilled ,
2016-04-19 19:32:17 +12:00
std : : wstring colorType ,
2016-03-19 06:57:51 +13:00
TXshSimpleLevel * sl ,
const TFrameId & fid ,
int cs )
{
TRectD selArea = stroke ? stroke - > getBBox ( ) : area ;
if ( TToonzImageP ti = img ) {
//allargo di 1 la savebox, perche cosi' il rectfill di tutta l'immagine fa una sola fillata
TRect enlargedSavebox = ti - > getSavebox ( ) . enlarge ( 1 ) * TRect ( TPoint ( 0 , 0 ) , ti - > getSize ( ) ) ;
TRect rasterFillArea = ToonzImageUtils : : convertWorldToRaster ( selArea , ti ) * enlargedSavebox ;
if ( rasterFillArea . isEmpty ( ) )
return ;
TRasterCM32P ras = ti - > getRaster ( ) ;
/*-- tileSetでFill範囲のRectをUndoに格納しておく --*/
TTileSetCM32 * tileSet = new TTileSetCM32 ( ras - > getSize ( ) ) ;
tileSet - > add ( ras , rasterFillArea ) ;
AreaFiller filler ( ti - > getRaster ( ) ) ;
if ( ! stroke )
filler . rectFill ( rasterFillArea , cs , onlyUnfilled , colorType ! = LINES , colorType ! = AREAS ) ;
else
filler . strokeFill ( stroke , cs , onlyUnfilled , colorType ! = LINES , colorType ! = AREAS ) ;
TPalette * plt = ti - > getPalette ( ) ;
if ( plt & & ! hasAutoInks ( plt ) )
plt = 0 ;
std : : set < int > autoInks ;
autoInks . insert ( 3 ) ;
autoInks . insert ( 4 ) ;
autoInks . insert ( 5 ) ;
if ( plt ) {
TRect rect = rasterFillArea ;
TRect bounds = ras - > getBounds ( ) ;
if ( bounds . overlaps ( rect ) ) {
rect * = bounds ;
const TTileSetCM32 : : Tile * tile = tileSet - > getTile ( tileSet - > getTileCount ( ) - 1 ) ;
TRasterCM32P rbefore ;
tile - > getRaster ( rbefore ) ;
fillautoInks ( ras , rect , rbefore , plt ) ;
}
}
ToolUtils : : updateSaveBox ( sl , fid ) ;
TUndoManager : : manager ( ) - > add ( new RasterRectFillUndo ( tileSet , stroke ,
rasterFillArea ,
cs , sl , colorType ,
onlyUnfilled , fid , plt ) ) ;
} else if ( TVectorImageP vi = img ) {
TPalette * palette = vi - > getPalette ( ) ;
assert ( palette ) ;
const TColorStyle * style = palette - > getStyle ( cs ) ;
//if( !style->isRegionStyle() )
//return;
vi - > findRegions ( ) ;
2016-04-19 19:32:17 +12:00
std : : vector < TFilledRegionInf > * regionFillInformation = 0 ;
std : : vector < std : : pair < int , int > > * strokeFillInformation = 0 ;
2016-03-19 06:57:51 +13:00
if ( colorType ! = LINES ) {
2016-04-19 19:32:17 +12:00
regionFillInformation = new std : : vector < TFilledRegionInf > ;
2016-03-19 06:57:51 +13:00
ImageUtils : : getFillingInformationInArea ( vi , * regionFillInformation , selArea ) ;
}
if ( colorType ! = AREAS ) {
2016-04-19 19:32:17 +12:00
strokeFillInformation = new std : : vector < std : : pair < int , int > > ;
2016-03-19 06:57:51 +13:00
ImageUtils : : getStrokeStyleInformationInArea ( vi , * strokeFillInformation , selArea ) ;
}
VectorRectFillUndo * fUndo =
new VectorRectFillUndo ( regionFillInformation , strokeFillInformation , selArea , stroke , cs , onlyUnfilled , sl , fid ) ;
QMutexLocker lock ( vi - > getMutex ( ) ) ;
if ( vi - > selectFill ( area , stroke , cs , onlyUnfilled , colorType ! = LINES , colorType ! = AREAS ) )
TUndoManager : : manager ( ) - > add ( fUndo ) ;
else
delete fUndo ;
}
}
//=============================================================================
// doFill
//-----------------------------------------------------------------------------
void doFill ( const TImageP & img ,
const TPointD & pos ,
FillParameters & params ,
bool isShiftFill ,
TXshSimpleLevel * sl ,
const TFrameId & fid )
{
TTool : : Application * app = TTool : : getApplication ( ) ;
if ( ! app )
return ;
if ( TToonzImageP ti = TToonzImageP ( img ) ) {
TPoint offs ( 0 , 0 ) ;
TRasterCM32P ras = ti - > getRaster ( ) ;
if ( Preferences : : instance ( ) - > getFillOnlySavebox ( ) ) {
TRectD bbox = ti - > getBBox ( ) ;
TRect ibbox = convert ( bbox ) ;
offs = ibbox . getP00 ( ) ;
ras = ti - > getRaster ( ) - > extract ( ibbox ) ;
}
bool recomputeSavebox = false ;
TPalette * plt = ti - > getPalette ( ) ;
if ( ! ras . getPointer ( ) | | ras - > isEmpty ( ) )
return ;
ras - > lock ( ) ;
TTileSetCM32 * tileSet = new TTileSetCM32 ( ras - > getSize ( ) ) ;
TTileSaverCM32 tileSaver ( ras , tileSet ) ;
TDimension imageSize = ti - > getSize ( ) ;
TPointD p ( imageSize . lx % 2 ? 0.0 : 0.5 , imageSize . ly % 2 ? 0.0 : 0.5 ) ;
/*-- params.m_p = convert(pos-p)では、マイナス座標でずれが生じる --*/
TPointD tmp_p = pos - p ;
params . m_p = TPoint ( ( int ) floor ( tmp_p . x + 0.5 ) , ( int ) floor ( tmp_p . y + 0.5 ) ) ;
params . m_p + = ti - > getRaster ( ) - > getCenter ( ) ;
params . m_p - = offs ;
params . m_shiftFill = isShiftFill ;
TRect rasRect ( ras - > getSize ( ) ) ;
if ( ! rasRect . contains ( params . m_p ) ) {
ras - > unlock ( ) ;
return ;
}
if ( plt & & hasAutoInks ( plt ) )
params . m_palette = plt ;
if ( params . m_fillType = = ALL | | params . m_fillType = = AREAS ) {
if ( isShiftFill ) {
FillParameters aux ( params ) ;
aux . m_styleId = ( params . m_styleId = = 0 ) ? 1 : 0 ;
recomputeSavebox = fill ( ras , aux , & tileSaver ) ;
}
recomputeSavebox = fill ( ras , params , & tileSaver ) ;
}
if ( params . m_fillType = = ALL | | params . m_fillType = = LINES ) {
if ( params . m_segment )
inkSegment ( ras , params . m_p , params . m_styleId , 2.51 , true , & tileSaver ) ;
else if ( ! params . m_segment )
inkFill ( ras , params . m_p , params . m_styleId , 2 , & tileSaver ) ;
}
if ( tileSaver . getTileSet ( ) - > getTileCount ( ) ! = 0 ) {
static int count = 0 ;
TSystem : : outputDebug ( " FILL " + toString ( count + + ) + " \n " ) ;
if ( offs ! = TPoint ( ) )
for ( int i = 0 ; i < tileSet - > getTileCount ( ) ; i + + ) {
TTileSet : : Tile * t = tileSet - > editTile ( i ) ;
t - > m_rasterBounds = t - > m_rasterBounds + offs ;
}
TUndoManager : : manager ( ) - > add ( new RasterFillUndo ( tileSet , params , sl , fid , Preferences : : instance ( ) - > getFillOnlySavebox ( ) ) ) ;
}
// al posto di updateFrame:
TXshLevel * xl = app - > getCurrentLevel ( ) - > getLevel ( ) ;
if ( ! xl )
return ;
TXshSimpleLevel * sl = xl - > getSimpleLevel ( ) ;
sl - > getProperties ( ) - > setDirtyFlag ( true ) ;
if ( recomputeSavebox & & Preferences : : instance ( ) - > isMinimizeSaveboxAfterEditing ( ) )
ToolUtils : : updateSaveBox ( sl , fid ) ;
ras - > unlock ( ) ;
} else if ( TVectorImageP vi = TImageP ( img ) ) {
int oldStyleId ;
QMutexLocker lock ( vi - > getMutex ( ) ) ;
/*if(params.m_fillType==ALL || params.m_fillType==AREAS)
vi - > computeRegion ( pos , params . m_styleId ) ; */
if ( ( oldStyleId = vectorFill ( vi , params . m_fillType , pos , params . m_styleId , params . m_emptyOnly ) ) ! = - 1 )
TUndoManager : : manager ( ) - > add (
new VectorFillUndo ( params . m_styleId , oldStyleId , params . m_fillType , pos , sl , fid ) ) ;
}
TTool * t = app - > getCurrentTool ( ) - > getTool ( ) ;
if ( t )
t - > notifyImageChanged ( ) ;
}
//=============================================================================
// SequencePainter
// da spostare in toolutils?
//-----------------------------------------------------------------------------
class SequencePainter
{
public :
virtual void process ( TImageP img /*, TImageLocation &imgloc*/ , double t , TXshSimpleLevel * sl , const TFrameId & fid ) = 0 ;
void processSequence ( TXshSimpleLevel * sl , TFrameId firstFid , TFrameId lastFid ) ;
virtual ~ SequencePainter ( ) { }
} ;
//-----------------------------------------------------------------------------
void SequencePainter : : processSequence ( TXshSimpleLevel * sl , TFrameId firstFid , TFrameId lastFid )
{
if ( ! sl )
return ;
bool backward = false ;
if ( firstFid > lastFid ) {
tswap ( firstFid , lastFid ) ;
backward = true ;
}
assert ( firstFid < = lastFid ) ;
2016-04-19 19:32:17 +12:00
std : : vector < TFrameId > allFids ;
2016-03-19 06:57:51 +13:00
sl - > getFids ( allFids ) ;
std : : vector < TFrameId > : : iterator i0 = allFids . begin ( ) ;
while ( i0 ! = allFids . end ( ) & & * i0 < firstFid )
i0 + + ;
if ( i0 = = allFids . end ( ) )
return ;
std : : vector < TFrameId > : : iterator i1 = i0 ;
while ( i1 ! = allFids . end ( ) & & * i1 < = lastFid )
i1 + + ;
assert ( i0 < i1 ) ;
2016-04-19 19:32:17 +12:00
std : : vector < TFrameId > fids ( i0 , i1 ) ;
2016-03-19 06:57:51 +13:00
int m = fids . size ( ) ;
assert ( m > 0 ) ;
TUndoManager : : manager ( ) - > beginBlock ( ) ;
for ( int i = 0 ; i < m ; + + i ) {
TFrameId fid = fids [ i ] ;
assert ( firstFid < = fid & & fid < = lastFid ) ;
TImageP img = sl - > getFrame ( fid , true ) ;
double t = m > 1 ? ( double ) i / ( double ) ( m - 1 ) : 0.5 ;
process ( img , backward ? 1 - t : t , sl , fid ) ;
//Setto il fid come corrente per notificare il cambiamento dell'immagine
TTool : : Application * app = TTool : : getApplication ( ) ;
if ( app ) {
if ( app - > getCurrentFrame ( ) - > isEditingScene ( ) )
app - > getCurrentFrame ( ) - > setFrame ( fid . getNumber ( ) ) ;
else
app - > getCurrentFrame ( ) - > setFid ( fid ) ;
TTool * tool = app - > getCurrentTool ( ) - > getTool ( ) ;
if ( tool )
tool - > notifyImageChanged ( fid ) ;
}
}
TUndoManager : : manager ( ) - > endBlock ( ) ;
}
//=============================================================================
// MultiAreaFiller : SequencePainter
//-----------------------------------------------------------------------------
class MultiAreaFiller : public SequencePainter
{
TRectD m_firstRect , m_lastRect ;
bool m_unfilledOnly ;
2016-04-19 19:32:17 +12:00
std : : wstring m_colorType ;
2016-03-19 06:57:51 +13:00
TVectorImageP m_firstImage , m_lastImage ;
int m_styleIndex ;
public :
MultiAreaFiller (
const TRectD & firstRect ,
const TRectD & lastRect ,
bool unfilledOnly ,
2016-04-19 19:32:17 +12:00
std : : wstring colorType ,
2016-03-19 06:57:51 +13:00
int styleIndex )
: m_firstRect ( firstRect ) , m_lastRect ( lastRect ) , m_unfilledOnly ( unfilledOnly ) , m_colorType ( colorType ) , m_firstImage ( ) , m_lastImage ( ) , m_styleIndex ( styleIndex )
{
}
~ MultiAreaFiller ( )
{
if ( m_firstImage ) {
m_firstImage - > removeStroke ( 0 ) ;
m_lastImage - > removeStroke ( 0 ) ;
}
}
MultiAreaFiller (
TStroke * & firstStroke ,
TStroke * & lastStroke ,
bool unfilledOnly ,
2016-04-19 19:32:17 +12:00
std : : wstring colorType ,
2016-03-19 06:57:51 +13:00
int styleIndex )
: m_firstRect ( ) , m_lastRect ( ) , m_unfilledOnly ( unfilledOnly ) , m_colorType ( colorType ) , m_styleIndex ( styleIndex )
{
m_firstImage = new TVectorImage ( ) ;
m_lastImage = new TVectorImage ( ) ;
m_firstImage - > addStroke ( firstStroke ) ;
m_lastImage - > addStroke ( lastStroke ) ;
}
void process ( TImageP img , double t , TXshSimpleLevel * sl , const TFrameId & fid )
{
if ( ! m_firstImage ) {
TPointD p0 = m_firstRect . getP00 ( ) * ( 1 - t ) + m_lastRect . getP00 ( ) * t ;
TPointD p1 = m_firstRect . getP11 ( ) * ( 1 - t ) + m_lastRect . getP11 ( ) * t ;
TRectD rect ( p0 . x , p0 . y , p1 . x , p1 . y ) ;
fillAreaWithUndo ( img , rect , 0 , m_unfilledOnly , m_colorType , sl , fid , m_styleIndex ) ;
} else {
if ( t = = 0 )
fillAreaWithUndo ( img , TRectD ( ) , m_firstImage - > getStroke ( 0 ) , m_unfilledOnly , m_colorType , sl , fid , m_styleIndex ) ;
else if ( t = = 1 )
fillAreaWithUndo ( img , TRectD ( ) , m_lastImage - > getStroke ( 0 ) , m_unfilledOnly , m_colorType , sl , fid , m_styleIndex ) ;
else
//if(t>1)
{
assert ( t > 0 & & t < 1 ) ;
assert ( m_firstImage - > getStrokeCount ( ) = = 1 ) ;
assert ( m_lastImage - > getStrokeCount ( ) = = 1 ) ;
TVectorImageP vi = TInbetween ( m_firstImage , m_lastImage ) . tween ( t ) ;
assert ( vi - > getStrokeCount ( ) = = 1 ) ;
fillAreaWithUndo ( img , TRectD ( ) , vi - > getStroke ( 0 ) /*, imgloc*/ , m_unfilledOnly , m_colorType , sl , fid , m_styleIndex ) ;
}
}
}
} ;
//=============================================================================
// MultiFiller : SequencePainter
//-----------------------------------------------------------------------------
class MultiFiller : public SequencePainter
{
TPointD m_firstPoint , m_lastPoint ;
FillParameters m_params ;
public :
MultiFiller (
const TPointD & firstPoint ,
const TPointD & lastPoint ,
const FillParameters & params )
: m_firstPoint ( firstPoint ) , m_lastPoint ( lastPoint ) , m_params ( params )
{
}
void process ( TImageP img , double t , TXshSimpleLevel * sl , const TFrameId & fid )
{
TPointD p = m_firstPoint * ( 1 - t ) + m_lastPoint * t ;
doFill ( img , p , m_params , false , sl , fid ) ;
}
} ;
//=============================================================================
/*
if ( e . isShiftPressed ( ) )
{
m_firstPoint = pos ;
m_firstFrameId = TApplication : : instance ( ) - > getCurrentFrameId ( ) ;
}
else
{
m_firstClick = false ;
TApplication : : instance ( ) - > setCurrentFrame ( m_veryFirstFrameId ) ;
}
TNotifier : : instance ( ) - > notify ( TLevelChange ( ) ) ;
TNotifier : : instance ( ) - > notify ( TStageChange ( ) ) ;
}
}
*/
//=============================================================================
// AreaFillTool
//-----------------------------------------------------------------------------
2016-04-19 19:32:17 +12:00
void drawPolyline ( const std : : vector < TPointD > & points )
2016-03-19 06:57:51 +13:00
{
if ( points . empty ( ) )
return ;
tglDrawCircle ( points [ 0 ] , 2 ) ;
for ( UINT i = 0 ; i < points . size ( ) - 1 ; i + + )
tglDrawSegment ( points [ i ] , points [ i + 1 ] ) ;
}
//-----------------------------------------------------------------------------
class AreaFillTool
{
public :
enum Type { RECT ,
FREEHAND ,
POLYLINE } ;
private :
bool m_frameRange ;
bool m_onlyUnfilled ;
Type m_type ;
bool m_selecting ;
TRectD m_selectingRect ;
TRectD m_firstRect ;
bool m_firstFrameSelected ;
TXshSimpleLevelP m_level ;
TFrameId m_firstFrameId , m_veryFirstFrameId ;
TTool * m_parent ;
2016-04-19 19:32:17 +12:00
std : : wstring m_colorType ;
2016-03-19 06:57:51 +13:00
std : : pair < int , int > m_currCell ;
StrokeGenerator m_track ;
2016-04-19 19:32:17 +12:00
std : : vector < TPointD > m_polyline ;
2016-03-19 06:57:51 +13:00
bool m_isPath ;
bool m_active ;
bool m_enabled ;
double m_thick ;
TPointD m_firstPos ;
TStroke * m_firstStroke ;
TPointD m_mousePosition ;
bool m_onion ;
bool m_isLeftButtonPressed ;
public :
AreaFillTool ( TTool * parent )
: m_frameRange ( false ) , m_onlyUnfilled ( false ) , m_selecting ( false ) , m_selectingRect ( TRectD ( ) ) , m_firstRect ( TRectD ( ) ) , m_firstFrameSelected ( false ) , m_level ( 0 ) , m_parent ( parent ) , m_colorType ( AREAS ) , m_currCell ( - 1 , - 1 ) , m_type ( RECT ) , m_isPath ( false ) , m_enabled ( false ) , m_active ( false ) , m_firstStroke ( 0 ) , m_thick ( 0.5 ) , m_mousePosition ( ) , m_onion ( false ) , m_isLeftButtonPressed ( false )
{
}
void draw ( )
{
m_thick = m_parent - > getPixelSize ( ) / 2.0 ;
TPixel color = TPixel32 : : Red ;
if ( m_type = = RECT ) {
if ( m_frameRange & & m_firstFrameSelected )
drawRect ( m_firstRect , color , 0x3F33 , true ) ;
if ( m_selecting | | ( m_frameRange & & ! m_firstFrameSelected ) )
drawRect ( m_selectingRect , color , 0xFFFF , true ) ;
} else if ( ( m_type = = FREEHAND | | m_type = = POLYLINE ) & & m_frameRange ) {
tglColor ( color ) ;
if ( m_firstStroke )
drawStrokeCenterline ( * m_firstStroke , 1 ) ;
}
if ( m_type = = POLYLINE & & ! m_polyline . empty ( ) ) {
glPushMatrix ( ) ;
tglColor ( TPixel : : Red ) ;
tglDrawCircle ( m_polyline [ 0 ] , 2 ) ;
glBegin ( GL_LINE_STRIP ) ;
for ( UINT i = 0 ; i < m_polyline . size ( ) ; i + + )
tglVertex ( m_polyline [ i ] ) ;
tglVertex ( m_mousePosition ) ;
glEnd ( ) ;
glPopMatrix ( ) ;
}
}
void resetMulti ( )
{
m_firstFrameSelected = false ;
m_firstRect . empty ( ) ;
m_selectingRect . empty ( ) ;
TTool : : Application * app = TTool : : getApplication ( ) ;
TXshLevel * xl = app - > getCurrentLevel ( ) - > getLevel ( ) ;
m_level = xl ? xl - > getSimpleLevel ( ) : 0 ;
m_firstFrameId = m_veryFirstFrameId = m_parent - > getCurrentFid ( ) ;
if ( m_firstStroke ) {
delete m_firstStroke ;
m_firstStroke = 0 ;
}
}
void leftButtonDown ( const TPointD & pos , const TMouseEvent & , TImage * img )
{
TVectorImageP vi = TImageP ( img ) ;
TToonzImageP ti = TToonzImageP ( img ) ;
if ( ! vi & & ! ti ) {
m_selecting = false ;
return ;
}
m_selecting = true ;
if ( m_type = = RECT ) {
m_selectingRect . x0 = pos . x ;
m_selectingRect . y0 = pos . y ;
m_selectingRect . x1 = pos . x + 1 ;
m_selectingRect . y1 = pos . y + 1 ;
} else if ( m_type = = FREEHAND | | m_type = = POLYLINE ) {
int col = TTool : : getApplication ( ) - > getCurrentColumn ( ) - > getColumnIndex ( ) ;
m_isPath = TTool : : getApplication ( ) - > getCurrentObject ( ) - > isSpline ( ) ; //getApplication()->isEditingSpline();
m_enabled = col > = 0 | | m_isPath ;
if ( ! m_enabled )
return ;
m_active = true ;
m_track . clear ( ) ;
m_firstPos = pos ;
double pixelSize2 = m_parent - > getPixelSize ( ) * m_parent - > getPixelSize ( ) ;
m_track . add ( TThickPoint ( pos , m_thick ) , pixelSize2 ) ;
if ( m_type = = POLYLINE ) {
if ( m_polyline . empty ( ) | | m_polyline . back ( ) ! = pos )
m_polyline . push_back ( pos ) ;
m_mousePosition = pos ;
} else
m_track . add ( TThickPoint ( pos , m_thick ) , pixelSize2 ) ;
TPointD dpiScale = m_parent - > getViewer ( ) - > getDpiScale ( ) ;
# if defined(MACOSX)
//m_parent->m_viewer->prepareForegroundDrawing();
# endif
// m_parent->m_viewer->makeCurrent();
tglColor ( TPixel : : Red ) ;
m_parent - > getViewer ( ) - > startForegroundDrawing ( ) ;
# if defined(MACOSX)
// m_parent->m_viewer->enableRedraw(m_type == POLYLINE);
# endif
glPushMatrix ( ) ;
tglMultMatrix ( m_parent - > getMatrix ( ) ) ;
glScaled ( dpiScale . x , dpiScale . y , 1 ) ;
if ( m_type = = POLYLINE ) {
if ( m_polyline . empty ( ) | | m_polyline . back ( ) ! = pos )
m_polyline . push_back ( pos ) ;
//drawPolyline(m_polyline);
} else
m_track . drawLastFragments ( ) ;
glPopMatrix ( ) ;
m_parent - > getViewer ( ) - > endForegroundDrawing ( ) ;
}
m_isLeftButtonPressed = true ;
}
/*-- PolyLineFillを閉じる時に呼ばれる --*/
void leftButtonDoubleClick ( const TPointD & pos , const TMouseEvent & e )
{
TStroke * stroke ;
TTool : : Application * app = TTool : : getApplication ( ) ;
if ( ! app )
return ;
if ( m_polyline . size ( ) < = 1 ) {
resetMulti ( ) ;
return ;
}
if ( m_polyline . back ( ) ! = pos )
m_polyline . push_back ( pos ) ;
if ( m_polyline . back ( ) ! = m_polyline . front ( ) )
m_polyline . push_back ( m_polyline . front ( ) ) ;
2016-04-19 19:32:17 +12:00
std : : vector < TThickPoint > strokePoints ;
2016-03-19 06:57:51 +13:00
for ( UINT i = 0 ; i < m_polyline . size ( ) - 1 ; i + + ) {
strokePoints . push_back ( TThickPoint ( m_polyline [ i ] , 1 ) ) ;
strokePoints . push_back ( TThickPoint ( 0.5 * ( m_polyline [ i ] + m_polyline [ i + 1 ] ) , 1 ) ) ;
}
strokePoints . push_back ( TThickPoint ( m_polyline . back ( ) , 1 ) ) ;
m_polyline . clear ( ) ;
stroke = new TStroke ( strokePoints ) ;
assert ( stroke - > getPoint ( 0 ) = = stroke - > getPoint ( 1 ) ) ;
// if (m_type==POLYLINE)
// m_polyline.push_back(pos);
// drawPolyline(m_polyline);
int styleIndex = app - > getCurrentLevelStyleIndex ( ) ;
if ( m_frameRange ) //stroke multi
{
if ( m_firstFrameSelected ) {
MultiAreaFiller filler ( m_firstStroke , stroke , m_onlyUnfilled , m_colorType , styleIndex ) ;
filler . processSequence (
m_level . getPointer ( ) ,
m_firstFrameId ,
m_parent - > getCurrentFid ( ) ) ;
m_parent - > invalidate ( m_selectingRect . enlarge ( 2 ) ) ;
if ( e . isShiftPressed ( ) ) {
m_firstStroke = stroke ;
m_firstFrameId = m_parent - > getCurrentFid ( ) ;
} else {
if ( app - > getCurrentFrame ( ) - > isEditingScene ( ) ) {
app - > getCurrentColumn ( ) - > setColumnIndex ( m_currCell . first ) ;
app - > getCurrentFrame ( ) - > setFrame ( m_currCell . second ) ;
} else
app - > getCurrentFrame ( ) - > setFid ( m_veryFirstFrameId ) ;
resetMulti ( ) ;
}
} else //primo frame
{
m_firstStroke = stroke ;
//if (app->getCurrentFrame()->isEditingScene())
m_currCell = std : : pair < int , int > ( app - > getCurrentColumn ( ) - > getColumnIndex ( ) ,
app - > getCurrentFrame ( ) - > getFrame ( ) ) ;
}
} else {
if ( m_onion ) {
OnionSkinMask osMask = app - > getCurrentOnionSkin ( ) - > getOnionSkinMask ( ) ;
doStrokeAutofill ( m_parent - > getImage ( true ) , stroke , m_onlyUnfilled , osMask ,
m_level . getPointer ( ) , m_parent - > getCurrentFid ( ) ) ;
} else
fillAreaWithUndo ( m_parent - > getImage ( true ) , TRectD ( ) , stroke , m_onlyUnfilled , m_colorType ,
m_level . getPointer ( ) , m_parent - > getCurrentFid ( ) , styleIndex ) ;
TTool * t = app - > getCurrentTool ( ) - > getTool ( ) ;
if ( t )
t - > notifyImageChanged ( ) ;
}
}
void leftButtonDrag ( const TPointD & pos , const TMouseEvent & e )
{
if ( m_type = = RECT ) {
m_selectingRect . x1 = pos . x ;
m_selectingRect . y1 = pos . y ;
m_parent - > invalidate ( ) ;
} else if ( m_type = = FREEHAND ) {
if ( ! m_enabled | | ! m_active )
return ;
# if defined(MACOSX)
//m_parent->m_viewer->enableRedraw(false);
# endif
m_parent - > getViewer ( ) - > startForegroundDrawing ( ) ;
tglColor ( TPixel : : Red ) ;
glPushMatrix ( ) ;
tglMultMatrix ( m_parent - > getMatrix ( ) ) ;
TPointD dpiScale = m_parent - > getViewer ( ) - > getDpiScale ( ) ;
glScaled ( dpiScale . x , dpiScale . y , 1 ) ;
double pixelSize2 = m_parent - > getPixelSize ( ) * m_parent - > getPixelSize ( ) ;
m_track . add ( TThickPoint ( pos , m_thick ) , pixelSize2 ) ;
m_track . drawLastFragments ( ) ;
glPopMatrix ( ) ;
m_parent - > getViewer ( ) - > endForegroundDrawing ( ) ;
}
}
void mouseMove ( const TPointD & pos , const TMouseEvent & e )
{
if ( m_type ! = POLYLINE | | m_polyline . empty ( ) )
return ;
if ( ! m_enabled | | ! m_active )
return ;
m_mousePosition = pos ;
m_parent - > invalidate ( ) ;
}
void leftButtonUp ( const TPointD & pos , const TMouseEvent & e )
{
if ( ! m_isLeftButtonPressed )
return ;
m_isLeftButtonPressed = false ;
TTool : : Application * app = TTool : : getApplication ( ) ;
if ( ! app )
return ;
TXshLevel * xl = app - > getCurrentLevel ( ) - > getLevel ( ) ;
m_level = xl ? xl - > getSimpleLevel ( ) : 0 ;
int styleIndex = app - > getCurrentLevelStyleIndex ( ) ;
m_selecting = false ;
if ( m_type = = RECT ) {
if ( m_selectingRect . x0 > m_selectingRect . x1 )
tswap ( m_selectingRect . x0 , m_selectingRect . x1 ) ;
if ( m_selectingRect . y0 > m_selectingRect . y1 )
tswap ( m_selectingRect . y0 , m_selectingRect . y1 ) ;
if ( m_frameRange ) {
if ( m_firstFrameSelected ) {
MultiAreaFiller filler ( m_firstRect , m_selectingRect , m_onlyUnfilled , m_colorType , styleIndex ) ;
filler . processSequence (
m_level . getPointer ( ) ,
m_firstFrameId ,
m_parent - > getCurrentFid ( ) ) ;
m_parent - > invalidate ( m_selectingRect . enlarge ( 2 ) ) ;
if ( e . isShiftPressed ( ) ) {
m_firstRect = m_selectingRect ;
m_firstFrameId = m_parent - > getCurrentFid ( ) ;
} else {
if ( app - > getCurrentFrame ( ) - > isEditingScene ( ) ) {
app - > getCurrentColumn ( ) - > setColumnIndex ( m_currCell . first ) ;
app - > getCurrentFrame ( ) - > setFrame ( m_currCell . second ) ;
} else
app - > getCurrentFrame ( ) - > setFid ( m_veryFirstFrameId ) ;
resetMulti ( ) ;
}
} else {
//if (app->getCurrentFrame()->isEditingScene())
m_currCell = std : : pair < int , int > ( app - > getCurrentColumn ( ) - > getColumnIndex ( ) ,
app - > getCurrentFrame ( ) - > getFrame ( ) ) ;
}
} else {
if ( m_onion ) {
OnionSkinMask osMask = app - > getCurrentOnionSkin ( ) - > getOnionSkinMask ( ) ;
doRectAutofill ( m_parent - > getImage ( true ) , m_selectingRect , m_onlyUnfilled , osMask ,
m_level . getPointer ( ) , m_parent - > getCurrentFid ( ) ) ;
} else
fillAreaWithUndo ( m_parent - > getImage ( true ) , m_selectingRect , 0 , m_onlyUnfilled , m_colorType , m_level . getPointer ( ) , m_parent - > getCurrentFid ( ) , styleIndex ) ;
m_parent - > invalidate ( ) ;
m_selectingRect . empty ( ) ;
TTool * t = app - > getCurrentTool ( ) - > getTool ( ) ;
if ( t )
t - > notifyImageChanged ( ) ;
}
} else if ( m_type = = FREEHAND ) {
# if defined(MACOSX)
//m_parent->m_viewer->enableRedraw(true);
# endif
bool isValid = m_enabled & & m_active ;
m_enabled = m_active = false ;
if ( ! isValid | | m_track . isEmpty ( ) )
return ;
double pixelSize2 = m_parent - > getPixelSize ( ) * m_parent - > getPixelSize ( ) ;
m_track . add ( TThickPoint ( m_firstPos , m_thick ) , pixelSize2 ) ;
m_track . filterPoints ( ) ;
double error = ( m_isPath ? 20.0 : 30.0 / 11 ) * sqrt ( pixelSize2 ) ;
TStroke * stroke = m_track . makeStroke ( error ) ;
stroke - > setStyle ( 1 ) ;
m_track . clear ( ) ;
if ( m_frameRange ) //stroke multi
{
if ( m_firstFrameSelected ) {
MultiAreaFiller filler ( m_firstStroke , stroke , m_onlyUnfilled , m_colorType , styleIndex ) ;
filler . processSequence (
m_level . getPointer ( ) ,
m_firstFrameId ,
m_parent - > getCurrentFid ( ) ) ;
m_parent - > invalidate ( m_selectingRect . enlarge ( 2 ) ) ;
if ( e . isShiftPressed ( ) ) {
m_firstStroke = stroke ;
m_firstFrameId = m_parent - > getCurrentFid ( ) ;
} else {
if ( app - > getCurrentFrame ( ) - > isEditingScene ( ) ) {
app - > getCurrentColumn ( ) - > setColumnIndex ( m_currCell . first ) ;
app - > getCurrentFrame ( ) - > setFrame ( m_currCell . second ) ;
} else
app - > getCurrentFrame ( ) - > setFid ( m_veryFirstFrameId ) ;
resetMulti ( ) ;
}
} else //primo frame
{
m_firstStroke = stroke ;
//if (app->getCurrentFrame()->isEditingScene())
m_currCell = std : : pair < int , int > ( app - > getCurrentColumn ( ) - > getColumnIndex ( ) ,
app - > getCurrentFrame ( ) - > getFrame ( ) ) ;
}
} else //stroke non multi
{
if ( ! m_parent - > getImage ( true ) )
return ;
if ( m_onion ) {
OnionSkinMask osMask = app - > getCurrentOnionSkin ( ) - > getOnionSkinMask ( ) ;
doStrokeAutofill ( m_parent - > getImage ( true ) , stroke , m_onlyUnfilled , osMask ,
m_level . getPointer ( ) , m_parent - > getCurrentFid ( ) ) ;
} else
fillAreaWithUndo (
m_parent - > getImage ( true ) ,
TRectD ( ) ,
stroke /*, imageLocation*/ ,
m_onlyUnfilled ,
m_colorType ,
m_level . getPointer ( ) ,
m_parent - > getCurrentFid ( ) ,
styleIndex ) ;
delete stroke ;
TTool * t = app - > getCurrentTool ( ) - > getTool ( ) ;
if ( t )
t - > notifyImageChanged ( ) ;
m_parent - > invalidate ( ) ;
}
}
}
void onImageChanged ( )
{
if ( ! m_frameRange )
return ;
TTool : : Application * app = TTool : : getApplication ( ) ;
if ( ! app )
return ;
TXshLevel * xshl = app - > getCurrentLevel ( ) - > getLevel ( ) ;
if ( ! xshl | | m_level . getPointer ( ) ! = xshl | | ( m_selectingRect . isEmpty ( ) & & ! m_firstStroke ) )
resetMulti ( ) ;
else if ( m_firstFrameId = = m_parent - > getCurrentFid ( ) )
m_firstFrameSelected = false ; //nel caso sono passato allo stato 1 e torno all'immagine iniziale, torno allo stato iniziale
else { //cambio stato.
m_firstFrameSelected = true ;
if ( m_type ! = FREEHAND & & m_type ! = POLYLINE ) {
assert ( ! m_selectingRect . isEmpty ( ) ) ;
m_firstRect = m_selectingRect ;
}
}
}
/*--Normal以外のTypeが選択された場合に呼ばれる--*/
2016-04-19 19:32:17 +12:00
bool onPropertyChanged ( bool multi , bool onlyUnfilled , bool onion , Type type , std : : wstring colorType )
2016-03-19 06:57:51 +13:00
{
m_frameRange = multi ;
m_onlyUnfilled = onlyUnfilled ;
m_colorType = colorType ;
m_type = type ;
m_onion = onion ;
if ( m_frameRange )
resetMulti ( ) ;
/*--動作中にプロパティが変わったら、現在の動作を無効にする--*/
if ( m_isLeftButtonPressed )
m_isLeftButtonPressed = false ;
if ( m_type = = POLYLINE & & ! m_polyline . empty ( ) )
m_polyline . clear ( ) ;
return true ;
}
void onActivate ( )
{
//getApplication()->editImage();
if ( m_frameRange )
resetMulti ( ) ;
if ( TVectorImageP vi = TImageP ( m_parent - > getImage ( false ) ) )
vi - > findRegions ( ) ;
}
void onEnter ( )
{
//getApplication()->editImage();
}
} ;
} // namespace
//=============================================================================
/*! NormalLineFillTool
マ ウ ス ド ラ ッ グ で 直 線 を 延 ば し 、 そ の 直 線 が ま た い だ 点 を FillLineするツール 。
Raster - Normal - Line Fillツール ( FrameRangeなし ) の と き 使 用 可 能 に す る
*/
class NormalLineFillTool
{
TTool * m_parent ;
TPointD m_startPosition , m_mousePosition ;
bool m_isEditing ;
public :
NormalLineFillTool ( TTool * parent )
: m_parent ( parent ) , m_isEditing ( false ) , m_mousePosition ( )
{
}
/*-- FillLineツールに戻ってきたときに前の位置情報をリセットする --*/
void init ( )
{
m_startPosition = TPointD ( ) ;
m_mousePosition = TPointD ( ) ;
m_isEditing = false ;
}
void leftButtonDown ( const TPointD & pos , const TMouseEvent & e )
{
m_startPosition = pos ; /*-始点-*/
m_mousePosition = pos ; /*-終点-*/
m_isEditing = true ;
}
void leftButtonDrag ( const TPointD & pos , const TMouseEvent & e )
{
if ( ! m_isEditing )
return ;
m_mousePosition = pos ;
m_parent - > invalidate ( ) ;
}
void leftButtonUp ( const TPointD & pos , const TMouseEvent & e , TImage * img , FillParameters & params )
{
if ( ! m_isEditing )
return ;
m_mousePosition = pos ;
TTool : : Application * app = TTool : : getApplication ( ) ;
if ( ! app )
return ;
TXshLevel * xl = app - > getCurrentLevel ( ) - > getLevel ( ) ;
TXshSimpleLevel * sl = xl ? xl - > getSimpleLevel ( ) : 0 ;
TToonzImageP ti = TImageP ( m_parent - > getImage ( true ) ) ;
if ( ! ti )
return ;
TRasterCM32P ras = ti - > getRaster ( ) ;
if ( ! ras )
return ;
int styleId = params . m_styleId ;
/*--- 線分上にある全ての点でdoFillを行う ---*/
double dx = m_mousePosition . x - m_startPosition . x ;
double dy = m_mousePosition . y - m_startPosition . y ;
if ( abs ( dx ) > abs ( dy ) ) /*-- 横長の線分の場合 --*/
{
double k = dy / dx ; /*-- 直線の傾き --*/
/*--- roundでは負値のときにうまく繋がらない ---*/
int start = tmin ( ( int ) floor ( m_startPosition . x + 0.5 ) , ( int ) floor ( m_mousePosition . x + 0.5 ) ) ;
int end = tmax ( ( int ) floor ( m_startPosition . x + 0.5 ) , ( int ) floor ( m_mousePosition . x + 0.5 ) ) ;
double start_x = ( m_startPosition . x < m_mousePosition . x ) ? m_startPosition . x : m_mousePosition . x ;
double start_y = ( m_startPosition . x < m_mousePosition . x ) ? m_startPosition . y : m_mousePosition . y ;
for ( int x = start ; x < = end ; x + + ) {
double ddx = ( double ) ( x - start ) ;
TPointD tmpPos ( start_x + ddx , ddx * k + start_y ) ;
TPoint ipos ( ( int ) ( tmpPos . x + ras - > getLx ( ) / 2 ) , ( int ) ( tmpPos . y + ras - > getLy ( ) / 2 ) ) ;
if ( ! ras - > getBounds ( ) . contains ( ipos ) )
continue ;
TPixelCM32 pix = ras - > pixels ( ipos . y ) [ ipos . x ] ;
if ( pix . getInk ( ) = = styleId | | pix . isPurePaint ( ) )
continue ;
doFill ( img , tmpPos , params , e . isShiftPressed ( ) , sl , m_parent - > getCurrentFid ( ) ) ;
}
} else /*-- 縦長の線分の場合 --*/
{
double k = dx / dy ; /*-- 直線の傾き --*/
/*--- roundでは負値のときにうまく繋がらない ---*/
int start = tmin ( ( int ) floor ( m_startPosition . y + 0.5 ) , ( int ) floor ( m_mousePosition . y + 0.5 ) ) ;
int end = tmax ( ( int ) floor ( m_startPosition . y + 0.5 ) , ( int ) floor ( m_mousePosition . y + 0.5 ) ) ;
double start_x = ( m_startPosition . y < m_mousePosition . y ) ? m_startPosition . x : m_mousePosition . x ;
double start_y = ( m_startPosition . y < m_mousePosition . y ) ? m_startPosition . y : m_mousePosition . y ;
for ( int y = start ; y < = end ; y + + ) {
double ddy = ( double ) ( y - start ) ;
TPointD tmpPos ( ddy * k + start_x , ddy + start_y ) ;
TPoint ipos ( ( int ) ( tmpPos . x + ras - > getLx ( ) / 2 ) , ( int ) ( tmpPos . y + ras - > getLy ( ) / 2 ) ) ;
if ( ! ras - > getBounds ( ) . contains ( ipos ) )
continue ;
TPixelCM32 pix = ras - > pixels ( ipos . y ) [ ipos . x ] ;
if ( pix . getInk ( ) = = styleId | | pix . isPurePaint ( ) )
continue ;
doFill ( img , tmpPos , params , e . isShiftPressed ( ) , sl , m_parent - > getCurrentFid ( ) ) ;
}
}
m_isEditing = false ;
m_parent - > invalidate ( ) ;
}
void draw ( )
{
if ( m_isEditing ) {
tglColor ( TPixel32 : : Red ) ;
glBegin ( GL_LINE_STRIP ) ;
tglVertex ( m_startPosition ) ;
tglVertex ( m_mousePosition ) ;
glEnd ( ) ;
}
}
} ;
//=============================================================================
//=============================================================================
// Fill Tool
//-----------------------------------------------------------------------------
class FillTool : public TTool
{
Q_DECLARE_TR_FUNCTIONS ( FillTool )
bool m_firstTime ;
TPointD m_firstPoint , m_clickPoint ;
bool m_firstClick ;
TXshSimpleLevelP m_level ;
TFrameId m_firstFrameId , m_veryFirstFrameId ;
int m_onionStyleId ;
TEnumProperty m_colorType ; //Line, Area
TEnumProperty m_fillType ; //Rect, Polyline etc.
TBoolProperty m_onion ;
TBoolProperty m_frameRange ;
TBoolProperty m_selective ;
TDoublePairProperty m_fillDepth ;
TBoolProperty m_segment ;
AreaFillTool * m_rectFill ;
NormalLineFillTool * m_normalLineFillTool ;
TPropertyGroup m_prop ;
std : : pair < int , int > m_currCell ;
# ifdef _DEBUG
2016-04-19 19:32:17 +12:00
std : : vector < TRect > m_rects ;
2016-03-19 06:57:51 +13:00
# endif
public :
FillTool ( int targetType ) ;
ToolType getToolType ( ) const { return TTool : : LevelWriteTool ; }
void updateTranslation ( ) ;
TPropertyGroup * getProperties ( int targetType ) { return & m_prop ; }
FillParameters getFillParameters ( ) const ;
void leftButtonDown ( const TPointD & pos , const TMouseEvent & e ) ;
void leftButtonDrag ( const TPointD & pos , const TMouseEvent & e ) ;
void leftButtonUp ( const TPointD & pos , const TMouseEvent & e ) ;
void mouseMove ( const TPointD & pos , const TMouseEvent & e ) ;
void leftButtonDoubleClick ( const TPointD & pos , const TMouseEvent & e ) ;
void resetMulti ( ) ;
2016-04-19 19:32:17 +12:00
bool onPropertyChanged ( std : : string propertyName ) ;
2016-03-19 06:57:51 +13:00
void onImageChanged ( ) ;
void draw ( ) ;
int pick ( const TImageP & image , const TPointD & pos ) ;
int pickOnionColor ( const TPointD & pos ) ;
void onEnter ( ) ;
void onActivate ( ) ;
void onDeactivate ( ) ;
int getCursorId ( ) const ;
int getColorClass ( ) const { return 2 ; }
} ;
//-----------------------------------------------------------------------------
FillTool : : FillTool ( int targetType )
: TTool ( " T_Fill " ) , m_frameRange ( " Frame Range " , false ) //W_ToolOptions_FrameRange
,
m_fillType ( " Type: " ) , m_selective ( " Selective " , false ) , m_colorType ( " Mode: " ) , m_onion ( " Onion Skin " , false ) , m_fillDepth ( " Fill Depth " , 0 , 15 , 0 , 15 ) , m_segment ( " Segment " , false ) , m_onionStyleId ( 0 ) , m_currCell ( - 1 , - 1 ) , m_firstTime ( true )
{
m_rectFill = new AreaFillTool ( this ) ;
m_normalLineFillTool = new NormalLineFillTool ( this ) ;
bind ( targetType ) ;
# ifndef STUDENT
m_prop . bind ( m_fillType ) ;
m_fillType . addValue ( NORMALFILL ) ;
m_fillType . addValue ( RECTFILL ) ;
m_fillType . addValue ( FREEHANDFILL ) ;
m_fillType . addValue ( POLYLINEFILL ) ;
# else
m_fillType . addValue ( NORMALFILL ) ;
# endif
m_prop . bind ( m_colorType ) ;
m_colorType . addValue ( LINES ) ;
m_colorType . addValue ( AREAS ) ;
m_colorType . addValue ( ALL ) ;
m_prop . bind ( m_selective ) ;
if ( targetType = = TTool : : ToonzImage ) {
m_prop . bind ( m_fillDepth ) ;
m_prop . bind ( m_segment ) ;
}
m_prop . bind ( m_onion ) ;
m_prop . bind ( m_frameRange ) ;
m_selective . setId ( " Selective " ) ;
m_onion . setId ( " OnionSkin " ) ;
m_frameRange . setId ( " FrameRange " ) ;
m_segment . setId ( " SegmentInk " ) ;
m_fillType . setId ( " Type " ) ;
m_colorType . setId ( " Mode " ) ;
}
//-----------------------------------------------------------------------------
int FillTool : : getCursorId ( ) const
{
bool isBlackBG = ToonzCheck : : instance ( ) - > getChecks ( ) & ToonzCheck : : eBlackBg ;
if ( m_colorType . getValue ( ) = = LINES ) {
if ( m_fillType . getValue ( ) = = NORMALFILL )
return ( isBlackBG ) ? ToolCursor : : FillCursorLWhite : ToolCursor : : FillCursorL ;
else if ( m_fillType . getValue ( ) = = FREEHANDFILL )
return ( isBlackBG ) ? ToolCursor : : FillCursorLFWhite : ToolCursor : : FillCursorLF ;
else if ( m_fillType . getValue ( ) = = POLYLINEFILL )
return ( isBlackBG ) ? ToolCursor : : FillCursorLPWhite : ToolCursor : : FillCursorLP ;
else //Rect
return ( isBlackBG ) ? ToolCursor : : FillCursorLRWhite : ToolCursor : : FillCursorLR ;
} else if ( m_colorType . getValue ( ) = = AREAS ) {
if ( m_fillType . getValue ( ) = = NORMALFILL )
return ( isBlackBG ) ? ToolCursor : : FillCursorAWhite : ToolCursor : : FillCursorA ;
else if ( m_fillType . getValue ( ) = = FREEHANDFILL )
return ( isBlackBG ) ? ToolCursor : : FillCursorAFWhite : ToolCursor : : FillCursorAF ;
else if ( m_fillType . getValue ( ) = = POLYLINEFILL )
return ( isBlackBG ) ? ToolCursor : : FillCursorAPWhite : ToolCursor : : FillCursorAP ;
else //Rect
return ( isBlackBG ) ? ToolCursor : : FillCursorARWhite : ToolCursor : : FillCursorAR ;
} else //line&areas
{
if ( m_fillType . getValue ( ) = = NORMALFILL )
return ( isBlackBG ) ? ToolCursor : : FillCursorWhite : ToolCursor : : FillCursor ;
else if ( m_fillType . getValue ( ) = = FREEHANDFILL )
return ( isBlackBG ) ? ToolCursor : : FillCursorFWhite : ToolCursor : : FillCursorF ;
else if ( m_fillType . getValue ( ) = = POLYLINEFILL )
return ( isBlackBG ) ? ToolCursor : : FillCursorPWhite : ToolCursor : : FillCursorP ;
else //Rect
return ( isBlackBG ) ? ToolCursor : : FillCursorRWhite : ToolCursor : : FillCursorR ;
}
}
//-----------------------------------------------------------------------------
void FillTool : : updateTranslation ( )
{
m_frameRange . setQStringName ( tr ( " Frame Range " ) ) ;
m_fillType . setQStringName ( tr ( " Type: " ) ) ;
m_selective . setQStringName ( tr ( " Selective " ) ) ;
m_colorType . setQStringName ( tr ( " Mode: " ) ) ;
m_onion . setQStringName ( tr ( " Onion Skin " ) ) ;
m_fillDepth . setQStringName ( tr ( " Fill Depth " ) ) ;
m_segment . setQStringName ( tr ( " Segment " ) ) ;
}
//-----------------------------------------------------------------------------
FillParameters FillTool : : getFillParameters ( ) const
{
FillParameters params ;
int styleId = TTool : : getApplication ( ) - > getCurrentLevelStyleIndex ( ) ;
params . m_styleId = styleId ;
/*---紛らわしいことに、colorTypeをfillTypeに名前を変えて保存している。間違いではない。---*/
params . m_fillType = m_colorType . getValue ( ) ;
params . m_emptyOnly = m_selective . getValue ( ) ;
params . m_segment = m_segment . getValue ( ) ;
params . m_minFillDepth = ( int ) m_fillDepth . getValue ( ) . first ;
params . m_maxFillDepth = ( int ) m_fillDepth . getValue ( ) . second ;
return params ;
}
//-----------------------------------------------------------------------------
void FillTool : : leftButtonDown ( const TPointD & pos , const TMouseEvent & e )
{
TTool : : Application * app = TTool : : getApplication ( ) ;
if ( ! app )
return ;
m_clickPoint = pos ;
if ( m_fillType . getValue ( ) ! = NORMALFILL ) {
m_rectFill - > leftButtonDown ( pos , e , getImage ( true ) ) ;
return ;
}
/*--以下、NormalFillの場合--*/
FillParameters params = getFillParameters ( ) ;
if ( m_onion . getValue ( ) ) {
m_onionStyleId = pickOnionColor ( pos ) ;
if ( m_onionStyleId > 0 )
app - > setCurrentLevelStyleIndex ( m_onionStyleId ) ;
} else if ( m_frameRange . getValue ( ) ) {
if ( ! m_firstClick ) {
// PRIMO CLICK
//if (app->getCurrentFrame()->isEditingScene())
m_currCell = std : : pair < int , int > ( getColumnIndex ( ) ,
getFrame ( ) ) ;
m_firstClick = true ;
m_firstPoint = pos ;
m_firstFrameId = m_veryFirstFrameId = getCurrentFid ( ) ;
// gmt. NON BISOGNA DISEGNARE DENTRO LE CALLBACKS!!!!
// drawCross(m_firstPoint, 6);
invalidate ( ) ;
} else {
// SECONDO CLICK
TFrameId fid = getCurrentFid ( ) ;
MultiFiller filler ( m_firstPoint , pos , params ) ;
filler . processSequence ( m_level . getPointer ( ) , m_firstFrameId , fid ) ;
if ( e . isShiftPressed ( ) ) {
m_firstPoint = pos ;
m_firstFrameId = getCurrentFid ( ) ;
} else {
m_firstClick = false ;
if ( app - > getCurrentFrame ( ) - > isEditingScene ( ) ) {
app - > getCurrentColumn ( ) - > setColumnIndex ( m_currCell . first ) ;
app - > getCurrentFrame ( ) - > setFrame ( m_currCell . second ) ;
} else
app - > getCurrentFrame ( ) - > setFid ( m_veryFirstFrameId ) ;
}
TTool * t = app - > getCurrentTool ( ) - > getTool ( ) ;
if ( t )
t - > notifyImageChanged ( ) ;
}
} else {
if ( params . m_fillType = = LINES & & m_targetType = = TTool : : ToonzImage )
m_normalLineFillTool - > leftButtonDown ( pos , e ) ;
else {
TXshLevel * xl = app - > getCurrentLevel ( ) - > getLevel ( ) ;
m_level = xl ? xl - > getSimpleLevel ( ) : 0 ;
doFill ( getImage ( true ) , pos , params , e . isShiftPressed ( ) , m_level . getPointer ( ) , getCurrentFid ( ) ) ;
invalidate ( ) ;
}
}
}
//-----------------------------------------------------------------------------
void FillTool : : leftButtonDoubleClick ( const TPointD & pos , const TMouseEvent & e )
{
if ( m_fillType . getValue ( ) ! = NORMALFILL ) {
m_rectFill - > leftButtonDoubleClick ( pos , e ) ;
return ;
}
}
//-----------------------------------------------------------------------------
void FillTool : : leftButtonDrag ( const TPointD & pos , const TMouseEvent & e )
{
if ( m_fillType . getValue ( ) ! = NORMALFILL & & ! m_onion . getValue ( ) | |
( m_colorType . getValue ( ) = = AREAS & & m_onion . getValue ( ) ) )
m_rectFill - > leftButtonDrag ( pos , e ) ;
else if ( ! m_onion . getValue ( ) & & ! m_frameRange . getValue ( ) ) {
FillParameters params = getFillParameters ( ) ;
if ( params . m_fillType = = LINES & & m_targetType = = TTool : : ToonzImage ) {
m_normalLineFillTool - > leftButtonDrag ( pos , e ) ;
return ;
}
if ( m_clickPoint = = pos )
return ;
TImageP img = getImage ( true ) ;
int styleId = params . m_styleId ;
if ( TVectorImageP vi = img ) {
TRegion * r = vi - > getRegion ( pos ) ;
if ( r & & r - > getStyle ( ) = = styleId )
return ;
} else if ( TToonzImageP ti = img ) {
TRasterCM32P ras = ti - > getRaster ( ) ;
if ( ! ras )
return ;
TPointD center = ras - > getCenterD ( ) ;
TPoint ipos = convert ( pos + center ) ;
if ( ! ras - > getBounds ( ) . contains ( ipos ) )
return ;
TPixelCM32 pix = ras - > pixels ( ipos . y ) [ ipos . x ] ;
if ( pix . getPaint ( ) = = styleId ) {
invalidate ( ) ;
return ;
}
TSystem : : outputDebug ( " ok. pix= " + toString ( pix . getTone ( ) ) + " , " + toString ( pix . getPaint ( ) ) + " \n " ) ;
} else
return ;
doFill ( img , pos , params , e . isShiftPressed ( ) , m_level . getPointer ( ) , getCurrentFid ( ) ) ;
invalidate ( ) ;
}
}
//-----------------------------------------------------------------------------
void FillTool : : leftButtonUp ( const TPointD & pos , const TMouseEvent & e )
{
if ( m_onion . getValue ( ) ) {
if ( m_fillType . getValue ( ) ! = NORMALFILL & & m_colorType . getValue ( ) = = AREAS )
m_rectFill - > leftButtonUp ( pos , e ) ;
else if ( m_onionStyleId > 0 ) {
FillParameters tmp = getFillParameters ( ) ;
doFill ( getImage ( true ) , pos , tmp , e . isShiftPressed ( ) , m_level . getPointer ( ) , getCurrentFid ( ) ) ;
invalidate ( ) ;
}
} else if ( m_fillType . getValue ( ) ! = NORMALFILL ) {
m_rectFill - > leftButtonUp ( pos , e ) ;
return ;
}
if ( ! m_frameRange . getValue ( ) ) {
TFrameId fid = getCurrentFid ( ) ;
//notifyImageChanged();
if ( getFillParameters ( ) . m_fillType = = LINES & & m_targetType = = TTool : : ToonzImage ) {
FillParameters params = getFillParameters ( ) ;
m_normalLineFillTool - > leftButtonUp ( pos , e , getImage ( true ) , params ) ;
return ;
}
}
}
//-----------------------------------------------------------------------------
void FillTool : : resetMulti ( )
{
m_firstClick = false ;
m_firstFrameId = - 1 ;
m_firstPoint = TPointD ( ) ;
TXshLevel * xl = TTool : : getApplication ( ) - > getCurrentLevel ( ) - > getLevel ( ) ;
m_level = xl ? xl - > getSimpleLevel ( ) : 0 ;
}
//-----------------------------------------------------------------------------
2016-04-19 19:32:17 +12:00
bool FillTool : : onPropertyChanged ( std : : string propertyName )
2016-03-19 06:57:51 +13:00
{
/*--- m_rectFill->onPropertyChangedを呼ぶかどうかのフラグ
fillType , frameRange , selective , colorTypeが変わったときに呼ぶ - - - */
bool rectPropChangedflag = false ;
//Areas, Lines etc.
if ( propertyName = = m_colorType . getName ( ) ) {
FillColorType = toString ( m_colorType . getValue ( ) ) ;
rectPropChangedflag = true ;
/*--- ColorModelのCursor更新のためにSIGNALを出す ---*/
TTool : : getApplication ( ) - > getCurrentTool ( ) - > notifyToolChanged ( ) ;
/*--- FillLineツールに戻ってきたときに前回の位置情報をリセットする ---*/
if ( FillColorType . getValue ( ) = = " Lines " )
m_normalLineFillTool - > init ( ) ;
}
// Rect, Polyline etc.
else if ( propertyName = = m_fillType . getName ( ) ) {
if ( m_fillType . getValue ( ) ! = NORMALFILL ) {
FillOnion = ( int ) ( m_onion . getValue ( ) ) ;
FillSegment = ( int ) ( m_segment . getValue ( ) ) ;
}
FillType = toString ( m_fillType . getValue ( ) ) ;
rectPropChangedflag = true ;
}
// Onion Skin
else if ( propertyName = = m_onion . getName ( ) ) {
if ( m_onion . getValue ( ) )
FillType = toString ( m_fillType . getValue ( ) ) ;
FillOnion = ( int ) ( m_onion . getValue ( ) ) ;
}
// Frame Range
else if ( propertyName = = m_frameRange . getName ( ) ) {
FillRange = ( int ) ( m_frameRange . getValue ( ) ) ;
resetMulti ( ) ;
rectPropChangedflag = true ;
}
// Selective
else if ( propertyName = = m_selective . getName ( ) ) {
rectPropChangedflag = true ;
}
// Fill Depth
else if ( propertyName = = m_fillDepth . getName ( ) ) {
MinFillDepth = ( int ) m_fillDepth . getValue ( ) . first ;
MaxFillDepth = ( int ) m_fillDepth . getValue ( ) . second ;
}
// Segment
else if ( propertyName = = m_segment . getName ( ) ) {
if ( m_segment . getValue ( ) )
FillType = toString ( m_fillType . getValue ( ) ) ;
FillSegment = ( int ) ( m_segment . getValue ( ) ) ;
}
/*--- fillType, frameRange, selective, colorTypeが変わったとき ---*/
if ( rectPropChangedflag & & m_fillType . getValue ( ) ! = NORMALFILL ) {
AreaFillTool : : Type type ;
if ( m_fillType . getValue ( ) = = RECTFILL )
type = AreaFillTool : : RECT ;
else if ( m_fillType . getValue ( ) = = FREEHANDFILL )
type = AreaFillTool : : FREEHAND ;
else if ( m_fillType . getValue ( ) = = POLYLINEFILL )
type = AreaFillTool : : POLYLINE ;
else
assert ( false ) ;
m_rectFill - > onPropertyChanged ( m_frameRange . getValue ( ) , m_selective . getValue ( ) ,
m_onion . getValue ( ) , type , m_colorType . getValue ( ) ) ;
}
return true ;
}
//-----------------------------------------------------------------------------
void FillTool : : mouseMove ( const TPointD & pos , const TMouseEvent & e )
{
if ( m_fillType . getValue ( ) ! = NORMALFILL )
m_rectFill - > mouseMove ( pos , e ) ;
}
//-----------------------------------------------------------------------------
void FillTool : : onImageChanged ( )
{
if ( m_fillType . getValue ( ) ! = NORMALFILL ) {
m_rectFill - > onImageChanged ( ) ;
return ;
}
if ( ! m_level )
resetMulti ( ) ;
}
//-----------------------------------------------------------------------------
void FillTool : : draw ( )
{
if ( Preferences : : instance ( ) - > getFillOnlySavebox ( ) ) {
TToonzImageP ti = ( TToonzImageP ) getImage ( false ) ;
if ( ti ) {
TRectD bbox = ToonzImageUtils : : convertRasterToWorld ( convert ( ti - > getBBox ( ) ) , ti ) ;
drawRect ( bbox . enlarge ( 0.5 ) * ti - > getSubsampling ( ) , TPixel32 : : Black , 0x5555 , true ) ;
}
}
if ( m_fillType . getValue ( ) ! = NORMALFILL ) {
m_rectFill - > draw ( ) ;
return ;
}
if ( m_frameRange . getValue ( ) & & m_firstClick ) {
tglColor ( TPixel : : Red ) ;
drawCross ( m_firstPoint , 6 ) ;
} else if ( ! m_frameRange . getValue ( ) & & getFillParameters ( ) . m_fillType = = LINES & & m_targetType = = TTool : : ToonzImage )
m_normalLineFillTool - > draw ( ) ;
}
//-----------------------------------------------------------------------------
int FillTool : : pick ( const TImageP & image , const TPointD & pos )
{
TToonzImageP ti = image ;
TVectorImageP vi = image ;
if ( ! ti & & ! vi )
return 0 ;
StylePicker picker ( image ) ;
double pixelSize2 = getPixelSize ( ) * getPixelSize ( ) ;
return picker . pickStyleId ( pos , pixelSize2 ) ;
}
//-----------------------------------------------------------------------------
int FillTool : : pickOnionColor ( const TPointD & pos )
{
TTool : : Application * app = TTool : : getApplication ( ) ;
if ( ! app )
return 0 ;
bool filmStripEditing = ! app - > getCurrentObject ( ) - > isSpline ( ) ;
OnionSkinMask osMask = app - > getCurrentOnionSkin ( ) - > getOnionSkinMask ( ) ;
TFrameId fid = getCurrentFid ( ) ;
TXshSimpleLevel * sl = m_level . getPointer ( ) ;
if ( ! sl )
return 0 ;
std : : vector < int > rows ;
osMask . getAll ( sl - > guessIndex ( fid ) , rows ) ;
int i , j ;
for ( i = 0 ; i < ( int ) rows . size ( ) ; i + + )
if ( sl - > index2fid ( rows [ i ] ) > fid )
break ;
int onionStyleId = 0 ;
for ( j = i - 1 ; j > = 0 ; j - - ) {
TFrameId onionFid = sl - > index2fid ( rows [ j ] ) ;
if ( onionFid ! = fid & & ( ( onionStyleId = pick ( m_level - > getFrame ( onionFid , ImageManager : : none , 1 ) , pos ) ) > 0 ) ) //subsabling must be 1, otherwise onionfill does not work
break ;
}
if ( onionStyleId = = 0 )
for ( j = i ; j < ( int ) rows . size ( ) ; j + + ) {
TFrameId onionFid = sl - > index2fid ( rows [ j ] ) ;
if ( onionFid ! = fid & & ( ( onionStyleId = pick ( m_level - > getFrame ( onionFid , ImageManager : : none , 1 ) , pos ) ) > 0 ) ) //subsabling must be 1, otherwise onionfill does not work
break ;
}
return onionStyleId ;
}
//-----------------------------------------------------------------------------
void FillTool : : onEnter ( )
{
//resetMulti();
// getApplication()->editImage();
}
//-----------------------------------------------------------------------------
void FillTool : : onActivate ( )
{
//OnionSkinMask osMask = getApplication()->getOnionSkinMask(false);
/*
for ( int i = 0 ; i < osMask . getMosCount ( ) ; i + + )
boh = osMask . getMos ( i ) ;
for ( i = 0 ; i < osMask . getFosCount ( ) ; i + + )
boh = osMask . getFos ( i ) ;
*/
if ( m_firstTime ) {
m_fillDepth . setValue ( TDoublePairProperty : : Value ( MinFillDepth , MaxFillDepth ) ) ;
m_fillType . setValue ( toWideString ( ( FillType . getValue ( ) ) ) ) ;
m_colorType . setValue ( toWideString ( ( FillColorType . getValue ( ) ) ) ) ;
// m_onlyEmpty.setValue(FillSelective ? 1 :0);
m_onion . setValue ( FillOnion ? 1 : 0 ) ;
m_segment . setValue ( FillSegment ? 1 : 0 ) ;
m_frameRange . setValue ( FillRange ? 1 : 0 ) ;
m_firstTime = false ;
if ( m_fillType . getValue ( ) ! = NORMALFILL ) {
AreaFillTool : : Type type ;
if ( m_fillType . getValue ( ) = = RECTFILL )
type = AreaFillTool : : RECT ;
else if ( m_fillType . getValue ( ) = = FREEHANDFILL )
type = AreaFillTool : : FREEHAND ;
else if ( m_fillType . getValue ( ) = = POLYLINEFILL )
type = AreaFillTool : : POLYLINE ;
else
assert ( false ) ;
m_rectFill - > onPropertyChanged ( m_frameRange . getValue ( ) , m_selective . getValue ( ) , m_onion . getValue ( ) ,
type , m_colorType . getValue ( ) ) ;
}
}
if ( m_fillType . getValue ( ) ! = NORMALFILL ) {
m_rectFill - > onActivate ( ) ;
return ;
}
if ( FillColorType . getValue ( ) = = " Lines " )
m_normalLineFillTool - > init ( ) ;
resetMulti ( ) ;
// getApplication()->editImage();
TVectorImageP vi = TImageP ( getImage ( false ) ) ;
if ( ! vi )
return ;
vi - > findRegions ( ) ;
}
//-----------------------------------------------------------------------------
void FillTool : : onDeactivate ( )
{
}
//-----------------------------------------------------------------------------
FillTool FillVectorTool ( TTool : : VectorImage ) ;
FillTool FiilRasterTool ( TTool : : ToonzImage ) ;