From a29aa1ee2935857f616351a23578311f514516d4 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Tue, 25 Mar 2008 18:51:27 +0000 Subject: screenshots --- src/client/chat.cc | 4 +-- src/client/console.cc | 4 +-- src/client/input.cc | 5 ++- src/client/video.cc | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/client/video.h | 3 ++ src/client/view.h | 2 +- 6 files changed, 109 insertions(+), 6 deletions(-) (limited to 'src/client') diff --git a/src/client/chat.cc b/src/client/chat.cc index 8d5e94c..7f5c22c 100644 --- a/src/client/chat.cc +++ b/src/client/chat.cc @@ -40,7 +40,7 @@ void func_con_chat(std::string const &args) void init() { // add engine functions - core::Func::add("con_chat", (core::FuncPtr) func_con_chat); + //core::Func::add("con_chat", (core::FuncPtr) func_con_chat); history.clear(); history.push_back(""); @@ -52,7 +52,7 @@ void init() void shutdown() { // remove engine functions - core::Func::remove("con_chat"); + //core::Func::remove("con_chat"); history.clear(); input_pos = 0; diff --git a/src/client/console.cc b/src/client/console.cc index 67a6ac9..2d667a8 100644 --- a/src/client/console.cc +++ b/src/client/console.cc @@ -84,7 +84,7 @@ void init() console_visible = false; // add engine functions - core::Func::add("con_toggle", (core::FuncPtr) func_con_toggle); + //core::Func::add("con_toggle", (core::FuncPtr) func_con_toggle); text.clear(); console_scroll = 0; @@ -104,7 +104,7 @@ void shutdown() save_history(); // remove engine functions - core::Func::remove("con_toggle"); + //core::Func::remove("con_toggle"); text.clear(); console_scroll = 0; diff --git a/src/client/input.cc b/src/client/input.cc index 4d0f54b..1a61424 100644 --- a/src/client/input.cc +++ b/src/client/input.cc @@ -11,6 +11,7 @@ #include "client/console.h" #include "client/camera.h" #include "client/keyboard.h" +#include "client/video.h" #include "SDL/SDL.h" @@ -117,7 +118,9 @@ void frame(float seconds) switch (event.type) { case SDL_KEYUP: - if (!chat::visible() && !console::visible() && + if (event.key.keysym.sym == SDLK_PRINT) { + video::screenshot(); + } else if (!chat::visible() && !console::visible() && core::application()->connected() && core::localcontrol()) // send key events to the game world diff --git a/src/client/video.cc b/src/client/video.cc index 86fca89..a7a74d5 100644 --- a/src/client/video.cc +++ b/src/client/video.cc @@ -4,10 +4,14 @@ the terms and conditions of the GNU General Public License version 2 */ +#include +#include + #include "client/video.h" #include "client/view.h" #include "render/render.h" #include "core/core.h" +#include "filesystem/filesystem.h" #include "sys/sys.h" #include @@ -141,6 +145,99 @@ void shutdown() SDL_QuitSubSystem(SDL_INIT_VIDEO); } +void screenshot() +{ + int number = 0; + bool available = false; + std::string shortname; + std::string filename; + + // make sure the screenshots folder exists + filename.assign(filesystem::writedir); + filename.append("screenshots/"); + sys::mkdir(filename); + + // find the first available screenshotxxx.tga + do { + std::stringstream nstr; + nstr << number; + shortname.assign(nstr.str()); + + while(shortname.size() < 3) + shortname.insert(0, 1, '0'); + + shortname.insert(0, "screenshots/osirion"); + shortname.append(".tga"); + + filename.assign(filesystem::writedir); + filename.append(shortname); + + FILE *handle = fopen(filename.c_str(), "r"); + if (handle) { + fclose(handle); + number++; + } else { + available = true; + } + } while (!available); + + std::ofstream ofs(filename.c_str()); + + if (!ofs.is_open()) { + con_warn << "Could not write " << shortname << std::endl; + return; + } + + // TGA header + // TODO: RL-encoding, image ID + + // note: see http://www.fileformat.info/format/tga/egff.htm + unsigned char header[18]; + memset(header, 0, sizeof(header)); + + // byte 0 - image ID field lenght = 0 (no image ID field present) + // byte 1 - color map type = 0 (no palette present) + // byte 2 - image type = 2 (truecolor without RLE) + header[2] = 2; + // byte 3-11 - palette data (not used) + // byte 12+13 - image width + header[12] = (video::width & 0xff); + header[13] = ((video::width >> 8) & 0xff); + // byte 14+15 - image height + header[14] = (video::height & 0xff); + header[15] = ((video::height >> 8) & 0xff); + // byte 16 - image color depth = 24 (RGB) + header[16] = 24; + // byte 17 - image descriptor byte + header[17] = 0; + + // allocate buffer to hold the RGB data + unsigned char *rgb_data = (unsigned char *) malloc(video::width * video::height * 3); + + // read OpenGL pixels into the buffer + //glReadBuffer(GL_FRONT); + glReadPixels(0, 0, (GLsizei) video::width, (GLsizei) video::height, GL_RGB, GL_UNSIGNED_BYTE, (void *) rgb_data); + + // either OpenGL actually returns BGR, or TGA wants BGR + for (size_t i = 0; i < (size_t) (video::width * video::height); i++) { + unsigned char tmp = rgb_data[i*3]; + rgb_data[i*3] = rgb_data[i*3+2]; + rgb_data[i*3+2] = tmp; + } + + ofs.write((char *)header, sizeof(header)); + ofs.write((char *)rgb_data, video::width * video::height * 3 ); + + // free the buffer + free(rgb_data); + + // close file + ofs.close(); + + con_print << "Wrote " << shortname << std::endl; +} + + } // namespace video } // namespace client diff --git a/src/client/video.h b/src/client/video.h index 2b3fc41..d453536 100644 --- a/src/client/video.h +++ b/src/client/video.h @@ -24,6 +24,9 @@ namespace video /// reset and clear the viewport void reset(); + /// make a screenshot + void screenshot(); + /// width of the window in pixels extern int width; diff --git a/src/client/view.h b/src/client/view.h index 6220147..d9e44ab 100644 --- a/src/client/view.h +++ b/src/client/view.h @@ -21,7 +21,7 @@ namespace view /// draw the next frame void frame(float seconds); - /// reset the projection matrix + /// reset OpenGL state void reset(); } // namespace view -- cgit v1.2.3