1 /*
2 Copyright (C) 2010 Andrew Caudwell (acaudwell@gmail.com)
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version
7 3 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "gource_shell.h"
19
20 GourceShell* gGourceShell = 0;
21
22 // GourceShell
23
GourceShell(ConfFile * conf,FrameExporter * exporter)24 GourceShell::GourceShell(ConfFile* conf, FrameExporter* exporter) {
25
26 this->conf = conf;
27 this->exporter = exporter;
28
29 min_delta_msec = 16;
30
31 next = false;
32
33 gource = 0;
34 gource_settings = conf->getSections("gource")->begin();
35
36 gGourceSettings.repo_count = conf->countSection("gource");
37
38 toggle_delay = 0.0;
39 transition_texture = 0;
40 transition_interval = 0.0f;
41
42 if(GLEW_ARB_texture_non_power_of_two || GLEW_VERSION_2_0) {
43 transition_texture = texturemanager.create(display.width, display.height, false, GL_CLAMP_TO_EDGE, GL_RGBA);
44 }
45 }
46
~GourceShell()47 GourceShell::~GourceShell() {
48 if(gource!=0) delete gource;
49 if(transition_texture!=0) texturemanager.release(transition_texture);
50 }
51
toggleFullscreen()52 void GourceShell::toggleFullscreen() {
53
54 if(exporter != 0) return;
55
56 texturemanager.unload();
57 shadermanager.unload();
58 fontmanager.unload();
59
60 if(gource!=0) gource->unload();
61
62 //recreate gl context
63 display.toggleFullscreen();
64
65 texturemanager.reload();
66 shadermanager.reload();
67 fontmanager.reload();
68
69 if(gource!=0) gource->reload();
70 }
71
toggleWindowFrame()72 void GourceShell::toggleWindowFrame() {
73 #if SDL_VERSION_ATLEAST(2,0,0)
74 if(toggle_delay > 0.0) return;
75 if(display.isFullscreen()) return;
76 if(exporter != 0) return;
77
78 texturemanager.unload();
79 shadermanager.unload();
80 fontmanager.unload();
81
82 if(gource!=0) gource->unload();
83
84 display.toggleFrameless();
85
86 texturemanager.reload();
87 shadermanager.reload();
88 fontmanager.reload();
89
90 if(gource!=0) gource->reload();
91
92 toggle_delay = 0.25f;
93 #endif
94 }
95
96
resize(int width,int height)97 void GourceShell::resize(int width, int height) {
98
99 texturemanager.unload();
100 shadermanager.unload();
101 fontmanager.unload();
102
103 if(gource!=0) gource->unload();
104
105 //recreate gl context
106 display.resize(width, height);
107
108 texturemanager.reload();
109 shadermanager.reload();
110 fontmanager.reload();
111
112 if(gource!=0) gource->reload();
113 }
114
keyPress(SDL_KeyboardEvent * e)115 void GourceShell::keyPress(SDL_KeyboardEvent *e) {
116
117 bool repeat = false;
118 #if SDL_VERSION_ATLEAST(2,0,0)
119 repeat = (e->repeat > 0);
120 #endif
121
122 //Quit demo if the user presses ESC
123 if (e->type == SDL_KEYDOWN && !repeat) {
124
125 #if SDL_VERSION_ATLEAST(2,0,0)
126 bool key_escape = e->keysym.sym == SDLK_ESCAPE;
127 bool key_return = e->keysym.sym == SDLK_RETURN;
128 #else
129 bool key_escape = e->keysym.unicode == SDLK_ESCAPE;
130 bool key_return = e->keysym.unicode == SDLK_RETURN;
131 #endif
132
133 if (key_escape) {
134 quit();
135 }
136
137 if(gGourceSettings.disable_input) {
138 // disable keyboard input other than the escape key
139 return;
140 }
141
142 if (e->keysym.sym == SDLK_F11) {
143 toggleWindowFrame();
144 }
145
146 if(key_return) {
147
148 #if SDL_VERSION_ATLEAST(2,0,0)
149 const Uint8* keystate = SDL_GetKeyboardState(NULL);
150 if(keystate[SDL_SCANCODE_RALT] || keystate[SDL_SCANCODE_LALT]) {
151 #else
152 Uint8* keystate = SDL_GetKeyState(NULL);
153 if(keystate[SDLK_RALT] || keystate[SDLK_LALT]) {
154 #endif
155
156 toggleFullscreen();
157
158 } else {
159 if(gGourceSettings.repo_count>1)
160 next = true;
161 }
162 }
163 }
164
165 if(gource!=0) gource->keyPress(e);
166 }
167
168 void GourceShell::mouseMove(SDL_MouseMotionEvent *e) {
169 if(gource!=0) gource->mouseMove(e);
170 }
171
172 #if SDL_VERSION_ATLEAST(2,0,0)
173 void GourceShell::mouseWheel(SDL_MouseWheelEvent *e) {
174 if(gource!=0) gource->mouseWheel(e);
175 }
176 #endif
177
178 void GourceShell::mouseClick(SDL_MouseButtonEvent *e) {
179 if(gource!=0) gource->mouseClick(e);
180 }
181
182 void GourceShell::quit() {
183 if(gource!=0) gource->quit();
184 gGourceSettings.shutdown=true;
185 }
186
187 Gource* GourceShell::getNext() {
188
189 if(gource != 0) {
190 transition_interval = 1.0f;
191 delete gource;
192 gource = 0;
193 }
194
195 if(gGourceSettings.shutdown || gource_settings == conf->getSections("gource")->end()) {
196 // done
197 return 0;
198 }
199
200 gGourceSettings.importGourceSettings(*conf, *gource_settings);
201
202 //recording a video kind of implies you want this, unless:
203 // -- dont stop requested
204 // -- loop requested
205 // -- reading from STDIN
206 if(exporter!=0 && !(gGourceSettings.dont_stop || gGourceSettings.loop || gGourceSettings.path == "-"))
207 gGourceSettings.stop_at_end = true;
208
209 //multiple repo special settings
210 if(gGourceSettings.repo_count > 1) {
211
212 //set a stop condition
213 if(gGourceSettings.stop_at_time <= 0.0f && gGourceSettings.stop_position <= 0.0f) {
214 gGourceSettings.stop_at_time = 60.0f;
215 }
216 }
217
218 gource_settings++;
219
220 //loop unless only 1 repo
221 if(gource_settings == conf->getSections("gource")->end()) {
222 if(gGourceSettings.repo_count>1 && exporter==0) {
223 gource_settings = conf->getSections("gource")->begin();
224 }
225 }
226
227 // replace gource
228 gource = new Gource(exporter);
229
230 next = false;
231
232 return gource;
233 }
234
235 void GourceShell::blendLastFrame(float dt) {
236 if(transition_texture==0 || transition_interval <= 0.0f) return;
237
238 display.mode2D();
239
240 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
241 glEnable(GL_BLEND);
242 glEnable(GL_TEXTURE_2D);
243
244 transition_texture->bind();
245
246 glColor4f(1.0, 1.0, 1.0, transition_interval);
247
248 glBegin(GL_QUADS);
249 glTexCoord2f(0.0f, 1.0f);
250 glVertex2f(0.0f, 0.0);
251
252 glTexCoord2f(1.0, 1.0f);
253 glVertex2f(display.width, 0.0);
254
255 glTexCoord2f(1.0, 0.0f);
256 glVertex2f(display.width, display.height);
257
258 glTexCoord2f(0.0f, 0.0f);
259 glVertex2f(0.0f, display.height);
260 glEnd();
261
262 transition_interval -= dt;
263 }
264
265 void GourceShell::update(float t, float dt) {
266
267 if(gource == 0 || gource->isFinished()) {
268 if(!getNext()) appFinished=true;
269
270 return;
271 }
272
273 gource->fps = this->fps;
274 gource->update(t, dt);
275
276 if(toggle_delay > 0.0) toggle_delay -= dt;
277
278 //copy last frame
279 if( (next|| gource->isFinished()) && transition_texture!=0) {
280
281 glEnable(GL_TEXTURE_2D);
282 transition_texture->bind();
283 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, display.width, display.height, 0);
284
285 } else {
286 //blend last frame of previous scene
287 blendLastFrame(dt);
288 }
289
290 if(next) {
291 delete gource;
292 gource = 0;
293 transition_interval = 1.0f;
294 next = false;
295 }
296 }
297