2016-03-19 06:57:51 +13:00
# include "toonzqt/swatchviewer.h"
# include "toonzqt/gutil.h"
# include <QPainter>
# include <QMouseEvent>
# include <QResizeEvent>
# include "trasterfx.h"
# include "toonz/tcolumnfx.h"
# include "tparamcontainer.h"
# include "tfxutil.h"
//Rendering cache management includes
# include "tfxcachemanager.h"
# include "tcacheresourcepool.h"
# include "tpassivecachemanager.h"
# include <QEventLoop>
# include <QCoreApplication>
using namespace TFxUtil ;
//#define USE_SQLITE_HDPOOL
//*************************************************************************************
// Swatch cache delegate
//*************************************************************************************
/*!
The swatch cache delegate is used to temporary store intermediate rendering results
in cache when an fx is being edited .
Input fxs of an edited fx are typically requested to produce the same results multiple times
as parameters of their schematic parent change - so , caching these results is a remunerative
practice as long as the fx is open for edit .
This delegate stores resources on two different levels : one is directly related to swatch rendering ,
while the other is used to cache results on the other rendering contexts .
In the swatch case , we store the above mentioned input results associated with the current scene
scale , releasing them when the scene scale changes ; plus , the resource associated with the current
output is also stored .
In other rendering contexts , the scene scale can be assumed constant - so the above distinction
is unnecessary . All results from the input fxs are stored until the edited fx is unset from the swatch .
Please observe that variations in the scene context - such as frame change , schematic changes , scene changes
and so on - actually cause the fx to be re - set for edit in the swatch . Once this happens , the previously
stored results are conveniently flushed from the cache .
*/
/*NOTE: This can be extended in case we realize multiple swatch viewers... It should be sufficient to map
a swatch pointer to its associated cache data - the advantage being that cache resources are shared at the
same scene zoom . */
class SwatchCacheManager : public TFxCacheManagerDelegate
{
T_RENDER_RESOURCE_MANAGER
unsigned long m_setFxId ;
std : : set < unsigned long > m_childrenFxIds ;
std : : set < TCacheResourceP > m_genericCacheContainer ;
std : : set < TCacheResourceP > m_swatchCacheContainer ;
TCacheResourceP m_currEditedFxResult ;
QMutex m_mutex ;
public :
SwatchCacheManager ( ) { }
~ SwatchCacheManager ( ) { }
static SwatchCacheManager * instance ( ) ;
void setFx ( const TFxP & actualFx ) ;
void clearSwatchResults ( ) ;
void getResource (
2016-04-19 19:32:17 +12:00
TCacheResourceP & resource , const std : : string & alias ,
2016-03-19 06:57:51 +13:00
const TFxP & fx , double frame , const TRenderSettings & rs ,
ResourceDeclaration * resData ) ;
//void onRenderInstanceStart(unsigned long renderId);
//void onRenderInstanceEnd(unsigned long renderId);
bool renderHasOwnership ( ) { return false ; }
} ;
//*****************************************************************************************
// Manager generator
//*****************************************************************************************
class SwatchCacheManagerGenerator : public TRenderResourceManagerGenerator
{
TRenderResourceManager * operator ( ) ( void )
{
//return new TPassiveCacheManager;
return SwatchCacheManager : : instance ( ) ;
}
} ;
MANAGER_FILESCOPE_DECLARATION_DEP (
SwatchCacheManager ,
SwatchCacheManagerGenerator ,
TFxCacheManager : : deps ( ) )
//=============================================================================
namespace
{
//-----------------------------------------------------------------------------
//!Abilita o disabilita la cache nell'effetto \b fx di \b frame in funzione di \b on
void setFxForCaching ( TFx * fx )
{
SwatchCacheManager : : instance ( ) - > setFx ( fx ) ;
TPassiveCacheManager : : instance ( ) - > releaseContextNamesWithPrefix ( " S " ) ;
}
//-----------------------------------------------------------------------------
//!Se name finisce con suffix ritorna la parte iniziale, altrimenti ""
2016-04-19 19:32:17 +12:00
std : : string matchSuffix ( std : : string name , std : : string suffix )
2016-03-19 06:57:51 +13:00
{
if ( name . length ( ) < = suffix . length ( ) )
return " " ;
int i = name . length ( ) - suffix . length ( ) ;
if ( name . substr ( i ) = = suffix )
return name . substr ( 0 , i ) ;
else
return " " ;
}
//-----------------------------------------------------------------------------
TRaster32P createCrossIcon ( )
{
TRaster32P crossIcon = TRaster32P ( 7 , 7 ) ;
//m_crossIcon e' utilizzata per evidenziare gli eventuali \b Point memorizzati in \b m_points.
crossIcon - > fill ( TPixel32 ( 0 , 0 , 0 , 0 ) ) ;
TPixel32 * c = crossIcon - > pixels ( 3 ) + 3 ;
for ( int i = 1 ; i < = 3 ; i + + )
c [ i ] = c [ - i ] = c [ 7 * i ] = c [ - 7 * i ] =
( i & 1 ) = = 0 ? TPixel32 : : White : TPixel32 : : Red ;
return crossIcon ;
}
//-----------------------------------------------------------------------------
//!Disegna una freccia lunga \b len pixel.
/*!La punta della freccia si trova a coordinate (0,ly/2), la coda a (len-1,ly/2).
*/
TRaster32P createArrowShape ( int len )
{
int d = 5 ;
if ( len < d )
len = d ;
TPixel32 c0 ( 210 , 210 , 210 ) ;
TPixel32 c1 ( 10 , 10 , 10 ) ;
TRaster32P ras ( len , d * 2 + 1 ) ;
ras - > clear ( ) ;
ras - > lock ( ) ;
TPixel32 * pix = ras - > pixels ( d ) ;
int x = 0 ;
for ( x = 0 ; x < len ; x + + )
pix [ x ] = ( x & 8 ) = = 0 ? c0 : c1 ;
for ( x = 1 ; x < d ; x + + )
for ( int y = - x ; y < x ; y + + ) {
assert ( ras - > getBounds ( ) . contains ( TPoint ( x , y + d ) ) ) ;
pix [ len * y + x ] = c0 ;
}
ras - > unlock ( ) ;
return ras ;
}
//-----------------------------------------------------------------------------
// Preso da sceneViewer.cpp quando si spostera' lo SceneViewer in toonzqt mettere
// il codice in comune!
# define ZOOMLEVELS 30
# define NOZOOMINDEX 20
double ZoomFactors [ ZOOMLEVELS ] = { 0.001 , 0.002 , 0.003 , 0.004 , 0.005 , 0.007 ,
0.01 , 0.015 , 0.02 , 0.03 , 0.04 , 0.05 ,
0.0625 , 0.0833 , 0.125 , 0.167 , 0.25 , 0.333 ,
0.5 , 0.667 , 1 , 2 , 3 , 4 ,
5 , 6 , 7 , 8 , 12 , 16 } ;
double getQuantizedZoomFactor ( double zf , bool forward )
{
if ( forward & & zf > ZoomFactors [ ZOOMLEVELS - 1 ] | |
areAlmostEqual ( zf , ZoomFactors [ ZOOMLEVELS - 1 ] , 1e-5 ) )
return zf ;
else if ( ! forward & & zf < ZoomFactors [ 0 ] | |
areAlmostEqual ( zf , ZoomFactors [ 0 ] , 1e-5 ) )
return zf ;
assert ( ( ! forward & & zf > ZoomFactors [ 0 ] ) | | ( forward & & zf < ZoomFactors [ ZOOMLEVELS - 1 ] ) ) ;
int i = 0 ;
for ( i = 0 ; i < = ZOOMLEVELS - 1 ; i + + )
if ( areAlmostEqual ( zf , ZoomFactors [ i ] , 1e-5 ) )
zf = ZoomFactors [ i ] ;
if ( forward & & zf < ZoomFactors [ 0 ] )
return ZoomFactors [ 0 ] ;
else if ( ! forward & & zf > ZoomFactors [ ZOOMLEVELS - 1 ] )
return ZoomFactors [ ZOOMLEVELS - 1 ] ;
for ( i = 0 ; i < ZOOMLEVELS - 1 ; i + + )
if ( ZoomFactors [ i + 1 ] - zf > = 0 & & zf - ZoomFactors [ i ] > = 0 ) {
if ( forward & & ZoomFactors [ i + 1 ] = = zf )
return ZoomFactors [ i + 2 ] ;
else if ( ! forward & & ZoomFactors [ i ] = = zf )
return ZoomFactors [ i - 1 ] ;
else
return forward ? ZoomFactors [ i + 1 ] : ZoomFactors [ i ] ;
}
return ZoomFactors [ NOZOOMINDEX ] ;
}
//-----------------------------------------------------------------------------
bool suspendedRendering = false ; //Global vars for swatch rendering suspension
QEventLoop * waitingLoop = 0 ;
int submittedTasks = 0 ;
//-----------------------------------------------------------------------------
} // namespace
//=============================================================================
//=============================================================================
// SwatchViewer
//-----------------------------------------------------------------------------
# if QT_VERSION >= 0x050500
SwatchViewer : : SwatchViewer ( QWidget * parent , Qt : : WindowFlags flags )
# else
SwatchViewer : : SwatchViewer ( QWidget * parent , Qt : : WFlags flags )
# endif
: QWidget ( parent , flags ) , m_fx ( 0 ) , m_actualFxClone ( 0 ) , m_mouseButton ( Qt : : NoButton ) , m_selectedPoint ( 0 ) , m_pointPosDelta ( TPointD ( ) ) , m_enabled ( false ) , m_content ( ) , m_aff ( TAffine ( ) ) , m_fxAff ( TAffine ( ) ) , m_cameraRect ( ) , m_bgPainter ( 0 ) , m_pos ( TPoint ( ) ) , m_firstPos ( TPoint ( ) ) , m_oldContent ( ) , m_curContent ( ) , m_executor ( )
{
//setMinimumSize(150,150);
setMinimumHeight ( 150 ) ;
setFixedWidth ( 150 ) ;
setSizePolicy ( QSizePolicy : : MinimumExpanding , QSizePolicy : : MinimumExpanding ) ;
m_raster = TRaster32P ( width ( ) , height ( ) ) ;
m_crossIcon = createCrossIcon ( ) ;
setFocusPolicy ( Qt : : StrongFocus ) ;
m_executor . setDedicatedThreads ( true ) ;
m_executor . setMaxActiveTasks ( 1 ) ;
m_renderer . enablePrecomputing ( false ) ;
}
//-----------------------------------------------------------------------------
SwatchViewer : : ~ SwatchViewer ( )
{
}
//-----------------------------------------------------------------------------
//!This static method is used to temporarily suspend all swatch-related render
//!processing, typically because the rendering scene is being deleted.
//!When a suspension is invoked, all further rendering requests made to
//!swatch viewers are silently rejected, while currently active or scheduled ones
//!are canceled and waited for completion.
void SwatchViewer : : suspendRendering ( bool suspend , bool blocking )
{
suspendedRendering = suspend ;
if ( suspend & & submittedTasks > 0 & & blocking ) {
QEventLoop loop ;
waitingLoop = & loop ;
loop . exec ( ) ;
waitingLoop = 0 ;
}
}
//-----------------------------------------------------------------------------
void SwatchViewer : : setCameraSize ( const TDimension & cameraSize )
{
TRect cameraRect ( cameraSize ) ;
if ( cameraRect ! = m_cameraRect ) {
m_cameraRect = cameraRect ;
updateSize ( size ( ) ) ; //Invoke a size update to adapt the widget to the new camera ratio
}
}
//-----------------------------------------------------------------------------
void SwatchViewer : : setFx ( const TFxP & fx , const TFxP & actualFx , int frame )
{
m_fx = m_actualFxClone = fx ;
m_frame = frame ;
m_points . clear ( ) ;
m_pointPairs . clear ( ) ;
if ( ! fx ) {
: : setFxForCaching ( 0 ) ;
computeContent ( ) ;
return ;
}
// abilita la cache nel nuovo effetto corrente
: : setFxForCaching ( actualFx . getPointer ( ) ) ;
if ( NaAffineFx * affFx = dynamic_cast < NaAffineFx * > ( m_fx . getPointer ( ) ) )
m_fxAff = affFx - > getPlacement ( m_frame ) ;
else
m_fxAff = TAffine ( ) ;
int i ;
for ( i = 0 ; i < actualFx - > getParams ( ) - > getParamCount ( ) ; i + + ) {
TPointParam * pointParam =
dynamic_cast < TPointParam * > ( actualFx - > getParams ( ) - > getParam ( i ) ) ;
if ( pointParam )
m_points . push_back ( Point ( i , pointParam ) ) ;
}
// cerco i segmenti
int n = m_points . size ( ) ;
for ( i = 0 ; i < n ; i + + ) {
2016-04-19 19:32:17 +12:00
std : : string name = m_points [ i ] . m_param - > getName ( ) ;
std : : string prefix = matchSuffix ( name , " _a " ) ;
2016-03-19 06:57:51 +13:00
if ( prefix = = " " )
continue ;
2016-04-19 19:32:17 +12:00
std : : string otherName = prefix + " _b " ;
2016-03-19 06:57:51 +13:00
int j ;
for ( j = 0 ; j < n ; j + + )
if ( i ! = j & & m_points [ j ] . m_param - > getName ( ) = = otherName )
break ;
if ( j < n ) {
m_pointPairs . push_back ( std : : make_pair ( i , j ) ) ;
m_points [ i ] . m_pairFlag = m_points [ j ] . m_pairFlag = true ;
}
}
computeContent ( ) ;
}
//-----------------------------------------------------------------------------
void SwatchViewer : : updateFrame ( int frame )
{
m_frame = frame ;
computeContent ( ) ;
update ( ) ;
}
//-----------------------------------------------------------------------------
void SwatchViewer : : setEnable ( bool enabled )
{
if ( m_enabled = = enabled )
return ;
m_enabled = enabled ;
if ( m_enabled )
computeContent ( ) ;
else
update ( ) ;
}
//-----------------------------------------------------------------------------
void SwatchViewer : : updateSize ( const QSize & size )
{
int h = size . height ( ) ;
double ratio = m_cameraRect . getLy ( ) > 0 ? m_cameraRect . getLx ( ) / ( double ) m_cameraRect . getLy ( ) : 1.0 ;
int w = tmin ( ( int ) ( h * ratio ) , parentWidget ( ) - > width ( ) ) ;
setFixedWidth ( w ) ;
if ( w > 2 & & h > 2 )
m_raster = TRaster32P ( TDimension ( w , h ) ) ;
else
m_raster = TRaster32P ( ) ;
}
//-----------------------------------------------------------------------------
void SwatchViewer : : setBgPainter ( TPixel32 color1 , TPixel32 color2 )
{
if ( color2 = = TPixel32 ( ) )
m_bgPainter = new SolidColorBgPainter ( " " , color1 ) ;
else
m_bgPainter = new CheckboardBgPainter ( " " , color1 , color2 ) ;
updateRaster ( ) ;
}
//-----------------------------------------------------------------------------
TPoint SwatchViewer : : world2win ( const TPointD & p ) const
{
TPointD center ( width ( ) * 0.5 , height ( ) * 0.5 ) ;
return convert ( m_aff * m_fxAff * p + center ) ;
}
//-----------------------------------------------------------------------------
TPointD SwatchViewer : : win2world ( const TPoint & p ) const
{
TPointD center ( width ( ) * 0.5 , height ( ) * 0.5 ) ;
TPointD point = TPointD ( convert ( p ) - center ) ;
return m_fxAff . inv ( ) * m_aff . inv ( ) * TPointD ( point . x , - point . y ) ;
}
//-----------------------------------------------------------------------------
void SwatchViewer : : zoom ( const TPoint & pos , double factor )
{
if ( ! m_content | | factor = = 1.0 )
return ;
TPointD delta = convert ( pos ) ;
double scale = m_aff . det ( ) ;
TAffine aff ;
if ( ( scale < 2000 | | factor < 1 ) & & ( scale > 0.004 | | factor > 1 ) ) {
aff = TTranslation ( delta ) * TScale ( factor ) * TTranslation ( - delta ) ;
setAff ( aff * m_aff ) ;
}
}
//-----------------------------------------------------------------------------
void SwatchViewer : : zoom ( bool forward , bool reset )
{
double scale2 = m_aff . det ( ) ;
if ( reset | | ( ( scale2 < 2000 | | ! forward ) & & ( scale2 > 0.004 | | forward ) ) ) {
double oldZoomScale = sqrt ( scale2 ) ;
double zoomScale = reset ? 1 : getQuantizedZoomFactor ( oldZoomScale , forward ) ;
TAffine aff = TScale ( zoomScale / oldZoomScale ) ;
setAff ( aff * m_aff ) ;
}
}
//-----------------------------------------------------------------------------
void SwatchViewer : : computeContent ( )
{
if ( suspendedRendering )
return ;
if ( ! m_enabled )
return ;
if ( ! m_raster )
return ;
//Clear the swatch cache when the zoom scale has changed (cache results are not compatible
//between different scale levels)
if ( m_aff . a11 ! = m_contentAff . a11 )
SwatchCacheManager : : instance ( ) - > clearSwatchResults ( ) ;
TRect rect ( 0 , 0 , width ( ) - 1 , height ( ) - 1 ) ;
TDimension size = rect . getSize ( ) ;
assert ( m_raster - > getSize ( ) = = size ) ;
if ( m_fx ) {
//TFxP fx = makeAffine(m_fx, m_aff);
//TRasterFxP rasterFx = fx;
TRasterFxP rasterFx = m_fx ;
if ( rasterFx ) {
m_executor . cancelAll ( ) ;
m_executor . addTask ( new ContentRender ( rasterFx . getPointer ( ) , m_frame , size , this ) ) ;
submittedTasks + + ;
return ;
} else {
m_content = TRaster32P ( size ) ;
m_content - > fill ( TPixel32 : : Red ) ;
}
} else {
m_content = TRaster32P ( size ) ;
m_content - > fill ( TPixel32 : : Transparent ) ;
}
updateRaster ( ) ;
}
//-----------------------------------------------------------------------------
void SwatchViewer : : updateRaster ( )
{
QMutexLocker sl ( & m_mutex ) ;
if ( ! m_enabled )
return ;
if ( ! m_raster )
return ;
if ( m_bgPainter )
m_bgPainter - > paint ( m_raster ) ;
else
m_raster - > fill ( TPixel32 ( 127 , 127 , 127 ) ) ;
if ( m_cameraMode & & ! m_cameraRect . isEmpty ( ) ) {
TPointD p0 ( m_cameraRect . x0 , m_cameraRect . y0 ) ;
TPointD p1 ( m_cameraRect . x1 , m_cameraRect . y1 ) ;
TPointD center ( width ( ) * 0.5 , height ( ) * 0.5 ) ;
TPoint transP0 = convert ( m_aff * p0 + center ) ;
TPoint transP1 = convert ( m_aff * p1 + center ) ;
TPoint p = convert ( ( TPointD ( transP1 . x , transP1 . y ) - TPointD ( transP0 . x , transP0 . y ) ) * 0.5 ) ;
TRect rect ( transP0 - p , transP1 - p ) ;
m_content - > fillOutside ( rect , TPixel32 ( 255 , 0 , 0 , 255 ) ) ;
m_content - > fillOutside ( rect . enlarge ( TDimension ( 1 , 1 ) ) , TPixel32 ( 0 , 0 , 0 , 0 ) ) ;
}
if ( m_content )
TRop : : over ( m_raster , m_content ) ;
int i ;
for ( i = 0 ; i < ( int ) m_points . size ( ) ; i + + ) {
if ( m_points [ i ] . m_pairFlag )
continue ;
TPoint p = world2win ( m_points [ i ] . m_param - > getValue ( m_frame ) ) ;
TRop : : over ( m_raster , m_crossIcon , p - TPoint ( 4 , 4 ) ) ;
}
for ( i = 0 ; i < ( int ) m_pointPairs . size ( ) ; i + + ) {
int i0 = m_pointPairs [ i ] . first ;
int i1 = m_pointPairs [ i ] . second ;
assert ( i0 ! = i1 ) ;
assert ( 0 < = i0 & & i0 < ( int ) m_points . size ( ) ) ;
assert ( 0 < = i1 & & i1 < ( int ) m_points . size ( ) ) ;
TPoint p0 = world2win ( m_points [ i0 ] . m_param - > getValue ( m_frame ) ) ;
TPoint p1 = world2win ( m_points [ i1 ] . m_param - > getValue ( m_frame ) ) ;
TPoint delta = p1 - p0 ;
int len = tround ( sqrt ( ( double ) ( delta * delta ) ) ) ;
double phi = 0 ;
if ( len > 0 )
phi = 180 * atan2 ( ( double ) delta . y , ( double ) delta . x ) / TConsts : : pi ;
if ( len > 500 ) {
// puo' succedere per zoom molto grandi.
// dovrei fare qualcosa, ma non so bene che cosa e non credo sia
// importantissimo
} else {
TRaster32P arrowShape = createArrowShape ( len ) ;
TAffine aff = TRotation ( phi ) . place ( 0 , arrowShape - > getLy ( ) / 2 , p0 . x , p0 . y ) ;
TRop : : over ( m_raster , arrowShape , aff ) ;
// verrebbe la tentazione di usare il filtro TRop::Bilinear (piu'veloce),
// ma la qualita' ne risente molto
}
}
update ( ) ;
}
//-----------------------------------------------------------------------------
void SwatchViewer : : setContent ( const TRaster32P & content , const TAffine & contentAff )
{
m_content = content ;
m_contentAff = contentAff ;
updateRaster ( ) ;
update ( ) ;
}
//-----------------------------------------------------------------------------
void SwatchViewer : : setAff ( const TAffine & aff )
{
m_aff = aff ;
computeContent ( ) ;
}
//-----------------------------------------------------------------------------
void SwatchViewer : : paintEvent ( QPaintEvent * event )
{
QPainter p ( this ) ;
QRect rectBox = rect ( ) ;
if ( ! m_enabled )
p . fillRect ( rectBox , QBrush ( QColor ( 120 , 120 , 120 ) ) ) ;
else {
if ( ! m_raster )
return ;
QImage image = rasterToQImage ( m_raster ) ;
p . drawImage ( rectBox , image ) ;
if ( m_computing ) {
QPen pen ;
pen . setColor ( Qt : : red ) ;
pen . setWidth ( 3 ) ;
p . setPen ( pen ) ;
p . drawRect ( rectBox . adjusted ( 0 , 0 , - 1 , - 1 ) ) ;
}
}
}
//-----------------------------------------------------------------------------
void SwatchViewer : : resizeEvent ( QResizeEvent * re )
{
int oldHeight = re - > oldSize ( ) . height ( ) ;
int newHeight = re - > size ( ) . height ( ) ;
if ( oldHeight ! = newHeight ) {
updateSize ( QSize ( newHeight , newHeight ) ) ;
computeContent ( ) ;
}
}
//-----------------------------------------------------------------------------
void SwatchViewer : : mousePressEvent ( QMouseEvent * event )
{
TPoint pos = TPoint ( event - > pos ( ) . x ( ) , event - > pos ( ) . y ( ) ) ;
m_mouseButton = event - > button ( ) ;
if ( m_mouseButton = = Qt : : LeftButton ) {
m_selectedPoint = - 1 ;
if ( m_points . empty ( ) )
return ;
TPointD p = win2world ( pos ) ;
TPointD q ;
double minDist2 = 1e6 ;
int i ;
for ( i = 0 ; i < ( int ) m_points . size ( ) ; i + + ) {
TPointD paramPoint = m_points [ i ] . m_param - > getValue ( m_frame ) ;
double d2 = tdistance2 ( p , paramPoint ) ;
if ( m_selectedPoint < 0 | | d2 < minDist2 ) {
m_selectedPoint = i ;
minDist2 = d2 ;
q = paramPoint ;
}
}
if ( m_selectedPoint > = 0 ) {
m_pointPosDelta = q - p ;
TPoint d = world2win ( p ) - world2win ( q ) ;
int dd2 = d . x * d . x + d . y * d . y ;
if ( dd2 > 400 )
m_selectedPoint = - 1 ;
else {
2016-04-19 19:32:17 +12:00
std : : string name = m_points [ m_selectedPoint ] . m_param - > getName ( ) ;
std : : string prefix = matchSuffix ( name , " _b " ) ;
2016-03-19 06:57:51 +13:00
if ( prefix ! = " " ) {
2016-04-19 19:32:17 +12:00
std : : string otherName = prefix + " _a " ;
2016-03-19 06:57:51 +13:00
int n = ( int ) m_points . size ( ) ;
int j ;
for ( j = 0 ; j < n ; j + + )
if ( i ! = j & & m_points [ j ] . m_param - > getName ( ) = = otherName )
break ;
if ( j < n ) {
TPoint dist = world2win ( m_points [ m_selectedPoint ] . m_param - > getValue ( m_frame ) ) -
world2win ( m_points [ j ] . m_param - > getValue ( m_frame ) ) ;
int ddist2 = dist . x * dist . x + dist . y * dist . y ;
if ( ddist2 < 100 )
m_selectedPoint = j ;
}
}
}
}
update ( ) ;
} else if ( m_mouseButton = = Qt : : MidButton ) {
m_pos = pos ;
m_firstPos = pos ;
m_oldContent = getContent ( ) ;
if ( m_oldContent )
m_curContent = TRaster32P ( m_oldContent - > getSize ( ) ) ;
else
m_curContent = TRaster32P ( ) ;
}
}
//-----------------------------------------------------------------------------
void SwatchViewer : : mouseMoveEvent ( QMouseEvent * event )
{
TPoint pos = TPoint ( event - > pos ( ) . x ( ) , event - > pos ( ) . y ( ) ) ;
if ( m_mouseButton = = Qt : : LeftButton ) {
if ( m_selectedPoint < 0 | | m_selectedPoint > = ( int ) m_points . size ( ) )
return ;
TPointD p = win2world ( pos ) + m_pointPosDelta ;
int index = m_points [ m_selectedPoint ] . m_index ;
emit pointPositionChanged ( index , p ) ;
//It seems that mouse move events may jeopardize our rendering notification deliveries
// - probably because Qt considers them 'higher priority stuff' with respect
//to common queued signal-slot connections.
//In order to allow processing of the ContentRender::started() and ContentRender::finished()
//signals, we need to process events. We will exclude user input events (ie other mouse events)
//to avoid unnecessary recursions.
QCoreApplication : : processEvents ( QEventLoop : : ExcludeUserInputEvents ) ;
} else if ( m_mouseButton = = Qt : : MidButton ) {
if ( ! m_oldContent | | ! m_curContent )
return ;
m_curContent - > fill ( TPixel32 : : Transparent ) ;
TPointD step = convert ( pos - m_pos ) ;
//Devo aggiornare l'affine per riposizionare la camera.
m_aff = TTranslation ( step . x , - step . y ) * m_aff ;
m_pos = pos ;
TPoint p = pos - m_firstPos ;
m_curContent - > copy ( m_oldContent , TPoint ( p . x , - p . y ) ) ;
setContent ( m_curContent , TTranslation ( step . x , - step . y ) * m_contentAff ) ;
}
}
//-----------------------------------------------------------------------------
void SwatchViewer : : mouseReleaseEvent ( QMouseEvent * event )
{
m_mouseButton = Qt : : NoButton ;
m_selectedPoint = - 1 ;
TPoint pos = TPoint ( event - > pos ( ) . x ( ) , event - > pos ( ) . y ( ) ) ;
if ( event - > button ( ) = = Qt : : MidButton ) {
if ( ! m_oldContent | | ! m_curContent )
return ;
TPointD p = convert ( pos - m_pos ) ;
setAff ( TTranslation ( p . x , - p . y ) * m_aff ) ;
update ( ) ;
}
}
//-----------------------------------------------------------------------------
void SwatchViewer : : wheelEvent ( QWheelEvent * event )
{
TPoint center ( event - > pos ( ) . x ( ) - width ( ) / 2 , - event - > pos ( ) . y ( ) + height ( ) / 2 ) ;
zoom ( center , exp ( 0.001 * event - > delta ( ) ) ) ;
}
//-----------------------------------------------------------------------------
void SwatchViewer : : keyPressEvent ( QKeyEvent * event )
{
int key = event - > key ( ) ;
if ( key = = ' + ' | | key = = ' - ' | | key = = ' 0 ' ) {
zoom ( key = = ' + ' , key = = ' 0 ' ) ;
}
}
//-----------------------------------------------------------------------------
void SwatchViewer : : hideEvent ( QHideEvent * event )
{
//Clear the swatch cache
: : setFxForCaching ( 0 ) ;
}
//=============================================================================
// SwatchViewer::ContentRender
//-----------------------------------------------------------------------------
SwatchViewer : : ContentRender : : ContentRender (
TRasterFx * fx , int frame , const TDimension & size , SwatchViewer * viewer )
: m_fx ( fx ) , m_raster ( 0 ) , m_frame ( frame ) , m_size ( size ) , m_aff ( viewer - > m_aff ) , m_viewer ( viewer ) , m_started ( false )
{
//Is there a less complicated way...?
connect ( this , SIGNAL ( started ( TThread : : RunnableP ) ) , this , SLOT ( onStarted ( TThread : : RunnableP ) ) ) ;
connect ( this , SIGNAL ( finished ( TThread : : RunnableP ) ) , this , SLOT ( onFinished ( TThread : : RunnableP ) ) ) ;
connect ( this , SIGNAL ( exception ( TThread : : RunnableP ) ) , this , SLOT ( onFinished ( TThread : : RunnableP ) ) ) ;
connect ( this , SIGNAL ( canceled ( TThread : : RunnableP ) ) , this , SLOT ( onCanceled ( TThread : : RunnableP ) ) , Qt : : QueuedConnection ) ; //Starts will need to come *strictly before* cancels
}
//-----------------------------------------------------------------------------
SwatchViewer : : ContentRender : : ~ ContentRender ( )
{
}
//-----------------------------------------------------------------------------
void SwatchViewer : : ContentRender : : run ( )
{
if ( suspendedRendering )
return ;
unsigned long renderId = TRenderer : : buildRenderId ( ) ;
TPassiveCacheManager : : instance ( ) - > setContextName ( renderId , " S " ) ;
m_viewer - > m_renderer . install ( renderId ) ;
m_viewer - > m_renderer . declareRenderStart ( renderId ) ;
m_viewer - > m_renderer . declareFrameStart ( m_frame ) ;
TRenderSettings info ;
info . m_isSwatch = true ;
info . m_affine = m_aff ;
TTile tile ;
m_fx - > allocateAndCompute ( tile , - 0.5 * TPointD ( m_size . lx , m_size . ly ) , m_size , 0 , ( double ) m_frame , info ) ;
m_raster = tile . getRaster ( ) ;
m_viewer - > m_renderer . declareFrameEnd ( m_frame ) ;
m_viewer - > m_renderer . declareRenderEnd ( renderId ) ;
m_viewer - > m_renderer . uninstall ( ) ;
}
//-----------------------------------------------------------------------------
int SwatchViewer : : ContentRender : : taskLoad ( )
{
return 100 ;
}
//-----------------------------------------------------------------------------
void SwatchViewer : : ContentRender : : onStarted ( TThread : : RunnableP task )
{
m_started = true ;
m_viewer - > m_computing = true ;
m_viewer - > update ( ) ;
}
//-----------------------------------------------------------------------------
void SwatchViewer : : ContentRender : : onFinished ( TThread : : RunnableP task )
{
m_viewer - > m_computing = false ;
m_viewer - > setContent ( m_raster , m_aff ) ;
if ( ( - - submittedTasks = = 0 ) & & waitingLoop )
waitingLoop - > quit ( ) ;
}
//-----------------------------------------------------------------------------
void SwatchViewer : : ContentRender : : onCanceled ( TThread : : RunnableP task )
{
if ( m_started )
return ;
if ( ( - - submittedTasks = = 0 ) & & waitingLoop )
waitingLoop - > quit ( ) ;
}
//*************************************************************************************
// Swatch cache manager implementation
//*************************************************************************************
SwatchCacheManager * SwatchCacheManager : : instance ( )
{
static SwatchCacheManager theInstance ;
return & theInstance ;
}
//-----------------------------------------------------------------------------
void SwatchCacheManager : : setFx ( const TFxP & fx )
{
QMutexLocker locker ( & m_mutex ) ;
//Update the fxs id data
if ( fx = = TFxP ( ) ) {
//Clear if no fx is set
m_setFxId = 0 ;
m_childrenFxIds . clear ( ) ;
} else {
m_setFxId = fx - > getIdentifier ( ) ;
m_childrenFxIds . clear ( ) ;
assert ( m_setFxId ! = 0 ) ;
TRasterFx * rfx = dynamic_cast < TRasterFx * > ( fx . getPointer ( ) ) ;
assert ( rfx ) ;
for ( int i = 0 ; i < fx - > getInputPortCount ( ) ; + + i ) {
//Fxs not allowing cache on the input port are skipped
if ( ! rfx - > allowUserCacheOnPort ( i ) )
continue ;
TFxPort * iport = fx - > getInputPort ( i ) ;
if ( iport & & iport - > isConnected ( ) ) {
TFx * child = iport - > getFx ( ) ;
//In the zerary case, extract the actual fx
TZeraryColumnFx * zcfx = dynamic_cast < TZeraryColumnFx * > ( child ) ;
if ( zcfx )
child = zcfx - > getZeraryFx ( ) ;
assert ( child & & child - > getIdentifier ( ) ! = 0 ) ;
m_childrenFxIds . insert ( child - > getIdentifier ( ) ) ;
}
}
}
//NOTE: Check if this should be avoided in some case...
//Release the locks and clear the resources
if ( m_currEditedFxResult )
m_currEditedFxResult - > releaseLock ( ) ;
m_currEditedFxResult = TCacheResourceP ( ) ;
std : : set < TCacheResourceP > : : iterator it ;
for ( it = m_swatchCacheContainer . begin ( ) ; it ! = m_swatchCacheContainer . end ( ) ; + + it )
( * it ) - > releaseLock ( ) ;
m_swatchCacheContainer . clear ( ) ;
# ifdef USE_SQLITE_HDPOOL
TCacheResourcePool : : instance ( ) - > releaseReferences ( " S " ) ;
# else
for ( it = m_genericCacheContainer . begin ( ) ; it ! = m_genericCacheContainer . end ( ) ; + + it )
( * it ) - > releaseLock ( ) ;
m_genericCacheContainer . clear ( ) ;
# endif
}
//-----------------------------------------------------------------------------
//This method is invoked by the swatch when its scene scale changes. Find it above.
void SwatchCacheManager : : clearSwatchResults ( )
{
QMutexLocker locker ( & m_mutex ) ;
if ( m_currEditedFxResult )
m_currEditedFxResult - > releaseLock ( ) ;
m_currEditedFxResult = TCacheResourceP ( ) ;
std : : set < TCacheResourceP > : : iterator it ;
for ( it = m_swatchCacheContainer . begin ( ) ; it ! = m_swatchCacheContainer . end ( ) ; + + it )
( * it ) - > releaseLock ( ) ;
m_swatchCacheContainer . clear ( ) ;
}
//-----------------------------------------------------------------------------
void SwatchCacheManager : : getResource (
2016-04-19 19:32:17 +12:00
TCacheResourceP & resource , const std : : string & alias ,
2016-03-19 06:57:51 +13:00
const TFxP & fx , double frame , const TRenderSettings & rs ,
ResourceDeclaration * resData )
{
//Only FX RESULTS are interesting - plus, avoid if we're not currently
//editing an fx.
if ( ! ( fx & & m_setFxId > 0 ) )
return ;
QMutexLocker locker ( & m_mutex ) ;
//Cache the result in case the fx's id is among the stored ones.
unsigned long fxId = fx - > getIdentifier ( ) ;
if ( fxId = = m_setFxId & & rs . m_isSwatch ) {
if ( ! resource )
resource = TCacheResourceP ( alias , true ) ;
resource - > addLock ( ) ;
if ( m_currEditedFxResult )
m_currEditedFxResult - > releaseLock ( ) ;
m_currEditedFxResult = resource ;
return ;
}
if ( m_childrenFxIds . find ( fxId ) ! = m_childrenFxIds . end ( ) ) {
if ( ! resource )
resource = TCacheResourceP ( alias , true ) ;
if ( rs . m_isSwatch ) {
std : : set < TCacheResourceP > : : iterator it =
m_swatchCacheContainer . find ( resource ) ;
if ( it = = m_swatchCacheContainer . end ( ) ) {
resource - > addLock ( ) ;
m_swatchCacheContainer . insert ( resource ) ;
}
} else {
# ifdef USE_SQLITE_HDPOOL
resource - > enableBackup ( ) ;
TCacheResourcePool : : instance ( ) - > addReference ( resource , " S " ) ;
# else
std : : set < TCacheResourceP > : : iterator it =
m_genericCacheContainer . find ( resource ) ;
if ( it = = m_genericCacheContainer . end ( ) ) {
resource - > addLock ( ) ;
m_genericCacheContainer . insert ( resource ) ;
}
# endif
}
}
}