3
* Copyright (C) Remigiusz Dybka 2009 <remigiusz.dybka@gmail.com>
5
Zaz is free software: you can redistribute it and/or modify it
6
under the terms of the GNU General Public License as published by the
7
Free Software Foundation, either version 3 of the License, or
8
(at your option) any later version.
10
Zaz is distributed in the hope that it will be useful, but
11
WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
See the GNU General Public License for more details.
15
You should have received a copy of the GNU General Public License along
16
with this program. If not, see <http://www.gnu.org/licenses/>.
32
Scene::Scene(SDL_Surface *surf, uint fps)
36
quit = resync = false;
38
renderframedecimator = 1;
39
show_fps = settings.getb("showFps", false);
41
screenshotRequested = false;
43
vwidth = 100 * (640.0/480.0);
44
vleft = (100 - vwidth) / 2;
48
void Scene::RestartTimers()
50
tickStart = SDL_GetTicks() - ((restartFromFrame * 1000) / desiredFPS);
51
logicFrame = restartFromFrame;
53
logicInterval = 1000.0 / desiredFPS;
63
void Scene::Record(ostream &outstr, uint fromFrame)
68
restartFromFrame = fromFrame;
72
void Scene::Play(istream &instr)
80
void Scene::Export(string philename, istream &instr, uint skipframes)
84
phn = Settings::W32_CreateFile(philename);
88
ogvexp = new OgvExport(phn, surface->w, surface->h, desiredFPS / skipframes);
91
renderframedecimator = skipframes;
92
mixerMode = Nonrealtime;
94
Mixer *oldmixer = mixer;
103
bool ownMixer = false;
107
mixer = new Mixer(mixerMode);
112
uint exportedFrame = 0;
115
int pcmbuffersize = (44100 * 2 * 2) / (desiredFPS / renderframedecimator);
119
pixels = malloc(3 * surface->w * surface->h);
120
pcmbuffer = malloc(pcmbuffersize);
125
uint last_sec = tickStart / 1000;
133
int currTick = SDL_GetTicks() - tickStart;
140
uint currFrame = (currTick / 1000) * desiredFPS;
141
uint now_sec = currTick / 1000;
143
currFrame += (uint)(double(currTick % 1000) / 1000.0 * desiredFPS);
146
currFrame = logicFrame+1;
148
// are we ahead of time ?
150
if (logicFrame >= currFrame)
152
SDL_Delay((Uint32)double(((logicFrame + 1) * logicInterval) - currTick));
156
while (!resync && (logicFrame < currFrame))
158
if ((mode == RUN) || (mode == RECORD))
160
events = CreateFrameEvents();
168
if ((mode == PLAY) || (mode == RENDER))
170
events = LoadFrameEvents();
172
SDL_WarpMouse(events.mouseX, events.mouseY);
186
if (screenshotRequested)
188
SaveScreenshot(screenshotFilename);
189
screenshotRequested = false;
195
fpsmsg << "fps: " << renderFPS;
197
double vleft = (100 - 100 * (640.0/480.0)) / 2;
199
glTranslated(vleft, 98, 50);
200
glScaled(0.1, 0.1, 0.1);
202
glColor3f(1.0f, 1.0f, 1.0f);
203
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
204
if ((renderFPS < 200) && (renderFPS > 0))
205
font->Render(fpsmsg.str().c_str());
208
SDL_GL_SwapBuffers();
222
events = CreateFrameEvents();
223
if (events.keyDown.size() > 0)
224
for (vector<SDLKey>::iterator i = events.keyDown.begin(); i != events.keyDown.end(); ++i)
226
if (*i == SDLK_ESCAPE)
233
events = CreateFrameEvents();
235
if (events.keyDown.size() > 0)
236
for (vector<SDLKey>::iterator i = events.keyDown.begin(); i != events.keyDown.end(); ++i)
238
if (*i == SDLK_ESCAPE)
242
if (logicFrame%renderframedecimator == 0)
247
glPixelStorei(GL_PACK_ALIGNMENT, 1);
248
glReadPixels(0, 0, surface->w, surface->h,
249
GL_RGB, GL_UNSIGNED_BYTE, pixels);
250
mixer->Fill((Uint8 *)pcmbuffer, pcmbuffersize);
252
ogvexp->FeedFrame(pixels, pcmbuffer);
256
// add progress before showing the buffer
258
sprintf(msg, "%s", _("Exporting video [press ESC to cancel]"));
260
FTBBox b = font->BBox(msg);
261
double tw = b.Upper().X() / 7;
263
glTranslated((100 - tw) / 2, 40, 50);
264
glScaled(1.0/7.0, 1.0/7.0, 1.0/7.0);
266
glColor3f(1.0f, 1.0f, 1.0f);
267
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
269
SDL_GL_SwapBuffers();
274
if (now_sec != last_sec)
296
void Scene::Branch(Scene *scn)
298
// no branching while recording/playing/rendering
302
//cout << "Leaving on frame :" << logicInputFrame << endl;
303
scn->logicInputFrame = logicInputFrame + 1;
306
logicInputFrame = scn->logicInputFrame;
310
FrameEvents Scene::CreateFrameEvents()
315
bool mmotion = false;
322
while (SDL_PollEvent(&event))
327
ev.keyDown.push_back(event.key.keysym.sym);
329
ev.unicode.push_back(event.key.keysym.unicode);
332
ev.keyUp.push_back(event.key.keysym.sym);
335
case SDL_MOUSEBUTTONDOWN:
336
if (event.button.button == SDL_BUTTON_LEFT)
337
ev.buttDown[0] = true;
338
if (event.button.button == SDL_BUTTON_RIGHT)
339
ev.buttDown[1] = true;
340
if (event.button.button == SDL_BUTTON_MIDDLE)
341
ev.buttDown[2] = true;
346
case SDL_MOUSEBUTTONUP:
347
if (event.button.button == SDL_BUTTON_LEFT)
349
if (event.button.button == SDL_BUTTON_RIGHT)
351
if (event.button.button == SDL_BUTTON_MIDDLE)
357
case SDL_MOUSEMOTION:
358
mmx = event.motion.x;
359
mmy = event.motion.y;
360
rmx = event.motion.xrel;
361
rmy = event.motion.yrel;
370
if (logicInputFrame == 0)
376
ev.mouseX = (double)mmx / (double)surface->w;
377
ev.mouseY = (double)mmy / (double)surface->h;
379
// convert to int and back exactly as recording/playback would have done
380
ev.mouseX = (double)((int)(ev.mouseX * MOUSE_RESOLUTION)) / MOUSE_RESOLUTION;
381
ev.mouseY = (double)((int)(ev.mouseY * MOUSE_RESOLUTION)) / MOUSE_RESOLUTION;
383
RecalculateMousePos(mmx, mmy);
390
void Scene::RecalculateMousePos(int mmx, int mmy)
392
if ((mmx == mmy) && (mmx == -1))
394
SDL_GetMouseState(&mmx, &mmy);
397
double mouseX = (double)mmx / (double)surface->w;
398
double mouseY = (double)mmy / (double)surface->h;
400
// convert to int and back exactly as recording/playback would have done
401
mouseX = (double)((int)(mouseX * MOUSE_RESOLUTION)) / MOUSE_RESOLUTION;
402
mouseY = (double)((int)(mouseY * MOUSE_RESOLUTION)) / MOUSE_RESOLUTION;
404
mx = (vwidth * mouseX) + vleft;
405
my = vheight - (vheight * mouseY);
409
FrameEvents Scene::LoadFrameEvents()
413
if (nextEventLine.empty())
414
*in_stream >> nextEventLine;
416
uint rec_frame = atoi(nextEventLine.c_str());
418
if (rec_frame == logicInputFrame)
420
//cout << nextEventLine << endl;
422
// split line in fields
423
vector<string> fields;
424
string::size_type startpos = 0;
425
string::size_type endpos = string::npos;
427
while ((endpos = nextEventLine.find_first_of(':', startpos)) != string::npos)
429
fields.push_back(nextEventLine.substr(startpos, (endpos - startpos)));
430
startpos = endpos + 1;
433
fields.push_back(nextEventLine.substr(startpos));
440
endpos = string::npos;
441
while ((endpos = fields[1].find_first_of(',', startpos)) != string::npos)
443
ev.keyDown.push_back((SDLKey)atoi(fields[1].substr(startpos, (endpos - startpos)).c_str()));
444
startpos = endpos + 1;
447
if (fields[1].size() - startpos)
448
ev.keyDown.push_back((SDLKey)atoi(fields[1].substr(startpos).c_str()));
452
endpos = string::npos;
453
while ((endpos = fields[2].find_first_of(',', startpos)) != string::npos)
455
ev.keyUp.push_back((SDLKey)atoi(fields[2].substr(startpos, (endpos - startpos)).c_str()));
456
startpos = endpos + 1;
459
if (fields[2].size() - startpos)
460
ev.keyUp.push_back((SDLKey)atoi(fields[2].substr(startpos).c_str()));
462
ev.mouseX = atoi(fields[3].c_str());
463
ev.mouseY = atoi(fields[4].c_str());
465
ev.mouseX = (double)ev.mouseX / (double) MOUSE_RESOLUTION;
466
ev.mouseY = (double)ev.mouseY / (double) MOUSE_RESOLUTION;
467
ev.relmouseX = atoi(fields[5].c_str());
468
ev.relmouseY = atoi(fields[6].c_str());
471
ev.buttDown[0] = fields[7][0] == '1';
472
ev.buttDown[1] = fields[7][1] == '1';
473
ev.buttDown[2] = fields[7][2] == '1';
475
ev.buttUp[0] = fields[8][0] == '1';
476
ev.buttUp[1] = fields[8][1] == '1';
477
ev.buttUp[2] = fields[8][2] == '1';
479
*in_stream >> nextEventLine;
485
void Scene::SaveFrameEvents()
489
bool escape_hit = false;
490
for (vector<SDLKey>::iterator i = events.keyDown.begin(); i != events.keyDown.end(); ++i)
492
if (*i == SDLK_ESCAPE)
496
if (escape_hit) // don't save the event
499
*out_stream << logicInputFrame;
502
for (vector<SDLKey>::iterator i = events.keyDown.begin(); i != events.keyDown.end(); ++i)
504
if (i != events.keyDown.begin())
512
for (vector<SDLKey>::iterator i = events.keyUp.begin(); i != events.keyUp.end(); ++i)
514
if (i != events.keyUp.begin())
521
*out_stream << ":" << (int)(events.mouseX * MOUSE_RESOLUTION) << ":" << (int)(events.mouseY * MOUSE_RESOLUTION);
522
*out_stream << ":" << events.relmouseX << ":" << events.relmouseY;
524
*out_stream << ":" << events.buttDown[0] << events.buttDown[1] << events.buttDown[2];
525
*out_stream << ":" << events.buttUp[0] << events.buttUp[1] << events.buttUp[2];
531
void Scene::SaveScreenshot(string philename)
533
unsigned char *pixels;
535
pixels = (unsigned char *)malloc(3 * surface->w * surface->h);
536
glPixelStorei(GL_PACK_ALIGNMENT, 1);
537
glReadPixels(0, 0, surface->w, surface->h,
538
GL_RGB, GL_UNSIGNED_BYTE, pixels);
541
Uint32 rmask, gmask, bmask;//, amask;
543
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
547
//amask = 0x000000ff;
552
//amask = 0xff000000;
555
SDL_Surface *temp = SDL_CreateRGBSurface(SDL_SWSURFACE, surface->w, surface->h, 24, rmask, gmask, bmask, 0);
557
for (int i=0; i<surface->h; i++)
558
memcpy(((char *) temp->pixels) + temp->pitch * i,
559
pixels + 3*surface->w * (surface->h-i-1),
563
SDL_SaveBMP(temp, Settings::W32_CreateFile(philename).c_str());
565
SDL_SaveBMP(temp, philename.c_str());
567
SDL_FreeSurface(temp);
570
void Scene::Screenshot(string philename)
572
screenshotFilename = philename;
573
screenshotRequested = true;