]> git.sesse.net Git - ccbs/blob - bigscreen/rotatescreen.cpp
3c2a4b9df16afcc0d41e822380bc65d39d4d5aa3
[ccbs] / bigscreen / rotatescreen.cpp
1 #include <cstring>
2 #include "rotatescreen.h"
3
4 RotateScreen::RotateScreen()
5         : valid(false), current_screen(0), in_fade(false)
6 {
7         fadefrom_buf = new unsigned char[800 * 600 * 4];
8 }
9
10 RotateScreen::~RotateScreen()
11 {
12         delete fadefrom_buf;
13 }
14
15 bool RotateScreen::check_invalidated()
16 {
17         if (!valid)
18                 return true;
19         if (in_fade)
20                 return true;
21         if (needs_update())
22                 return true;
23         
24         for (unsigned i = 0; i < subscreens.size(); ++i) {
25                 if (subscreens[i].screen->check_invalidated())
26                         return true;
27         }
28
29         return false;
30 }
31
32 void RotateScreen::draw(unsigned char *buf)
33 {
34         bool force = false;
35         
36         // if we're in a fade, complete it before doing anything else
37         if (in_fade) {
38                 struct timeval now;
39                 gettimeofday(&now, NULL);
40
41                 if (!fade_found_start_time) {
42                         fade_found_start_time = true;
43                         fade_started = now;
44                 }
45                 
46                 double elapsed_fade = double(now.tv_sec - fade_started.tv_sec) +
47                         double(now.tv_usec - fade_started.tv_usec) * 1.0e-6;
48                 
49                 if (elapsed_fade > 6.0 || (!same_fade && elapsed_fade > 1.0)) {
50                         in_fade = false;
51
52                         // ugly hack here? :-)
53                         subscreens[current_screen].screen->draw(subscreens[current_screen].buf);
54                         
55                         memcpy(buf, subscreens[current_screen].buf, 800 * 600 * 4);
56                 } else {
57                         // find the fade factors
58                         int fr, fg, fb, fa;
59                         if (same_fade) {
60                                 if (elapsed_fade < 1.0) {
61                                         fr = fg = fb = fa = unsigned(elapsed_fade/1.0 * 256.0);
62                                 } else {
63                                         fr = fg = fb = fa = unsigned((elapsed_fade-1.0)/5.0 * 256.0);
64                                 }
65                         } else {
66                                 fr = fg = fb = fa = unsigned(elapsed_fade/1.0 * 256.0);
67                         }
68
69                         unsigned char *sptr1 = fadefrom_buf;
70                         unsigned char *sptr2 = subscreens[current_screen].buf;
71                         unsigned char *dptr = buf;
72
73                         if (same_fade && elapsed_fade >= 1.0) {
74                                 // fade G&B to be = R
75                                 for (unsigned i = 0; i < 800 * 600; ++i) {
76                                         dptr[0] = sptr2[0] + (((int(sptr2[2]) - int(sptr2[0])) * fb) >> 8);
77                                         dptr[1] = sptr2[1] + (((int(sptr2[2]) - int(sptr2[1])) * fg) >> 8);
78                                         dptr[2] = sptr2[2];
79                                         dptr[3] = sptr2[3];
80
81                                         sptr1 += 4, sptr2 += 4, dptr += 4;
82                                 }
83                         } else {
84                                 for (unsigned i = 0; i < 800 * 600; ++i) {
85                                         dptr[0] = sptr1[0] + (((int(sptr2[0]) - int(sptr1[0])) * fb) >> 8);
86                                         dptr[1] = sptr1[1] + (((int(sptr2[1]) - int(sptr1[1])) * fg) >> 8);
87                                         dptr[2] = sptr1[2] + (((int(sptr2[2]) - int(sptr1[2])) * fr) >> 8);
88                                         dptr[3] = sptr1[3] + (((int(sptr2[3]) - int(sptr1[3])) * fa) >> 8); 
89
90                                         sptr1 += 4, sptr2 += 4, dptr += 4;
91                                 }
92                         }
93                 }
94         } else {
95                 // determine if we want to switch screens
96         
97                 unsigned old_current_screen = current_screen;
98                 
99                 // push any invalidated screen first (for now)
100                 for (unsigned i = 0; i < subscreens.size(); ++i) {
101                         if (subscreens[i].screen->check_invalidated()) {
102                                 current_screen = i;
103                                 force = true;
104                         }
105                 }
106
107                 // check if we want to go to the next screen
108                 if (valid && !force && needs_update()) {
109                         current_screen = (current_screen + 1) % subscreens.size();
110                         gettimeofday(&last_update, NULL);
111                 }
112
113                 if (current_screen != old_current_screen || subscreens[current_screen].screen->check_invalidated()) {
114                         // initialize a fade
115                         in_fade = true;
116                         fade_found_start_time = false;
117                         same_fade = (current_screen == old_current_screen);
118                         
119                         memcpy(fadefrom_buf, subscreens[old_current_screen].buf, 800 * 600 * 4);
120
121                         if (subscreens[current_screen].screen->check_invalidated())
122                                 subscreens[current_screen].screen->draw(subscreens[current_screen].buf);
123                 }
124         }
125
126         if (!valid) {
127                 valid = true;
128                 gettimeofday(&last_update, NULL);
129         }
130 }
131         
132 // note: makes no sense if valid=false!
133 bool RotateScreen::needs_update()
134 {
135         struct timeval now;
136         gettimeofday(&now, NULL);
137
138         double since = double(now.tv_sec - last_update.tv_sec) +
139                 double(now.tv_usec - last_update.tv_usec) * 1.0e-6;
140
141         return (since >= 10.0);
142 }
143
144 void RotateScreen::add_screen(GenericScreen *screen)
145 {
146         Subscreen ss;
147         ss.buf = new unsigned char[800 * 600 * 4];
148         ss.screen = screen;
149
150         subscreens.push_back(ss);
151 }
152