2022-03-23 22:01:59 +01:00
# include "AnimationManager.hpp"
# include "../Compositor.hpp"
2022-04-23 21:47:16 +02:00
CAnimationManager : : CAnimationManager ( ) {
2022-04-23 21:54:03 +02:00
std : : vector < Vector2D > points = { Vector2D ( 0 , 0.75f ) , Vector2D ( 0.15f , 1.f ) } ;
2022-04-23 21:47:16 +02:00
m_mBezierCurves [ " default " ] . setup ( & points ) ;
}
void CAnimationManager : : removeAllBeziers ( ) {
m_mBezierCurves . clear ( ) ;
// add the default one
2022-04-23 21:54:03 +02:00
std : : vector < Vector2D > points = { Vector2D ( 0 , 0.75f ) , Vector2D ( 0.15f , 1.f ) } ;
2022-04-23 21:47:16 +02:00
m_mBezierCurves [ " default " ] . setup ( & points ) ;
}
void CAnimationManager : : addBezierWithName ( std : : string name , const Vector2D & p1 , const Vector2D & p2 ) {
std : : vector points = { p1 , p2 } ;
m_mBezierCurves [ name ] . setup ( & points ) ;
}
2022-03-23 22:01:59 +01:00
void CAnimationManager : : tick ( ) {
bool animationsDisabled = false ;
if ( ! g_pConfigManager - > getInt ( " animations:enabled " ) )
animationsDisabled = true ;
const float ANIMSPEED = g_pConfigManager - > getFloat ( " animations:speed " ) ;
2022-04-14 16:43:29 +02:00
const auto BORDERSIZE = g_pConfigManager - > getInt ( " general:border_size " ) ;
2022-04-23 21:47:16 +02:00
const auto BEZIERSTR = g_pConfigManager - > getString ( " animations:curve " ) ;
2022-04-14 16:43:29 +02:00
2022-04-23 21:47:16 +02:00
auto DEFAULTBEZIER = m_mBezierCurves . find ( BEZIERSTR ) ;
if ( DEFAULTBEZIER = = m_mBezierCurves . end ( ) )
DEFAULTBEZIER = m_mBezierCurves . find ( " default " ) ;
2022-04-05 20:53:16 +02:00
2022-04-23 21:47:16 +02:00
for ( auto & av : m_lAnimatedVariables ) {
2022-04-23 14:16:02 +02:00
// get speed
const auto SPEED = * av - > m_pSpeed = = 0 ? ANIMSPEED : * av - > m_pSpeed ;
2022-03-31 17:50:00 +02:00
2022-04-23 14:16:02 +02:00
// window stuff
const auto PWINDOW = ( CWindow * ) av - > m_pWindow ;
2022-05-12 11:27:31 +02:00
const auto PWORKSPACE = ( CWorkspace * ) av - > m_pWorkspace ;
2022-05-14 17:23:46 +02:00
const auto PLAYER = ( SLayerSurface * ) av - > m_pLayer ;
2022-05-12 11:27:31 +02:00
wlr_box WLRBOXPREV = { 0 , 0 , 0 , 0 } ;
if ( PWINDOW ) {
WLRBOXPREV = { ( int ) PWINDOW - > m_vRealPosition . vec ( ) . x - BORDERSIZE - 1 , ( int ) PWINDOW - > m_vRealPosition . vec ( ) . y - BORDERSIZE - 1 , ( int ) PWINDOW - > m_vRealSize . vec ( ) . x + 2 * BORDERSIZE + 2 , ( int ) PWINDOW - > m_vRealSize . vec ( ) . y + 2 * BORDERSIZE + 2 } ;
} else if ( PWORKSPACE ) {
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( PWORKSPACE - > m_iMonitorID ) ;
WLRBOXPREV = { ( int ) PMONITOR - > vecPosition . x , ( int ) PMONITOR - > vecPosition . y , ( int ) PMONITOR - > vecSize . x , ( int ) PMONITOR - > vecSize . y } ;
2022-05-14 17:23:46 +02:00
} else if ( PLAYER ) {
WLRBOXPREV = PLAYER - > geometry ;
2022-05-12 11:27:31 +02:00
}
2022-04-23 21:47:16 +02:00
// check if it's disabled, if so, warp
if ( av - > m_pEnabled = = 0 | | animationsDisabled ) {
av - > warp ( ) ;
g_pHyprRenderer - > damageBox ( & WLRBOXPREV ) ;
2022-04-27 16:34:28 +02:00
2022-05-12 11:27:31 +02:00
if ( PWINDOW ) {
g_pHyprRenderer - > damageWindow ( PWINDOW ) ;
// set size and pos if valid
if ( g_pCompositor - > windowValidMapped ( PWINDOW ) )
g_pXWaylandManager - > setWindowSize ( PWINDOW , PWINDOW - > m_vRealSize . goalv ( ) ) ;
}
2022-04-23 21:47:16 +02:00
continue ;
}
2022-04-23 14:16:02 +02:00
2022-04-23 21:47:16 +02:00
// beziers are with a switch unforto
2022-04-23 14:16:02 +02:00
// TODO: maybe do something cleaner
2022-04-23 21:47:16 +02:00
// get the spent % (0 - 1)
const auto DURATIONPASSED = std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( std : : chrono : : system_clock : : now ( ) - av - > animationBegin ) . count ( ) ;
const float SPENT = std : : clamp ( ( DURATIONPASSED / 100.f ) / SPEED , 0.f , 1.f ) ;
2022-04-23 14:16:02 +02:00
switch ( av - > m_eVarType ) {
case AVARTYPE_FLOAT : {
if ( ! deltazero ( av - > m_fValue , av - > m_fGoal ) ) {
2022-04-23 21:47:16 +02:00
const auto DELTA = av - > m_fGoal - av - > m_fBegun ;
const auto BEZIER = m_mBezierCurves . find ( * av - > m_pBezier ) ;
if ( BEZIER ! = m_mBezierCurves . end ( ) )
av - > m_fValue = av - > m_fBegun + BEZIER - > second . getYForPoint ( SPENT ) * DELTA ;
else
av - > m_fValue = av - > m_fBegun + DEFAULTBEZIER - > second . getYForPoint ( SPENT ) * DELTA ;
if ( SPENT > = 1.f ) {
2022-04-23 14:16:02 +02:00
av - > warp ( ) ;
}
2022-04-23 21:47:16 +02:00
} else {
continue ; // dont process
2022-03-31 17:50:00 +02:00
}
2022-04-23 14:16:02 +02:00
break ;
2022-03-31 17:50:00 +02:00
}
2022-04-23 14:16:02 +02:00
case AVARTYPE_VECTOR : {
if ( ! deltazero ( av - > m_vValue , av - > m_vGoal ) ) {
2022-04-23 21:47:16 +02:00
const auto DELTA = av - > m_vGoal - av - > m_vBegun ;
const auto BEZIER = m_mBezierCurves . find ( * av - > m_pBezier ) ;
if ( BEZIER ! = m_mBezierCurves . end ( ) )
av - > m_vValue = av - > m_vBegun + DELTA * BEZIER - > second . getYForPoint ( SPENT ) ;
else
av - > m_vValue = av - > m_vBegun + DELTA * DEFAULTBEZIER - > second . getYForPoint ( SPENT ) ;
if ( SPENT > = 1.f ) {
2022-04-23 14:16:02 +02:00
av - > warp ( ) ;
}
2022-04-23 21:47:16 +02:00
} else {
continue ; // dont process
2022-03-31 17:50:00 +02:00
}
2022-04-23 14:16:02 +02:00
break ;
}
case AVARTYPE_COLOR : {
if ( ! deltazero ( av - > m_cValue , av - > m_cGoal ) ) {
2022-04-23 21:47:16 +02:00
const auto DELTA = av - > m_cGoal - av - > m_cBegun ;
const auto BEZIER = m_mBezierCurves . find ( * av - > m_pBezier ) ;
if ( BEZIER ! = m_mBezierCurves . end ( ) )
av - > m_cValue = av - > m_cBegun + DELTA * BEZIER - > second . getYForPoint ( SPENT ) ;
else
av - > m_cValue = av - > m_cBegun + DELTA * DEFAULTBEZIER - > second . getYForPoint ( SPENT ) ;
if ( SPENT > = 1.f ) {
2022-04-23 14:16:02 +02:00
av - > warp ( ) ;
}
2022-04-23 21:47:16 +02:00
} else {
continue ; // dont process
2022-04-23 14:16:02 +02:00
}
break ;
2022-03-23 22:01:59 +01:00
}
2022-04-23 14:36:03 +02:00
default : {
;
}
2022-03-23 22:01:59 +01:00
}
2022-04-14 16:43:29 +02:00
2022-05-05 14:02:30 +02:00
// damage the window with the damage policy
switch ( av - > m_eDamagePolicy ) {
case AVARDAMAGE_ENTIRE : {
g_pHyprRenderer - > damageBox ( & WLRBOXPREV ) ;
2022-05-12 11:27:31 +02:00
if ( PWINDOW )
g_pHyprRenderer - > damageWindow ( PWINDOW ) ;
2022-05-05 14:02:30 +02:00
break ;
}
case AVARDAMAGE_BORDER : {
2022-05-12 11:27:31 +02:00
RASSERT ( PWINDOW , " Tried to AVARDAMAGE_BORDER a non-window AVAR! " ) ;
2022-05-05 14:02:30 +02:00
// damage only the border.
const auto BORDERSIZE = g_pConfigManager - > getInt ( " general:border_size " ) + 1 ; // +1 for padding and shit
2022-05-05 15:19:50 +02:00
const auto ROUNDINGSIZE = g_pConfigManager - > getInt ( " decoration:rounding " ) + 1 ;
2022-05-05 14:02:30 +02:00
// damage for old box
2022-05-18 12:27:43 +02:00
g_pHyprRenderer - > damageBox ( WLRBOXPREV . x - BORDERSIZE , WLRBOXPREV . y - BORDERSIZE , WLRBOXPREV . width + 2 * BORDERSIZE , BORDERSIZE + ROUNDINGSIZE ) ; // top
g_pHyprRenderer - > damageBox ( WLRBOXPREV . x - BORDERSIZE , WLRBOXPREV . y - BORDERSIZE , BORDERSIZE + ROUNDINGSIZE , WLRBOXPREV . height + 2 * BORDERSIZE ) ; // left
g_pHyprRenderer - > damageBox ( WLRBOXPREV . x + WLRBOXPREV . width - ROUNDINGSIZE , WLRBOXPREV . y - BORDERSIZE , BORDERSIZE + ROUNDINGSIZE , WLRBOXPREV . height + 2 * BORDERSIZE ) ; // right
g_pHyprRenderer - > damageBox ( WLRBOXPREV . x , WLRBOXPREV . y + WLRBOXPREV . height - ROUNDINGSIZE , WLRBOXPREV . width + 2 * BORDERSIZE , BORDERSIZE + ROUNDINGSIZE ) ; // bottom
2022-05-05 14:02:30 +02:00
// damage for new box
const wlr_box WLRBOXNEW = { PWINDOW - > m_vRealPosition . vec ( ) . x , PWINDOW - > m_vRealPosition . vec ( ) . y , PWINDOW - > m_vRealSize . vec ( ) . x , PWINDOW - > m_vRealSize . vec ( ) . y } ;
2022-05-18 12:27:43 +02:00
g_pHyprRenderer - > damageBox ( WLRBOXNEW . x - BORDERSIZE , WLRBOXNEW . y - BORDERSIZE , WLRBOXNEW . width + 2 * BORDERSIZE , BORDERSIZE + ROUNDINGSIZE ) ; // top
g_pHyprRenderer - > damageBox ( WLRBOXNEW . x - BORDERSIZE , WLRBOXNEW . y - BORDERSIZE , BORDERSIZE + ROUNDINGSIZE , WLRBOXNEW . height + 2 * BORDERSIZE ) ; // left
g_pHyprRenderer - > damageBox ( WLRBOXNEW . x + WLRBOXNEW . width - ROUNDINGSIZE , WLRBOXNEW . y - BORDERSIZE , BORDERSIZE + ROUNDINGSIZE , WLRBOXNEW . height + 2 * BORDERSIZE ) ; // right
g_pHyprRenderer - > damageBox ( WLRBOXNEW . x , WLRBOXNEW . y + WLRBOXNEW . height - ROUNDINGSIZE , WLRBOXNEW . width + 2 * BORDERSIZE , BORDERSIZE + ROUNDINGSIZE ) ; // bottom
2022-05-05 14:02:30 +02:00
break ;
}
default : {
Debug : : log ( ERR , " av has damage policy INVALID??? " ) ;
break ;
}
}
2022-04-27 16:34:28 +02:00
2022-05-05 15:16:10 +02:00
// set size and pos if valid, but only if damage policy entire (dont if border for example)
if ( g_pCompositor - > windowValidMapped ( PWINDOW ) & & av - > m_eDamagePolicy = = AVARDAMAGE_ENTIRE )
2022-04-27 16:34:28 +02:00
g_pXWaylandManager - > setWindowSize ( PWINDOW , PWINDOW - > m_vRealSize . goalv ( ) ) ;
2022-03-23 22:01:59 +01:00
}
}
bool CAnimationManager : : deltaSmallToFlip ( const Vector2D & a , const Vector2D & b ) {
return std : : abs ( a . x - b . x ) < 0.5f & & std : : abs ( a . y - b . y ) < 0.5f ;
}
2022-03-31 17:50:00 +02:00
bool CAnimationManager : : deltaSmallToFlip ( const CColor & a , const CColor & b ) {
return std : : abs ( a . r - b . r ) < 0.5f & & std : : abs ( a . g - b . g ) < 0.5f & & std : : abs ( a . b - b . b ) < 0.5f & & std : : abs ( a . a - b . a ) < 0.5f ;
}
2022-04-14 16:43:29 +02:00
bool CAnimationManager : : deltaSmallToFlip ( const float & a , const float & b ) {
return std : : abs ( a - b ) < 0.5f ;
}
2022-03-23 22:01:59 +01:00
bool CAnimationManager : : deltazero ( const Vector2D & a , const Vector2D & b ) {
return a . x = = b . x & & a . y = = b . y ;
}
2022-04-14 16:43:29 +02:00
bool CAnimationManager : : deltazero ( const float & a , const float & b ) {
return a = = b ;
}
2022-03-31 17:50:00 +02:00
bool CAnimationManager : : deltazero ( const CColor & a , const CColor & b ) {
return a . r = = b . r & & a . g = = b . g & & a . b = = b . b & & a . a = = b . a ;
2022-05-14 16:43:30 +02:00
}
2022-05-15 14:18:31 +02:00
//
// Anims
//
//
2022-05-14 16:43:30 +02:00
2022-05-28 18:28:55 +02:00
void CAnimationManager : : animationPopin ( CWindow * pWindow , bool close ) {
2022-05-15 14:18:31 +02:00
const auto GOALPOS = pWindow - > m_vRealPosition . goalv ( ) ;
const auto GOALSIZE = pWindow - > m_vRealSize . goalv ( ) ;
2022-05-14 16:43:30 +02:00
2022-05-28 18:28:55 +02:00
if ( ! close ) {
pWindow - > m_vRealPosition . setValue ( GOALPOS + GOALSIZE / 2.f ) ;
pWindow - > m_vRealSize . setValue ( Vector2D ( 5 , 5 ) ) ;
} else {
pWindow - > m_vRealPosition = GOALPOS + GOALSIZE / 2.f ;
pWindow - > m_vRealSize = Vector2D ( 5 , 5 ) ;
}
2022-05-15 14:18:31 +02:00
}
2022-05-28 18:28:55 +02:00
void CAnimationManager : : animationSlide ( CWindow * pWindow , std : : string force , bool close ) {
2022-05-15 14:18:31 +02:00
pWindow - > m_vRealSize . warp ( ) ; // size we preserve in slide
2022-05-14 16:43:30 +02:00
const auto GOALPOS = pWindow - > m_vRealPosition . goalv ( ) ;
const auto GOALSIZE = pWindow - > m_vRealSize . goalv ( ) ;
2022-05-15 14:18:31 +02:00
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( pWindow - > m_iMonitorID ) ;
2022-05-28 18:28:55 +02:00
Vector2D posOffset ;
2022-05-15 14:18:31 +02:00
if ( force ! = " " ) {
2022-05-28 18:28:55 +02:00
if ( force = = " bottom " ) posOffset = Vector2D ( GOALPOS . x , PMONITOR - > vecPosition . y + PMONITOR - > vecSize . y ) ;
else if ( force = = " left " ) posOffset = GOALPOS - Vector2D ( GOALSIZE . x , 0 ) ;
else if ( force = = " right " ) posOffset = GOALPOS + Vector2D ( GOALSIZE . x , 0 ) ;
else posOffset = Vector2D ( GOALPOS . x , PMONITOR - > vecPosition . y - GOALSIZE . y ) ;
if ( ! close )
pWindow - > m_vRealPosition . setValue ( posOffset ) ;
else
pWindow - > m_vRealPosition = posOffset ;
2022-05-15 14:18:31 +02:00
return ;
}
const auto MIDPOINT = GOALPOS + GOALSIZE / 2.f ;
// check sides it touches
const bool DISPLAYLEFT = STICKS ( pWindow - > m_vPosition . x , PMONITOR - > vecPosition . x + PMONITOR - > vecReservedTopLeft . x ) ;
const bool DISPLAYRIGHT = STICKS ( pWindow - > m_vPosition . x + pWindow - > m_vSize . x , PMONITOR - > vecPosition . x + PMONITOR - > vecSize . x - PMONITOR - > vecReservedBottomRight . x ) ;
const bool DISPLAYTOP = STICKS ( pWindow - > m_vPosition . y , PMONITOR - > vecPosition . y + PMONITOR - > vecReservedTopLeft . y ) ;
const bool DISPLAYBOTTOM = STICKS ( pWindow - > m_vPosition . y + pWindow - > m_vSize . y , PMONITOR - > vecPosition . y + PMONITOR - > vecSize . y - PMONITOR - > vecReservedBottomRight . y ) ;
2022-05-14 16:43:30 +02:00
2022-05-15 14:18:31 +02:00
if ( DISPLAYBOTTOM & & DISPLAYTOP ) {
if ( DISPLAYLEFT & & DISPLAYRIGHT ) {
2022-05-28 18:28:55 +02:00
posOffset = GOALPOS + Vector2D ( 0 , GOALSIZE . y ) ;
2022-05-15 14:18:31 +02:00
} else if ( DISPLAYLEFT ) {
2022-05-28 18:28:55 +02:00
posOffset = GOALPOS - Vector2D ( GOALSIZE . x , 0 ) ;
2022-05-15 14:18:31 +02:00
} else {
2022-05-28 18:28:55 +02:00
posOffset = GOALPOS + Vector2D ( GOALSIZE . x , 0 ) ;
2022-05-15 14:18:31 +02:00
}
} else if ( DISPLAYTOP ) {
2022-05-28 18:28:55 +02:00
posOffset = GOALPOS - Vector2D ( 0 , GOALSIZE . y ) ;
2022-05-15 14:18:31 +02:00
} else if ( DISPLAYBOTTOM ) {
2022-05-28 18:28:55 +02:00
posOffset = GOALPOS + Vector2D ( 0 , GOALSIZE . y ) ;
2022-05-15 14:18:31 +02:00
} else {
if ( MIDPOINT . y > PMONITOR - > vecPosition . y + PMONITOR - > vecSize . y / 2.f )
2022-05-28 18:28:55 +02:00
posOffset = Vector2D ( GOALPOS . x , PMONITOR - > vecPosition . y + PMONITOR - > vecSize . y ) ;
2022-05-15 14:18:31 +02:00
else
2022-05-28 18:28:55 +02:00
posOffset = Vector2D ( GOALPOS . x , PMONITOR - > vecPosition . y - GOALSIZE . y ) ;
2022-05-15 14:18:31 +02:00
}
2022-05-28 18:28:55 +02:00
if ( ! close )
pWindow - > m_vRealPosition . setValue ( posOffset ) ;
else
pWindow - > m_vRealPosition = posOffset ;
2022-05-15 14:18:31 +02:00
}
2022-05-28 18:28:55 +02:00
void CAnimationManager : : onWindowPostCreateClose ( CWindow * pWindow , bool close ) {
2022-05-15 14:18:31 +02:00
auto ANIMSTYLE = g_pConfigManager - > getString ( " animations:windows_style " ) ;
transform ( ANIMSTYLE . begin ( ) , ANIMSTYLE . end ( ) , ANIMSTYLE . begin ( ) , : : tolower ) ;
2022-05-14 16:43:30 +02:00
2022-05-15 14:18:31 +02:00
// if the window is not being animated, that means the layout set a fixed size for it, don't animate.
if ( ! pWindow - > m_vRealPosition . isBeingAnimated ( ) & & ! pWindow - > m_vRealSize . isBeingAnimated ( ) )
return ;
2022-05-14 16:43:30 +02:00
2022-05-15 14:18:31 +02:00
if ( pWindow - > m_sAdditionalConfigData . animationStyle ! = " " ) {
// the window has config'd special anim
if ( pWindow - > m_sAdditionalConfigData . animationStyle . find ( " slide " ) = = 0 ) {
if ( pWindow - > m_sAdditionalConfigData . animationStyle . find ( ' ' ) ! = std : : string : : npos ) {
// has a direction
2022-05-28 18:28:55 +02:00
animationSlide ( pWindow , pWindow - > m_sAdditionalConfigData . animationStyle . substr ( pWindow - > m_sAdditionalConfigData . animationStyle . find ( ' ' ) + 1 ) , close ) ;
2022-05-14 16:43:30 +02:00
} else {
2022-05-28 18:28:55 +02:00
animationSlide ( pWindow , " " , close ) ;
2022-05-14 16:43:30 +02:00
}
} else {
2022-05-15 14:18:31 +02:00
// anim popin, fallback
2022-05-28 18:28:55 +02:00
animationPopin ( pWindow , close ) ;
2022-05-14 16:43:30 +02:00
}
} else {
2022-05-15 14:18:31 +02:00
if ( ANIMSTYLE = = " slide " ) {
2022-05-28 18:28:55 +02:00
animationSlide ( pWindow , " " , close ) ;
2022-05-15 14:18:31 +02:00
} else {
// anim popin, fallback
2022-05-28 18:28:55 +02:00
animationPopin ( pWindow , close ) ;
2022-05-15 14:18:31 +02:00
}
2022-05-14 16:43:30 +02:00
}
2022-03-23 22:01:59 +01:00
}