diff --git a/panda/src/display/config_display.cxx b/panda/src/display/config_display.cxx index 21d9402746..11cda8e6a0 100644 --- a/panda/src/display/config_display.cxx +++ b/panda/src/display/config_display.cxx @@ -81,6 +81,9 @@ const bool yield_timeslice = config_display.GetBool("yield-timeslice", false); // This variable may be repeated several times. +const string screenshot_filename = config_display.GetString("screenshot-filename", "%~p-%a-%b-%d-%H-%M-%S-%Y-%~f.%~e"); +const string screenshot_extension = config_display.GetString("screenshot-extension", "jpg"); + //////////////////////////////////////////////////////////////////// // Function: init_libdisplay // Description: Initializes the library. This must be called at diff --git a/panda/src/display/config_display.h b/panda/src/display/config_display.h index 17014d40a7..832c859707 100644 --- a/panda/src/display/config_display.h +++ b/panda/src/display/config_display.h @@ -37,6 +37,9 @@ extern const string threading_model; extern const bool auto_flip; extern const bool yield_timeslice; +extern const string screenshot_filename; +extern const string screenshot_extension; + extern EXPCL_PANDA const bool multiple_windows; extern EXPCL_PANDA void init_libdisplay(); diff --git a/panda/src/display/graphicsWindow.cxx b/panda/src/display/graphicsWindow.cxx index a60ded2114..cdf9f7104a 100644 --- a/panda/src/display/graphicsWindow.cxx +++ b/panda/src/display/graphicsWindow.cxx @@ -385,6 +385,122 @@ get_display_region(int n) const { return result; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsWindow::take_screenshot +// Access: Published +// Description: Saves a screenshot of the window to a default +// filename, and returns the filename, or empty string +// if the screenshot failed. The default filename is +// generated from the supplied prefix and from the +// Configrc variable screenshot-filename, which contains +// the following strings: +// +// %~p - the supplied prefix +// %~f - the frame count +// %~e - the value of screenshot-extension +// All other % strings in strftime(). +//////////////////////////////////////////////////////////////////// +Filename GraphicsWindow:: +take_screenshot(const string &prefix) { + time_t now = time(NULL); + struct tm *ttm = localtime(&now); + int frame_count = ClockObject::get_global_clock()->get_frame_count(); + + static const int buffer_size = 1024; + char buffer[buffer_size]; + + ostringstream filename_strm; + + size_t i = 0; + while (i < screenshot_filename.length()) { + char ch1 = screenshot_filename[i++]; + if (ch1 == '%' && i < screenshot_filename.length()) { + char ch2 = screenshot_filename[i++]; + if (ch2 == '~' && i < screenshot_filename.length()) { + char ch3 = screenshot_filename[i++]; + switch (ch3) { + case 'p': + filename_strm << prefix; + break; + + case 'f': + filename_strm << frame_count; + break; + + case 'e': + filename_strm << screenshot_extension; + break; + } + + } else { + // Use strftime() to decode the percent code. + char format[3] = {'%', ch2, '\0'}; + if (strftime(buffer, buffer_size, format, ttm)) { + for (char *b = buffer; *b != '\0'; b++) { + switch (*b) { + case ' ': + case ':': + case '/': + filename_strm << '-'; + break; + + case '\n': + break; + + default: + filename_strm << *b; + } + } + } + } + } else { + filename_strm << ch1; + } + } + + Filename filename = filename_strm.str(); + if (take_screenshot(filename)) { + return filename; + } + return Filename(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsWindow::take_screenshot +// Access: Published +// Description: Saves a screenshot of the window to the indicated +// filename. Returns true on success, false on failure. +//////////////////////////////////////////////////////////////////// +bool GraphicsWindow:: +take_screenshot(const Filename &filename) { + if (_gsg == (GraphicsStateGuardian *)NULL) { + return false; + } + + WindowProperties props = get_properties(); + if (!props.has_size()) { + return false; + } + + int x_size = props.get_x_size(); + int y_size = props.get_y_size(); + + PixelBuffer p(x_size, y_size, 3, 1, PixelBuffer::T_unsigned_byte, + PixelBuffer::F_rgb); + + DisplayRegion dr(x_size, y_size); + RenderBuffer rb = _gsg->get_render_buffer(RenderBuffer::T_front); + if (!p.copy(_gsg, &dr, rb)) { + return false; + } + + if (!p.write(filename)) { + return false; + } + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsWindow::get_num_input_devices // Access: Published diff --git a/panda/src/display/graphicsWindow.h b/panda/src/display/graphicsWindow.h index aceefd27eb..833d4a60da 100644 --- a/panda/src/display/graphicsWindow.h +++ b/panda/src/display/graphicsWindow.h @@ -36,6 +36,7 @@ #include "iterator_types.h" #include "notify.h" #include "pmutex.h" +#include "filename.h" #include "pvector.h" #include "pdeque.h" @@ -97,6 +98,9 @@ PUBLISHED: int get_num_display_regions() const; DisplayRegion *get_display_region(int n) const; + Filename take_screenshot(const string &prefix = "screenshot"); + bool take_screenshot(const Filename &filename); + // Mouse and keyboard routines int get_num_input_devices() const; string get_input_device_name(int device) const; diff --git a/panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx b/panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx index 11a962d222..f88314ffdd 100644 --- a/panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx +++ b/panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx @@ -3641,21 +3641,18 @@ texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb, // Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian7:: +bool DXGraphicsStateGuardian7:: copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { extern HRESULT ConvertDDSurftoPixBuf(PixelBuffer *pixbuf,LPDIRECTDRAWSURFACE7 pDDSurf); - nassertv(pb != NULL && dr != NULL); + nassertr(pb != NULL && dr != NULL, false); int xo, yo, w, h; dr->get_region_pixels(xo, yo, w, h); // only handled simple case - nassertv(xo==0); - nassertv(yo==0); - nassertv(w==pb->get_xsize()); - nassertv(h==pb->get_ysize()); + nassertr(xo == 0 && yo==0 && w == pb->get_xsize() && h == pb->get_ysize(), false); /* set_pack_alignment(1); @@ -3669,7 +3666,8 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { (void) ConvertDDSurftoPixBuf(pb,((_cur_read_pixel_buffer & RenderBuffer::T_back) ? _pScrn->pddsBack : _pScrn->pddsPrimary)); - nassertv(!pb->_image.empty()); + nassertr(!pb->_image.empty(), false); + return true; } //////////////////////////////////////////////////////////////////// @@ -3677,11 +3675,11 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { // Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian7:: +bool DXGraphicsStateGuardian7:: copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, const RenderBuffer &rb) { set_read_buffer(rb); - copy_pixel_buffer(pb, dr); + return copy_pixel_buffer(pb, dr); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/dxgsg7/dxGraphicsStateGuardian7.h b/panda/src/dxgsg7/dxGraphicsStateGuardian7.h index b40ec9a338..e29e416950 100644 --- a/panda/src/dxgsg7/dxGraphicsStateGuardian7.h +++ b/panda/src/dxgsg7/dxGraphicsStateGuardian7.h @@ -106,8 +106,8 @@ public: virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb, const DisplayRegion *dr); - virtual void copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr); - virtual void copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, + virtual bool copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr); + virtual bool copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, const RenderBuffer &rb); virtual void apply_material(const Material *material); diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index 81e71a0b7b..2d2d0ae95d 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -3318,20 +3318,17 @@ texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb, // Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: +bool DXGraphicsStateGuardian8:: copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { RECT SrcCopyRect; - nassertv(pb != NULL && dr != NULL); + nassertr(pb != NULL && dr != NULL, false); int xo, yo, w, h; dr->get_region_pixels(xo, yo, w, h); // only handled simple case - nassertv(xo==0); - nassertv(yo==0); - nassertv(w==pb->get_xsize()); - nassertv(h==pb->get_ysize()); + nassertr(xo == 0 && yo==0 && w == pb->get_xsize() && h == pb->get_ysize(), false); IDirect3DSurface8 *pD3DSurf; HRESULT hr; @@ -3345,7 +3342,7 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { if(FAILED(hr)) { dxgsg8_cat.error() << "GetBackBuffer failed" << D3DERRORSTRING(hr); - exit(1); + return false; } D3DSURFACE_DESC SurfDesc; @@ -3389,31 +3386,32 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { hr=_pD3DDevice->CreateImageSurface(TmpSurfXsize,TmpSurfYsize,D3DFMT_A8R8G8B8,&pD3DSurf); if(FAILED(hr)) { dxgsg8_cat.error() << "CreateImageSurface failed in copy_pixel_buffer()" << D3DERRORSTRING(hr); - exit(1); + return false; } hr=_pD3DDevice->GetFrontBuffer(pD3DSurf); if(hr==D3DERR_DEVICELOST) { - // dont necessary want to exit in this case pD3DSurf->Release(); dxgsg8_cat.error() << "copy_pixel_buffer failed: device lost\n"; - return; + return false; } } else { dxgsg8_cat.error() << "copy_pixel_buffer: unhandled current_read_pixel_buffer type\n"; + return false; } if((RECT_XSIZE(SrcCopyRect)>w) || (RECT_YSIZE(SrcCopyRect)>h)) { dxgsg8_cat.error() << "copy_pixel_buffer: pixel buffer size does not match selected screen RenderBuffer size!\n"; - exit(1); + return false; } (void) ConvertD3DSurftoPixBuf(SrcCopyRect,pD3DSurf,pb); RELEASE(pD3DSurf,dxgsg8,"pD3DSurf",RELEASE_ONCE); - nassertv(!pb->_image.empty()); + nassertr(!pb->_image.empty(), false); + return true; } //////////////////////////////////////////////////////////////////// @@ -3421,11 +3419,11 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { // Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: +bool DXGraphicsStateGuardian8:: copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, const RenderBuffer &rb) { set_read_buffer(rb); - copy_pixel_buffer(pb, dr); + return copy_pixel_buffer(pb, dr); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h index 818178a3e0..fd3d5d0c04 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h @@ -110,8 +110,8 @@ public: virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb, const DisplayRegion *dr); - virtual void copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr); - virtual void copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, + virtual bool copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr); + virtual bool copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, const RenderBuffer &rb); virtual void apply_material(const Material *material); diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx index b984c3b495..333685e1a5 100755 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx @@ -3337,20 +3337,17 @@ texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb, // Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian9:: +bool DXGraphicsStateGuardian9:: copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { RECT SrcCopyRect; - nassertv(pb != NULL && dr != NULL); + nassertr(pb != NULL && dr != NULL, false); int xo, yo, w, h; dr->get_region_pixels(xo, yo, w, h); // only handled simple case - nassertv(xo==0); - nassertv(yo==0); - nassertv(w==pb->get_xsize()); - nassertv(h==pb->get_ysize()); + nassertr(xo == 0 && yo==0 && w == pb->get_xsize() && h == pb->get_ysize(), false); IDirect3DSurface9 *pD3DSurf; HRESULT hr; @@ -3364,7 +3361,7 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { if(FAILED(hr)) { dxgsg9_cat.error() << "GetBackBuffer failed" << D3DERRORSTRING(hr); - exit(1); + return false; } D3DSURFACE_DESC SurfDesc; @@ -3405,34 +3402,35 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { SrcCopyRect.bottom=TmpSurfYsize; } - hr=_pD3DDevice->CreateOffscreenPlainSurface(TmpSurfXsize,TmpSurfYsize,D3DFMT_A8R8G8B8,D3DPOOL_MANAGED, &pD3DSurf, NULL); + hr=_pD3DDevice->CreateOffscreenPlainSurface(TmpSurfXsize,TmpSurfYsize,D3DFMT_A8R8G8B8,D3DPOOL_SCRATCH, &pD3DSurf, NULL); if(FAILED(hr)) { dxgsg9_cat.error() << "CreateImageSurface failed in copy_pixel_buffer()" << D3DERRORSTRING(hr); - exit(1); + return false; } hr=_pD3DDevice->GetFrontBufferData(0, pD3DSurf); if(hr==D3DERR_DEVICELOST) { - // dont necessary want to exit in this case pD3DSurf->Release(); dxgsg9_cat.error() << "copy_pixel_buffer failed: device lost\n"; - return; + return false; } } else { dxgsg9_cat.error() << "copy_pixel_buffer: unhandled current_read_pixel_buffer type\n"; + return false; } if((RECT_XSIZE(SrcCopyRect)>w) || (RECT_YSIZE(SrcCopyRect)>h)) { dxgsg9_cat.error() << "copy_pixel_buffer: pixel buffer size does not match selected screen RenderBuffer size!\n"; - exit(1); + return false; } (void) ConvertD3DSurftoPixBuf(SrcCopyRect,pD3DSurf,pb); RELEASE(pD3DSurf,dxgsg9,"pD3DSurf",RELEASE_ONCE); - nassertv(!pb->_image.empty()); + nassertr(!pb->_image.empty(), false); + return true; } //////////////////////////////////////////////////////////////////// @@ -3440,11 +3438,11 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { // Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian9:: +bool DXGraphicsStateGuardian9:: copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, const RenderBuffer &rb) { set_read_buffer(rb); - copy_pixel_buffer(pb, dr); + return copy_pixel_buffer(pb, dr); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.h b/panda/src/dxgsg9/dxGraphicsStateGuardian9.h index e19af4bef2..83c615a1ef 100755 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.h +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.h @@ -110,8 +110,8 @@ public: virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb, const DisplayRegion *dr); - virtual void copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr); - virtual void copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, + virtual bool copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr); + virtual bool copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, const RenderBuffer &rb); virtual void apply_material(const Material *material); diff --git a/panda/src/framework/config_framework.cxx b/panda/src/framework/config_framework.cxx index e1fecb475c..63d4dc8fa6 100644 --- a/panda/src/framework/config_framework.cxx +++ b/panda/src/framework/config_framework.cxx @@ -45,3 +45,4 @@ const float win_background_b = config_framework.GetFloat("win-background-b", 0.4 const string record_session = config_framework.GetString("record-session", ""); const string playback_session = config_framework.GetString("playback-session", ""); + diff --git a/panda/src/framework/pandaFramework.cxx b/panda/src/framework/pandaFramework.cxx index 80c47b2b0f..1f685b08a8 100644 --- a/panda/src/framework/pandaFramework.cxx +++ b/panda/src/framework/pandaFramework.cxx @@ -618,6 +618,14 @@ do_frame() { DataGraphTraverser dg_trav; dg_trav.traverse(_data_root.node()); _event_handler.process_events(); + + if (!_screenshot_text.is_empty()) { + double now = ClockObject::get_global_clock()->get_frame_time(); + if (now >= _screenshot_clear_time) { + _screenshot_text.remove_node(); + } + } + if (_recorder != (RecorderController *)NULL) { _recorder->record_frame(); } @@ -701,6 +709,7 @@ do_enable_default_keys() { define_key("arrow_left", "move highlight to sibling", event_arrow_left, this); define_key("arrow_right", "move highlight to sibling", event_arrow_right, this); define_key("shift-s", "activate PStats", event_S, this); + define_key("f9", "Take screenshot", event_f9, this); define_key(",", "change background color", event_comma, this); define_key("?", "", event_question, this); define_key("shift-/", "", event_question, this); @@ -708,6 +717,29 @@ do_enable_default_keys() { _event_handler.add_hook("window-event", event_window_event, this); } +//////////////////////////////////////////////////////////////////// +// Function: PandaFramework::clear_text +// Access: Protected +// Description: Removes any onscreen text (like help text or +// screenshot filename). Returns true if there was any +// text in the first place, false otherwise. +//////////////////////////////////////////////////////////////////// +bool PandaFramework:: +clear_text() { + bool any_text = false; + if (!_screenshot_text.is_empty()) { + _screenshot_text.remove_node(); + any_text = true; + } + + if (!_help_text.is_empty()) { + _help_text.remove_node(); + any_text = true; + } + + return any_text; +} + //////////////////////////////////////////////////////////////////// // Function: PandaFramework::event_esc // Access: Protected, Static @@ -1031,7 +1063,7 @@ event_arrow_right(CPT_Event, void *data) { // Description: Default handler for shift-S key: activate stats. //////////////////////////////////////////////////////////////////// void PandaFramework:: -event_S(CPT_Event, void *data) { +event_S(CPT_Event, void *) { #ifdef DO_PSTATS nout << "Connecting to stats host" << endl; PStatClient::connect(); @@ -1040,6 +1072,48 @@ event_S(CPT_Event, void *data) { #endif } +//////////////////////////////////////////////////////////////////// +// Function: PandaFramework::event_f9 +// Access: Protected, Static +// Description: Default handler for f9 key: take screenshot. +//////////////////////////////////////////////////////////////////// +void PandaFramework:: +event_f9(CPT_Event event, void *data) { + PandaFramework *self = (PandaFramework *)data; + + if (event->get_num_parameters() == 1) { + EventParameter param = event->get_parameter(0); + WindowFramework *wf; + DCAST_INTO_V(wf, param.get_ptr()); + + if (self->clear_text()) { + // Render one more frame to remove the text. + self->_engine.render_frame(); + } + + Filename filename = wf->get_graphics_window()->take_screenshot(); + string text; + if (filename.empty()) { + text = "Screenshot failed"; + } else { + text = filename; + } + + TextNode *text_node = new TextNode("screenshot"); + self->_screenshot_text = NodePath(text_node); + text_node->set_align(TextNode::A_center); + text_node->set_shadow_color(0.0f, 0.0f, 0.0f, 1.0f); + text_node->set_shadow(0.04f, 0.04f); + text_node->set_text(text); + self->_screenshot_text.set_scale(0.06); + self->_screenshot_text.set_pos(0.0, 0.0, -0.7); + self->_screenshot_text.reparent_to(wf->get_aspect_2d()); + + double now = ClockObject::get_global_clock()->get_frame_time(); + self->_screenshot_clear_time = now + 2.0; + } +} + //////////////////////////////////////////////////////////////////// // Function: PandaFramework::event_comma // Access: Protected, Static @@ -1073,15 +1147,17 @@ event_comma(CPT_Event event, void *) { //////////////////////////////////////////////////////////////////// void PandaFramework:: event_question(CPT_Event event, void *data) { - cerr << "got question\n"; PandaFramework *self = (PandaFramework *)data; if (event->get_num_parameters() == 1) { EventParameter param = event->get_parameter(0); WindowFramework *wf; DCAST_INTO_V(wf, param.get_ptr()); + self->_screenshot_text.remove_node(); + if (!self->_help_text.is_empty()) { self->_help_text.remove_node(); + // This key is a toggle; remove the help text and do nothing else. } else { // Build up a string to display. @@ -1096,12 +1172,12 @@ event_question(CPT_Event event, void *data) { string help_text = help.str(); - TextNode *text_node = new TextNode("text"); + TextNode *text_node = new TextNode("help"); self->_help_text = NodePath(text_node); - text_node->set_text(help_text); text_node->set_align(TextNode::A_left); text_node->set_shadow_color(0.0f, 0.0f, 0.0f, 1.0f); text_node->set_shadow(0.04f, 0.04f); + text_node->set_text(help_text); LVecBase4f frame = text_node->get_frame_actual(); diff --git a/panda/src/framework/pandaFramework.h b/panda/src/framework/pandaFramework.h index 4d968a37c1..3bd1b6519d 100644 --- a/panda/src/framework/pandaFramework.h +++ b/panda/src/framework/pandaFramework.h @@ -115,6 +115,7 @@ protected: virtual PT(WindowFramework) make_window_framework(); virtual void make_default_pipe(); virtual void do_enable_default_keys(); + bool clear_text(); static void event_esc(CPT_Event, void *data); static void event_f(CPT_Event, void *data); @@ -133,6 +134,7 @@ protected: static void event_arrow_left(CPT_Event, void *data); static void event_arrow_right(CPT_Event, void *data); static void event_S(CPT_Event, void *data); + static void event_f9(CPT_Event, void *data); static void event_comma(CPT_Event, void *data); static void event_question(CPT_Event event, void *data); static void event_window_event(CPT_Event, void *data); @@ -181,6 +183,8 @@ private: KeyDefinitions _key_definitions; NodePath _help_text; + NodePath _screenshot_text; + double _screenshot_clear_time; PT(RecorderController) _recorder; }; diff --git a/panda/src/framework/windowFramework.h b/panda/src/framework/windowFramework.h index 9b2b176658..fcb473e4d0 100644 --- a/panda/src/framework/windowFramework.h +++ b/panda/src/framework/windowFramework.h @@ -100,7 +100,7 @@ public: INLINE bool get_one_sided_reverse() const; INLINE bool get_lighting() const; INLINE BackgroundType get_background_type() const; - + protected: PT(Camera) make_camera(); void setup_lights(); diff --git a/panda/src/glgsg/glGraphicsStateGuardian.cxx b/panda/src/glgsg/glGraphicsStateGuardian.cxx index e3d8c18ac0..b10516efc9 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.cxx +++ b/panda/src/glgsg/glGraphicsStateGuardian.cxx @@ -1954,9 +1954,9 @@ texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb, // Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// -void GLGraphicsStateGuardian:: +bool GLGraphicsStateGuardian:: copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { - nassertv(pb != NULL && dr != NULL); + nassertr(pb != NULL && dr != NULL, false); set_pack_alignment(1); // Bug fix for RE, RE2, and VTX - need to disable texturing in order @@ -2014,7 +2014,7 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { // pixelbuffer "origin" represents upper left screen point at which // pixelbuffer should be drawn using draw_pixel_buffer - nassertv(!pb->_image.empty()); + nassertr(!pb->_image.empty(), false); glReadPixels(pb->get_xorg() + xo, pb->get_yorg() + yo, pb->get_xsize(), pb->get_ysize(), external_format, @@ -2035,6 +2035,7 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { } report_gl_errors(); + return true; } //////////////////////////////////////////////////////////////////// @@ -2042,11 +2043,11 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { // Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// -void GLGraphicsStateGuardian:: +bool GLGraphicsStateGuardian:: copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, const RenderBuffer &rb) { set_read_buffer(rb); - copy_pixel_buffer(pb, dr); + return copy_pixel_buffer(pb, dr); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/glgsg/glGraphicsStateGuardian.h b/panda/src/glgsg/glGraphicsStateGuardian.h index 1a73eb3c96..c8f63574a9 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.h +++ b/panda/src/glgsg/glGraphicsStateGuardian.h @@ -104,8 +104,8 @@ public: virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb, const DisplayRegion *dr); - virtual void copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr); - virtual void copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, + virtual bool copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr); + virtual bool copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, const RenderBuffer &rb); virtual void apply_material(const Material *material); diff --git a/panda/src/gobj/imageBuffer.h b/panda/src/gobj/imageBuffer.h index 1c88680a31..ec716137e8 100644 --- a/panda/src/gobj/imageBuffer.h +++ b/panda/src/gobj/imageBuffer.h @@ -43,8 +43,8 @@ PUBLISHED: public: virtual void config( void ) { WritableConfigurable::config(); } - virtual void copy(GraphicsStateGuardianBase *, const DisplayRegion *)=0; - virtual void copy(GraphicsStateGuardianBase *, const DisplayRegion *, + virtual bool copy(GraphicsStateGuardianBase *, const DisplayRegion *)=0; + virtual bool copy(GraphicsStateGuardianBase *, const DisplayRegion *, const RenderBuffer &rb)=0; PUBLISHED: diff --git a/panda/src/gobj/pixelBuffer.cxx b/panda/src/gobj/pixelBuffer.cxx index 18354561d7..366428645a 100644 --- a/panda/src/gobj/pixelBuffer.cxx +++ b/panda/src/gobj/pixelBuffer.cxx @@ -422,12 +422,12 @@ copy(const PixelBuffer *pb) { _image.v() = pb->_image.v(); } -void PixelBuffer::copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr) { - gsg->copy_pixel_buffer(this, dr); +bool PixelBuffer::copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr) { + return gsg->copy_pixel_buffer(this, dr); } -void PixelBuffer::copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr, +bool PixelBuffer::copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr, const RenderBuffer &rb) { - gsg->copy_pixel_buffer(this, dr, rb); + return gsg->copy_pixel_buffer(this, dr, rb); } diff --git a/panda/src/gobj/pixelBuffer.h b/panda/src/gobj/pixelBuffer.h index e72cf04ccc..1d27c242ba 100644 --- a/panda/src/gobj/pixelBuffer.h +++ b/panda/src/gobj/pixelBuffer.h @@ -105,10 +105,10 @@ public: bool store( PNMImage& pnmimage ) const; void copy(const PixelBuffer *pb); - - virtual void copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr); - virtual void copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr, - const RenderBuffer &rb); + + virtual bool copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr); + virtual bool copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr, + const RenderBuffer &rb); INLINE void set_xsize(int size); INLINE void set_ysize(int size); diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index fdba10dd40..63f537f5dd 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -606,13 +606,15 @@ get_ram_image() { } } -void Texture::copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr) { +bool Texture::copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr) { gsg->copy_texture(prepare(gsg), dr); + return true; } -void Texture::copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr, +bool Texture::copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr, const RenderBuffer &rb) { gsg->copy_texture(prepare(gsg), dr, rb); + return true; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index 6fd53ddae7..916fb8b59d 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -116,8 +116,8 @@ public: INLINE void apply(GraphicsStateGuardianBase *gsg); - virtual void copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr); - virtual void copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr, + virtual bool copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr); + virtual bool copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr, const RenderBuffer &rb); // These bits are used as parameters to Texture::mark_dirty() and diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index 94d49f61e6..92dceadcbe 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/panda/src/gsgbase/graphicsStateGuardianBase.h @@ -164,8 +164,8 @@ public: virtual void texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb, const DisplayRegion *dr)=0; - virtual void copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr)=0; - virtual void copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, + virtual bool copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr)=0; + virtual bool copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, const RenderBuffer &rb)=0; virtual void apply_material(const Material *material)=0;