summaryrefslogtreecommitdiff
path: root/src/managers/AnimationManager.cpp
blob: f77c3d7cfa3bb8b1165cf5abb4d5d295359a0477 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#include "AnimationManager.hpp"
#include "../Compositor.hpp"

void CAnimationManager::tick() {

    bool animationsDisabled = false;

    if (!g_pConfigManager->getInt("animations:enabled"))
        animationsDisabled = true;

    const bool WINDOWSENABLED   = g_pConfigManager->getInt("animations:windows") && !animationsDisabled;
    const bool BORDERSENABLED   = g_pConfigManager->getInt("animations:borders") && !animationsDisabled;
    const bool FADEENABLED      = g_pConfigManager->getInt("animations:fadein") && !animationsDisabled;
    const float ANIMSPEED       = g_pConfigManager->getFloat("animations:speed");

    // Process speeds
    const float WINDOWSPEED     = g_pConfigManager->getFloat("animations:windows_speed") == 0 ? ANIMSPEED : g_pConfigManager->getFloat("animations:windows_speed");
    const float BORDERSPEED     = g_pConfigManager->getFloat("animations:borders_speed") == 0 ? ANIMSPEED : g_pConfigManager->getFloat("animations:borders_speed");
    const float FADESPEED       = g_pConfigManager->getFloat("animations:fadein_speed")  == 0 ? ANIMSPEED : g_pConfigManager->getFloat("animations:fadein_speed");

    const auto BORDERACTIVECOL  = CColor(g_pConfigManager->getInt("general:col.active_border"));
    const auto BORDERINACTIVECOL = CColor(g_pConfigManager->getInt("general:col.inactive_border"));

    const auto BORDERSIZE       = g_pConfigManager->getInt("general:border_size");

    for (auto& w : g_pCompositor->m_lWindows) {

        // get the box before transforms, for damage tracking later
        wlr_box WLRBOXPREV = { w.m_vRealPosition.x - BORDERSIZE - 1, w.m_vRealPosition.y - BORDERSIZE - 1, w.m_vRealSize.x + 2 * BORDERSIZE + 2, w.m_vRealSize.y + 2 * BORDERSIZE + 2};
        bool needsDamage = false;

        // process fadeinout
        if (FADEENABLED) {
            const auto GOALALPHA = w.m_bIsMapped ? 255.f : 0.f;
            w.m_bFadingOut = false;

            if (!deltazero(w.m_fAlpha, GOALALPHA)) {
                if (deltaSmallToFlip(w.m_fAlpha, GOALALPHA)) {
                    w.m_fAlpha = GOALALPHA;
                } else {
                    if (w.m_fAlpha > GOALALPHA)
                        w.m_bFadingOut = true;
                    w.m_fAlpha = parabolic(w.m_fAlpha, GOALALPHA, FADESPEED);
                }

                needsDamage = true;
            }

        } else {
            const auto GOALALPHA = w.m_bIsMapped ? 255.f : 0.f;

            if (!deltazero(GOALALPHA, w.m_fAlpha)) {
                if (w.m_bIsMapped)
                    w.m_fAlpha = 255.f;
                else {
                    w.m_fAlpha = 0.f;
                    w.m_bFadingOut = false;
                }

                needsDamage = true;
            }
        }

        // process fadein/out for unmapped windows, but nothing else.
        // we can't use windowValidMapped because we want to animate hidden windows too.
        if (!g_pCompositor->windowExists(&w) || !w.m_bIsMapped || !g_pXWaylandManager->getWindowSurface(&w)){
            if (needsDamage) {
                g_pHyprRenderer->damageWindow(&w); // only window, it didnt move cuz its unmappy
            }

            continue;
        }

        // process the borders
        const auto RENDERHINTS = g_pLayoutManager->getCurrentLayout()->requestRenderHints(&w);

        const auto& COLOR = RENDERHINTS.isBorderColor ? RENDERHINTS.borderColor : g_pCompositor->isWindowActive(&w) ? BORDERACTIVECOL : BORDERINACTIVECOL;

        if (BORDERSENABLED) {
            if (!deltazero(COLOR, w.m_cRealBorderColor)) {
                if (deltaSmallToFlip(COLOR, w.m_cRealBorderColor)) {
                    w.m_cRealBorderColor = COLOR;
                } else {
                    w.m_cRealBorderColor = parabolic(BORDERSPEED, w.m_cRealBorderColor, COLOR);
                }
                needsDamage = true;
            }
        } else {
            if (!deltazero(w.m_cRealBorderColor, COLOR))
                needsDamage = true;
            w.m_cRealBorderColor = COLOR;
        }

        // process the window
        if (WINDOWSENABLED) {
            if (!deltazero(w.m_vRealPosition, w.m_vEffectivePosition) || !deltazero(w.m_vRealSize, w.m_vEffectiveSize)) {
                if (deltaSmallToFlip(w.m_vRealPosition, w.m_vEffectivePosition) && deltaSmallToFlip(w.m_vRealSize, w.m_vEffectiveSize)) {
                    w.m_vRealPosition = w.m_vEffectivePosition;
                    w.m_vRealSize = w.m_vEffectiveSize;
                    g_pXWaylandManager->setWindowSize(&w, w.m_vRealSize);
                } else {
                    // if it is to be animated, animate it.
                    w.m_vRealPosition = Vector2D(parabolic(w.m_vRealPosition.x, w.m_vEffectivePosition.x, WINDOWSPEED), parabolic(w.m_vRealPosition.y, w.m_vEffectivePosition.y, WINDOWSPEED));
                    w.m_vRealSize = Vector2D(parabolic(w.m_vRealSize.x, w.m_vEffectiveSize.x, WINDOWSPEED), parabolic(w.m_vRealSize.y, w.m_vEffectiveSize.y, WINDOWSPEED));
                }

                needsDamage = true;
            }
        } else {
            if (!deltazero(w.m_vRealPosition, w.m_vEffectivePosition) || !deltazero(w.m_vRealSize, w.m_vEffectiveSize))
                needsDamage = true;

            w.m_vRealPosition = w.m_vEffectivePosition;
            w.m_vRealSize = w.m_vEffectiveSize;
        }

        if (needsDamage) {
            g_pHyprRenderer->damageBox(&WLRBOXPREV);
            g_pHyprRenderer->damageWindow(&w);
        }
    }
}

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;
}

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;
}

bool CAnimationManager::deltaSmallToFlip(const float& a, const float& b) {
    return std::abs(a - b) < 0.5f;
}

bool CAnimationManager::deltazero(const Vector2D& a, const Vector2D& b) {
    return a.x == b.x && a.y == b.y;
}

bool CAnimationManager::deltazero(const float& a, const float& b) {
    return a == b;
}

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;
}

double CAnimationManager::parabolic(const double from, const double to, const double incline) {
    return from + ((to - from) / incline);
}

CColor CAnimationManager::parabolic(const double incline, const CColor& from, const CColor& to) {
    CColor newColor;

    newColor.r = parabolic(from.r, to.r, incline);
    newColor.g = parabolic(from.g, to.g, incline);
    newColor.b = parabolic(from.b, to.b, incline);
    newColor.a = parabolic(from.a, to.a, incline);

    return newColor;
}