MainLoop* main_loop = NULL;
MainLoop::MainLoop()
- : speed(1.0), nextpop(false), nextpush(false), fps(0)
+ : speed(1.0), nextpop(false), nextpush(false), fps(0), screenshot_requested(false)
{
using namespace Scripting;
TimeScheduler::instance = new TimeScheduler();
if(config->show_fps)
draw_fps(context, fps);
+ // if a screenshot was requested, pass request on to drawing_context
+ if (screenshot_requested) {
+ context.take_screenshot();
+ screenshot_requested = false;
+ }
context.do_drawing();
/* Calculate frames per second */
config->use_fullscreen = !config->use_fullscreen;
init_video();
}
+ else if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_PRINT) {
+ take_screenshot();
+ }
}
}
SDL_Delay(0);
}
}
+
+void
+MainLoop::take_screenshot()
+{
+ screenshot_requested = true;
+}
+
void quit(ScreenFade* fade = NULL);
void set_speed(float speed);
+ /**
+ * requests that a screenshot be taken after the next frame has been rendered
+ */
+ void take_screenshot();
+
// push new screen on screen_stack
void push_screen(Screen* screen, ScreenFade* fade = NULL);
void set_screen_fade(ScreenFade* fade);
std::auto_ptr<Console> console;
std::auto_ptr<ScreenFade> screen_fade;
std::vector<Screen*> screen_stack;
+ bool screenshot_requested; /**< true if a screenshot should be taken after the next frame has been rendered */
};
extern MainLoop* main_loop;
#include <iostream>
#include <SDL_image.h>
#include <GL/gl.h>
+#include <sstream>
+#include <iomanip>
+#include <physfs.h>
#include "drawing_context.hpp"
#include "surface.hpp"
}
DrawingContext::DrawingContext()
- : ambient_color(1.0f, 1.0f, 1.0f, 1.0f), target(NORMAL)
+ : ambient_color(1.0f, 1.0f, 1.0f, 1.0f), target(NORMAL), screenshot_requested(false)
{
screen = SDL_GetVideoSurface();
obstack_init(&obst);
assert_gl("drawing");
+ // if a screenshot was requested, take one
+ if (screenshot_requested) {
+ do_take_screenshot();
+ screenshot_requested = false;
+ }
+
SDL_GL_SwapBuffers();
}
{
ambient_color = new_color;
}
+
+void
+DrawingContext::do_take_screenshot()
+{
+ // [Christoph] TODO: Yes, this method also takes care of the actual disk I/O. Split it?
+
+ // create surface to hold screenshot
+ #if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ SDL_Surface* shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0);
+ #else
+ SDL_Surface* shot_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0);
+ #endif
+ if (!shot_surf) {
+ log_warning << "Could not create RGB Surface to contain screenshot" << std::endl;
+ return;
+ }
+
+ // read pixels into array
+ char* pixels = new char[3 * SCREEN_WIDTH * SCREEN_HEIGHT];
+ if (!pixels) {
+ log_warning << "Could not allocate memory to store screenshot" << std::endl;
+ SDL_FreeSurface(shot_surf);
+ return;
+ }
+ glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels);
+
+ // copy array line-by-line
+ for (int i = 0; i < SCREEN_HEIGHT; i++) {
+ char* src = pixels + (3 * SCREEN_WIDTH * (SCREEN_HEIGHT - i - 1));
+ char* dst = ((char*)shot_surf->pixels) + i * shot_surf->pitch;
+ memcpy(dst, src, 3 * SCREEN_WIDTH);
+ }
+
+ // free array
+ delete[](pixels);
+
+ // save screenshot
+ static const std::string writeDir = PHYSFS_getWriteDir();
+ static const std::string dirSep = PHYSFS_getDirSeparator();
+ static const std::string baseName = "screenshot";
+ static const std::string fileExt = ".bmp";
+ std::string fullFilename;
+ for (int num = 0; num < 1000; num++) {
+ std::ostringstream oss;
+ oss << baseName;
+ oss << std::setw(3) << std::setfill('0') << num;
+ oss << fileExt;
+ std::string fileName = oss.str();
+ fullFilename = writeDir + dirSep + fileName;
+ if (!PHYSFS_exists(fileName.c_str())) {
+ SDL_SaveBMP(shot_surf, fullFilename.c_str());
+ log_debug << "Wrote screenshot to \"" << fullFilename << "\"" << std::endl;
+ SDL_FreeSurface(shot_surf);
+ return;
+ }
+ }
+ log_warning << "Did not save screenshot, because all files up to \"" << fullFilename << "\" already existed" << std::endl;
+ SDL_FreeSurface(shot_surf);
+}
+
+void
+DrawingContext::take_screenshot()
+{
+ screenshot_requested = true;
+}
+
void set_ambient_color( Color new_color );
+ /**
+ * requests that a screenshot be taken after the next frame has been rendered
+ */
+ void take_screenshot();
+
private:
class Transform
{
void draw_filled_rect(const DrawingRequest& request) const;
void draw_lightmap(const DrawingRequest& request) const;
void get_light(const DrawingRequest& request) const;
+ void do_take_screenshot();
DrawingRequests drawing_requests;
DrawingRequests lightmap_requests;
/* obstack holding the memory of the drawing requests */
struct obstack obst;
+
+ bool screenshot_requested; /**< true if a screenshot should be taken after the next frame has been rendered */
};
#endif