From 389b24e69522f986296817818f2f2ab1803fc1bb Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 13 Mar 2023 10:36:55 +0100 Subject: [PATCH 01/15] windisplay: Fix issues switching fullscreen while maximized Fixes #1469 --- panda/src/windisplay/winGraphicsWindow.cxx | 79 +++++++++++++++------- panda/src/windisplay/winGraphicsWindow.h | 2 + 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/panda/src/windisplay/winGraphicsWindow.cxx b/panda/src/windisplay/winGraphicsWindow.cxx index 1ca0425273..7878484a79 100644 --- a/panda/src/windisplay/winGraphicsWindow.cxx +++ b/panda/src/windisplay/winGraphicsWindow.cxx @@ -283,15 +283,34 @@ process_events() { */ void WinGraphicsWindow:: set_properties_now(WindowProperties &properties) { - if (properties.has_fullscreen() && !properties.get_fullscreen() && - is_fullscreen()) { - if (do_windowed_switch()) { - _properties.set_fullscreen(false); - properties.clear_fullscreen(); - } else { - windisplay_cat.warning() - << "Switching to windowed mode failed!\n"; + if (properties.has_fullscreen()) { + if (!properties.get_fullscreen() && is_fullscreen()) { + if (do_windowed_switch()) { + _properties.set_fullscreen(false); + } else { + windisplay_cat.warning() + << "Switching to windowed mode failed!\n"; + } } + else if (properties.get_fullscreen() && !is_fullscreen()) { + int x_size; + int y_size; + if (properties.has_size()) { + x_size = properties.get_x_size(); + y_size = properties.get_y_size(); + } else { + x_size = _properties.get_x_size(); + y_size = _properties.get_y_size(); + } + if (do_fullscreen_switch(x_size, y_size)) { + _properties.set_fullscreen(true); + properties.clear_size(); + } else { + windisplay_cat.warning() + << "Switching to fullscreen mode failed!\n"; + } + } + properties.clear_fullscreen(); } GraphicsWindow::set_properties_now(properties); @@ -917,8 +936,8 @@ do_fullscreen_resize(int x_size, int y_size) { * Called in the set_properties_now function to switch to fullscreen. */ bool WinGraphicsWindow:: -do_fullscreen_switch() { - if (!do_fullscreen_enable()) { +do_fullscreen_switch(int x_size, int y_size) { + if (!do_fullscreen_enable(x_size, y_size)) { // Couldn't get fullscreen. return false; } @@ -928,17 +947,21 @@ do_fullscreen_switch() { DWORD window_style = make_style(props); SetWindowLong(_hWnd, GWL_STYLE, window_style); - WINDOW_METRICS metrics; - bool has_origin; - if (!calculate_metrics(true, window_style, metrics, has_origin)){ - return false; - } - - SetWindowPos(_hWnd, HWND_NOTOPMOST, 0, 0, metrics.width, metrics.height, + SetWindowPos(_hWnd, HWND_NOTOPMOST, 0, 0, x_size, y_size, SWP_FRAMECHANGED | SWP_SHOWWINDOW); + + handle_reshape(); return true; } +/** + * Called in the set_properties_now function to switch to fullscreen. + */ +bool WinGraphicsWindow:: +do_fullscreen_switch() { + return do_fullscreen_switch(_properties.get_x_size(), _properties.get_y_size()); +} + /** * Called in the set_properties_now function to switch to windowed mode. */ @@ -1188,8 +1211,8 @@ open_graphic_window() { // somehow, but I need the window's black background to cover up the desktop // during the mode change. - if (fullscreen){ - if (!do_fullscreen_enable()){ + if (fullscreen) { + if (!do_fullscreen_enable()) { return false; } } @@ -1202,7 +1225,7 @@ open_graphic_window() { * Not to confuse with do_fullscreen_switch(). */ bool WinGraphicsWindow:: -do_fullscreen_enable() { +do_fullscreen_enable(int x_size, int y_size) { HWND hDesktopWindow = GetDesktopWindow(); HDC scrnDC = GetDC(hDesktopWindow); @@ -1212,8 +1235,8 @@ do_fullscreen_enable() { // GetDeviceCaps(scrnDC, VERTRES); ReleaseDC(hDesktopWindow, scrnDC); - DWORD dwWidth = _properties.get_x_size(); - DWORD dwHeight = _properties.get_y_size(); + DWORD dwWidth = x_size; + DWORD dwHeight = y_size; DWORD dwFullScreenBitDepth = cur_bitdepth; DEVMODE dm; @@ -1241,12 +1264,16 @@ do_fullscreen_enable() { } _fullscreen_display_mode = dm; - - _properties.set_origin(0, 0); - _properties.set_size(dwWidth, dwHeight); - return true; +} +/** + * This is a low-level function that just puts Windows in fullscreen mode. + * Not to confuse with do_fullscreen_switch(). + */ +bool WinGraphicsWindow:: +do_fullscreen_enable() { + return do_fullscreen_enable(_properties.get_x_size(), _properties.get_y_size()); } /** diff --git a/panda/src/windisplay/winGraphicsWindow.h b/panda/src/windisplay/winGraphicsWindow.h index 083508087b..a0416a873f 100644 --- a/panda/src/windisplay/winGraphicsWindow.h +++ b/panda/src/windisplay/winGraphicsWindow.h @@ -111,8 +111,10 @@ protected: virtual void handle_reshape(); virtual bool do_fullscreen_resize(int x_size, int y_size); + bool do_fullscreen_switch(int x_size, int y_size); virtual bool do_fullscreen_switch(); virtual bool do_windowed_switch(); + bool do_fullscreen_enable(int x_size, int y_size); virtual bool do_fullscreen_enable(); virtual bool do_fullscreen_disable(); From 21d7a83bfc1215c38827b003ac53f1abdf68f76f Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 29 Mar 2023 16:33:33 +0200 Subject: [PATCH 02/15] egldisplay: Fix GL_INVALID_OPERATION with headless pbuffer --- panda/src/egldisplay/eglGraphicsBuffer.cxx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/panda/src/egldisplay/eglGraphicsBuffer.cxx b/panda/src/egldisplay/eglGraphicsBuffer.cxx index 2cfbff83b4..e1293fd52e 100644 --- a/panda/src/egldisplay/eglGraphicsBuffer.cxx +++ b/panda/src/egldisplay/eglGraphicsBuffer.cxx @@ -38,9 +38,10 @@ eglGraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe, DCAST_INTO_V(egl_pipe, _pipe); _pbuffer = EGL_NO_SURFACE; - // Since the pbuffer never gets flipped, we get screenshots from the same - // buffer we draw into. - _screenshot_buffer_type = _draw_buffer_type; + // EGL pbuffers only have a back buffer (see 2.2.2 in spec), and it is never + // flipped (eglSwapBuffers is a no-op). + _draw_buffer_type = RenderBuffer::T_back; + _screenshot_buffer_type = RenderBuffer::T_back; } /** From f5d5340ad314cf36ed4426292beeffb4aa53cf73 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 8 Apr 2023 10:37:13 +0200 Subject: [PATCH 03/15] egldisplay: make pbuffers resizeable --- panda/src/egldisplay/eglGraphicsBuffer.cxx | 24 ++++++++++++++++++++++ panda/src/egldisplay/eglGraphicsBuffer.h | 2 ++ panda/src/egldisplay/eglGraphicsPipe.cxx | 1 - 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/panda/src/egldisplay/eglGraphicsBuffer.cxx b/panda/src/egldisplay/eglGraphicsBuffer.cxx index e1293fd52e..a71f562611 100644 --- a/panda/src/egldisplay/eglGraphicsBuffer.cxx +++ b/panda/src/egldisplay/eglGraphicsBuffer.cxx @@ -120,6 +120,30 @@ end_frame(FrameMode mode, Thread *current_thread) { } } +/** + * + */ +void eglGraphicsBuffer:: +set_size(int x, int y) { + nassertv_always(_gsg != nullptr); + + if (_size.get_x() != x || _size.get_y() != y) { + eglDestroySurface(_egl_display, _pbuffer); + + int attrib_list[] = { + EGL_WIDTH, x, + EGL_HEIGHT, y, + EGL_NONE + }; + + eglGraphicsStateGuardian *eglgsg; + DCAST_INTO_V(eglgsg, _gsg); + _pbuffer = eglCreatePbufferSurface(eglgsg->_egl_display, eglgsg->_fbconfig, attrib_list); + } + + set_size_and_recalc(x, y); +} + /** * Closes the buffer right now. Called from the window thread. */ diff --git a/panda/src/egldisplay/eglGraphicsBuffer.h b/panda/src/egldisplay/eglGraphicsBuffer.h index 68697ef94c..60be353e47 100644 --- a/panda/src/egldisplay/eglGraphicsBuffer.h +++ b/panda/src/egldisplay/eglGraphicsBuffer.h @@ -36,6 +36,8 @@ public: virtual bool begin_frame(FrameMode mode, Thread *current_thread); virtual void end_frame(FrameMode mode, Thread *current_thread); + virtual void set_size(int x, int y); + protected: virtual void close_buffer(); virtual bool open_buffer(); diff --git a/panda/src/egldisplay/eglGraphicsPipe.cxx b/panda/src/egldisplay/eglGraphicsPipe.cxx index 6d4a58adc5..4df78c1028 100644 --- a/panda/src/egldisplay/eglGraphicsPipe.cxx +++ b/panda/src/egldisplay/eglGraphicsPipe.cxx @@ -323,7 +323,6 @@ make_output(const std::string &name, if (retry == 2) { if (((flags&BF_require_parasite)!=0)|| ((flags&BF_require_window)!=0)|| - ((flags&BF_resizeable)!=0)|| ((flags&BF_size_track_host)!=0)) { return nullptr; } From 87b46a61ed2ee417aac7270233a158e10a2bc20e Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 5 May 2023 10:45:26 +0200 Subject: [PATCH 04/15] display: minor doc fix and code cleanup --- panda/src/display/graphicsOutput.cxx | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/panda/src/display/graphicsOutput.cxx b/panda/src/display/graphicsOutput.cxx index 63d21476c0..9b6c93c49a 100644 --- a/panda/src/display/graphicsOutput.cxx +++ b/panda/src/display/graphicsOutput.cxx @@ -1113,8 +1113,9 @@ clear_pipe() { /** * Changes the x_size and y_size, then recalculates structures that depend on - * size. The recalculation currently includes: - compute_pixels on all the - * graphics regions. - updating the texture card, if one is present. + * size. The recalculation currently includes: + * - compute_pixels on all the graphics regions. + * - updating the texture card, if one is present. */ void GraphicsOutput:: set_size_and_recalc(int x, int y) { @@ -1126,11 +1127,8 @@ set_size_and_recalc(int x, int y) { int fb_x_size = get_fb_x_size(); int fb_y_size = get_fb_y_size(); - TotalDisplayRegions::iterator dri; - for (dri = _total_display_regions.begin(); - dri != _total_display_regions.end(); - ++dri) { - (*dri)->compute_pixels_all_stages(fb_x_size, fb_y_size); + for (DisplayRegion *dr : _total_display_regions) { + dr->compute_pixels_all_stages(fb_x_size, fb_y_size); } if (_texture_card != nullptr && _texture_card->get_num_geoms() > 0) { From eb82dbc7656075c466ce02ee8ffb7a8929173c09 Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 5 May 2023 10:47:14 +0200 Subject: [PATCH 05/15] putil: Accept bytes in DatagramOutputFile::write_header() --- panda/src/putil/datagramOutputFile.cxx | 16 ++++++++++++++++ panda/src/putil/datagramOutputFile.h | 1 + 2 files changed, 17 insertions(+) diff --git a/panda/src/putil/datagramOutputFile.cxx b/panda/src/putil/datagramOutputFile.cxx index 407e1adfec..6d285a7f3e 100644 --- a/panda/src/putil/datagramOutputFile.cxx +++ b/panda/src/putil/datagramOutputFile.cxx @@ -86,6 +86,22 @@ close() { _error = false; } +/** + * Writes a sequence of bytes to the beginning of the datagram file. This may + * be called any number of times after the file has been opened and before the + * first datagram is written. It may not be called once the first datagram is + * written. + */ +bool DatagramOutputFile:: +write_header(const vector_uchar &header) { + nassertr(_out != nullptr, false); + nassertr(!_wrote_first_datagram, false); + + _out->write((const char *)&header[0], header.size()); + thread_consider_yield(); + return !_out->fail(); +} + /** * Writes a sequence of bytes to the beginning of the datagram file. This may * be called any number of times after the file has been opened and before the diff --git a/panda/src/putil/datagramOutputFile.h b/panda/src/putil/datagramOutputFile.h index 17402850b0..fbc88e0bcd 100644 --- a/panda/src/putil/datagramOutputFile.h +++ b/panda/src/putil/datagramOutputFile.h @@ -38,6 +38,7 @@ PUBLISHED: void close(); + bool write_header(const vector_uchar &header); bool write_header(const std::string &header); virtual bool put_datagram(const Datagram &data); virtual bool copy_datagram(SubfileInfo &result, const Filename &filename); From 86804b3ed1c31841cd198091cd3f5688a0028e3e Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 5 May 2023 10:48:04 +0200 Subject: [PATCH 06/15] putil: Fix a faulty docstring in BamReader --- panda/src/putil/bamReader.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda/src/putil/bamReader.cxx b/panda/src/putil/bamReader.cxx index 2c9f0958ea..6c6d6e7b4f 100644 --- a/panda/src/putil/bamReader.cxx +++ b/panda/src/putil/bamReader.cxx @@ -315,7 +315,7 @@ read_object(TypedWritable *&ptr, ReferenceCount *&ref_ptr) { * time to call it. * * This must be called at least once after reading a particular object via - * get_object() in order to validate that object. + * read_object() in order to validate that object. * * The return value is true if all objects have been resolved, or false if * some objects are still outstanding (in which case you will need to call From 749e297a027dffda4c413ae24e8f9a19cc185e11 Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 5 May 2023 10:51:24 +0200 Subject: [PATCH 07/15] putil: Add file_version property to BamWriter (mirroring BamReader) --- panda/src/putil/bamWriter.h | 4 +++ panda/src/putil/bamWriter_ext.cxx | 28 +++++++++++++++++ panda/src/putil/bamWriter_ext.h | 37 +++++++++++++++++++++++ panda/src/putil/p3putil_ext_composite.cxx | 1 + 4 files changed, 70 insertions(+) create mode 100644 panda/src/putil/bamWriter_ext.cxx create mode 100644 panda/src/putil/bamWriter_ext.h diff --git a/panda/src/putil/bamWriter.h b/panda/src/putil/bamWriter.h index 780104b61c..be07d80411 100644 --- a/panda/src/putil/bamWriter.h +++ b/panda/src/putil/bamWriter.h @@ -87,9 +87,13 @@ PUBLISHED: INLINE TypedWritable *get_root_node() const; INLINE void set_root_node(TypedWritable *root_node); +public: + EXTENSION(PyObject *get_file_version() const); + PUBLISHED: MAKE_PROPERTY(target, get_target, set_target); MAKE_PROPERTY(filename, get_filename); + MAKE_PROPERTY(file_version, get_file_version); MAKE_PROPERTY(file_endian, get_file_endian); MAKE_PROPERTY(file_stdfloat_double, get_file_stdfloat_double); MAKE_PROPERTY(file_texture_mode, get_file_texture_mode); diff --git a/panda/src/putil/bamWriter_ext.cxx b/panda/src/putil/bamWriter_ext.cxx new file mode 100644 index 0000000000..ea5b451eb6 --- /dev/null +++ b/panda/src/putil/bamWriter_ext.cxx @@ -0,0 +1,28 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file bamWriter_ext.cxx + * @author rdb + * @date 2023-05-03 + */ + +#include "bamWriter_ext.h" +#include "config_putil.h" + +#ifdef HAVE_PYTHON + +/** + * Returns the version number of the Bam file currently being written. + */ +PyObject *Extension:: +get_file_version() const { + return Py_BuildValue("(ii)", _this->get_file_major_ver(), + _this->get_file_minor_ver()); +} + +#endif diff --git a/panda/src/putil/bamWriter_ext.h b/panda/src/putil/bamWriter_ext.h new file mode 100644 index 0000000000..1f0b3eefb1 --- /dev/null +++ b/panda/src/putil/bamWriter_ext.h @@ -0,0 +1,37 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file bamWriter_ext.h + * @author rdb + * @date 2023-05-01 + */ + +#ifndef BAMWRITER_EXT_H +#define BAMWRITER_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "extension.h" +#include "bamWriter.h" +#include "py_panda.h" + +/** + * This class defines the extension methods for BamWriter, which are called + * instead of any C++ methods with the same prototype. + */ +template<> +class Extension : public ExtensionBase { +public: + PyObject *get_file_version() const; +}; + +#endif // HAVE_PYTHON + +#endif // BAMWRITER_EXT_H diff --git a/panda/src/putil/p3putil_ext_composite.cxx b/panda/src/putil/p3putil_ext_composite.cxx index 6306661a7f..abb9df3b73 100644 --- a/panda/src/putil/p3putil_ext_composite.cxx +++ b/panda/src/putil/p3putil_ext_composite.cxx @@ -1,4 +1,5 @@ #include "bamReader_ext.cxx" +#include "bamWriter_ext.cxx" #include "bitArray_ext.cxx" #include "paramPyObject.cxx" #include "pythonCallbackObject.cxx" From 45fbfab094ab68ca4f130f7a496f65fbe7273fa0 Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 5 May 2023 10:52:46 +0200 Subject: [PATCH 08/15] pgraph: Add file_version property to BamFile (like BamReader/Writer) --- panda/src/pgraph/bamFile.h | 4 +++ panda/src/pgraph/bamFile_ext.cxx | 28 ++++++++++++++++ panda/src/pgraph/bamFile_ext.h | 37 +++++++++++++++++++++ panda/src/pgraph/p3pgraph_ext_composite.cxx | 1 + 4 files changed, 70 insertions(+) create mode 100644 panda/src/pgraph/bamFile_ext.cxx create mode 100644 panda/src/pgraph/bamFile_ext.h diff --git a/panda/src/pgraph/bamFile.h b/panda/src/pgraph/bamFile.h index a244ab3fa3..32793e512e 100644 --- a/panda/src/pgraph/bamFile.h +++ b/panda/src/pgraph/bamFile.h @@ -74,7 +74,11 @@ PUBLISHED: BamReader *get_reader(); BamWriter *get_writer(); +public: + EXTENSION(PyObject *get_file_version() const); + PUBLISHED: + MAKE_PROPERTY(file_version, get_file_version); MAKE_PROPERTY(file_endian, get_file_endian); MAKE_PROPERTY(file_stdfloat_double, get_file_stdfloat_double); diff --git a/panda/src/pgraph/bamFile_ext.cxx b/panda/src/pgraph/bamFile_ext.cxx new file mode 100644 index 0000000000..6c5cd04e1a --- /dev/null +++ b/panda/src/pgraph/bamFile_ext.cxx @@ -0,0 +1,28 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file bamFile_ext.cxx + * @author rdb + * @date 2023-05-03 + */ + +#include "bamFile_ext.h" +#include "bamWriter_ext.h" + +#ifdef HAVE_PYTHON + +/** + * Returns the version number of the Bam file currently being written. + */ +PyObject *Extension:: +get_file_version() const { + return Py_BuildValue("(ii)", _this->get_file_major_ver(), + _this->get_file_minor_ver()); +} + +#endif diff --git a/panda/src/pgraph/bamFile_ext.h b/panda/src/pgraph/bamFile_ext.h new file mode 100644 index 0000000000..7a6408d531 --- /dev/null +++ b/panda/src/pgraph/bamFile_ext.h @@ -0,0 +1,37 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file bamFile_ext.h + * @author rdb + * @date 2023-05-03 + */ + +#ifndef BAMFILE_EXT_H +#define BAMFILE_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "extension.h" +#include "bamFile.h" +#include "py_panda.h" + +/** + * This class defines the extension methods for BamFile, which are called + * instead of any C++ methods with the same prototype. + */ +template<> +class Extension : public ExtensionBase { +public: + PyObject *get_file_version() const; +}; + +#endif // HAVE_PYTHON + +#endif // BAMFILE_EXT_H diff --git a/panda/src/pgraph/p3pgraph_ext_composite.cxx b/panda/src/pgraph/p3pgraph_ext_composite.cxx index 37b9012c76..493636ccda 100644 --- a/panda/src/pgraph/p3pgraph_ext_composite.cxx +++ b/panda/src/pgraph/p3pgraph_ext_composite.cxx @@ -1,3 +1,4 @@ +#include "bamFile_ext.cxx" #include "loaderFileTypeRegistry_ext.cxx" #include "nodePath_ext.cxx" #include "nodePathCollection_ext.cxx" From 5d833c988aaace97b5460ed1bb2d4c53c3c9bf27 Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 5 May 2023 10:55:06 +0200 Subject: [PATCH 09/15] interrogate: Support explicit `cls` parameter for static methods --- dtool/src/interrogate/functionRemap.cxx | 20 ++++++++++++++----- dtool/src/interrogate/functionRemap.h | 1 + .../interfaceMakerPythonNative.cxx | 9 ++++++++- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/dtool/src/interrogate/functionRemap.cxx b/dtool/src/interrogate/functionRemap.cxx index 2e984c652b..f4fc81ddbe 100644 --- a/dtool/src/interrogate/functionRemap.cxx +++ b/dtool/src/interrogate/functionRemap.cxx @@ -479,6 +479,10 @@ get_call_str(const string &container, const vector_string &pexprs) const { call << separator << "self"; separator = ", "; } + if (_flags & F_explicit_cls) { + call << separator << "cls"; + separator = ", "; + } size_t pn = _first_true_parameter; size_t num_parameters = pexprs.size(); @@ -807,14 +811,20 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak first_param = 1; } - if (_parameters.size() > first_param && _parameters[first_param]._name == "self" && + if (_parameters.size() > first_param && TypeManager::is_pointer_to_PyObject(_parameters[first_param]._remap->get_orig_type())) { // Here's a special case. If the first parameter of a nonstatic method // is a PyObject * called "self", then we will automatically fill it in - // from the this pointer, and remove it from the generated parameter - // list. - _parameters.erase(_parameters.begin() + first_param); - _flags |= F_explicit_self; + // from the this pointer, and remove it from the generated parameter list. + // For static methods, we offer "cls" instead, containing the type object. + if (_parameters[first_param]._name == "self") { + _parameters.erase(_parameters.begin() + first_param); + _flags |= F_explicit_self; + } + else if (!_has_this && _parameters[first_param]._name == "cls") { + _parameters.erase(_parameters.begin() + first_param); + _flags |= F_explicit_cls; + } } if (_parameters.size() == first_param) { diff --git a/dtool/src/interrogate/functionRemap.h b/dtool/src/interrogate/functionRemap.h index 61ce48bcb6..87c6b0a523 100644 --- a/dtool/src/interrogate/functionRemap.h +++ b/dtool/src/interrogate/functionRemap.h @@ -101,6 +101,7 @@ public: F_divide_float = 0x2000, F_hash = 0x4000, F_explicit_args = 0x8000, + F_explicit_cls =0x10000, }; typedef std::vector Parameters; diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index cc184c7efa..e1bf72eb93 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -1669,7 +1669,11 @@ write_module_class(ostream &out, Object *obj) { } if (!func->_has_this) { - flags += " | METH_STATIC"; + if (func->_flags & FunctionRemap::F_explicit_cls) { + flags += " | METH_CLASS"; + } else { + flags += " | METH_STATIC"; + } // Skip adding this entry if we also have a property with the same name. // In that case, we will use a Dtool_StaticProperty to disambiguate @@ -3527,6 +3531,9 @@ write_function_for_top(ostream &out, InterfaceMaker::Object *obj, InterfaceMaker if (func->_has_this) { prototype += "self"; } + else if (func->_flags & FunctionRemap::F_explicit_cls) { + prototype += "cls"; + } switch (func->_args_type) { case AT_keyword_args: From cc74efa79ab64b5d41c887a7222250f61e84cdc3 Mon Sep 17 00:00:00 2001 From: max Date: Fri, 5 May 2023 11:08:17 +0200 Subject: [PATCH 10/15] Fix assorted instances of leftover Python 3 syntax Closes #1490 --- contrib/src/panda3dtoolsgui/Panda3DToolsGUI.py | 6 +++--- panda/src/iphone/ipfreeze.py | 6 +++--- panda/src/iphone/provision.py | 2 +- panda/src/testbed/test_native_net1.py | 12 ++++++------ panda/src/testbed/test_native_net2.py | 6 +++--- panda/src/testbed/test_native_net3.py | 4 ++-- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/contrib/src/panda3dtoolsgui/Panda3DToolsGUI.py b/contrib/src/panda3dtoolsgui/Panda3DToolsGUI.py index 0c8b3f3ccd..331081016b 100644 --- a/contrib/src/panda3dtoolsgui/Panda3DToolsGUI.py +++ b/contrib/src/panda3dtoolsgui/Panda3DToolsGUI.py @@ -1905,7 +1905,7 @@ class main(wx.Frame): self.txaExtraLines.append(line) txafile.close() except: - print "Error opening .txa file!" + print("Error opening .txa file!") self.palettize_saveTxaTxt.SetValue(os.path.join(dirname + os.sep , filename)) dlg.Destroy() @@ -2705,7 +2705,7 @@ class main(wx.Frame): selectedItemIndex = int(self.batchTree.GetItemText(selectedItemId).split()[0])-1 batchItem = self.batchList[selectedItemIndex] - print '\n'+self.BuildCommand(batchItem) + print('\n'+self.BuildCommand(batchItem)) if (batchItem['cmd'].count('maya2egg')): # Display Maya2Egg Tool Panel @@ -2840,7 +2840,7 @@ class main(wx.Frame): self.txaExtraLines.append(line) txafile.close() except: - print "Error opening .txa file!" + print("Error opening .txa file!") self.batchItemNameTxt.SetValue(batchItem['label']) diff --git a/panda/src/iphone/ipfreeze.py b/panda/src/iphone/ipfreeze.py index d7fe343a15..8762b95b63 100755 --- a/panda/src/iphone/ipfreeze.py +++ b/panda/src/iphone/ipfreeze.py @@ -17,8 +17,8 @@ import os from direct.dist import FreezeTool def usage(code, msg = ''): - print >> sys.stderr, __doc__ - print >> sys.stderr, msg + print(__doc__, file=sys.stderr) + print(msg, file=sys.stderr) sys.exit(code) if __name__ == '__main__': @@ -30,7 +30,7 @@ if __name__ == '__main__': try: opts, args = getopt.getopt(sys.argv[1:], 'h') - except getopt.error, msg: + except getopt.error as msg: usage(1, msg) for opt, arg in opts: diff --git a/panda/src/iphone/provision.py b/panda/src/iphone/provision.py index 47a445d3cc..ffdefc6fa0 100755 --- a/panda/src/iphone/provision.py +++ b/panda/src/iphone/provision.py @@ -34,7 +34,7 @@ command = 'env CODESIGN_ALLOCATE="/Developer/Platforms/iPhoneOS.platform/Develop 'xcent' : xcent, } -print command +print(command) result = os.system(command) if result != 0: raise StandardError diff --git a/panda/src/testbed/test_native_net1.py b/panda/src/testbed/test_native_net1.py index 0e4738e8ad..dd96973b16 100644 --- a/panda/src/testbed/test_native_net1.py +++ b/panda/src/testbed/test_native_net1.py @@ -11,7 +11,7 @@ SocketIP.InitNetworkDriver(); addr = SocketAddress() addr.setHost("127.0.0.1",8080) -print addr.getIpPort() +print(addr.getIpPort()) inbound = SocketTCPListen() @@ -23,16 +23,16 @@ while 1 == 1: source = SocketAddress() if inbound.GetIncomingConnection(newsession,source) : #newsession.SetNonBlocking(); - print source.getIpPort() + print(source.getIpPort()) newsession.SendData("Hello From the Listener\n\r"); s = newsession.RecvData(10); - print s - print newsession.GetLastError() + print(s) + print(newsession.GetLastError()) if newsession.ErrorIsWouldBlocking(newsession.GetLastError()) : - print "Reading Would Block" + print("Reading Would Block") else: - print "Not A Blocking Error" + print("Not A Blocking Error") newsession.SendData("GoodBy From the Listener\n\r"); newsession.Close(); diff --git a/panda/src/testbed/test_native_net2.py b/panda/src/testbed/test_native_net2.py index 44c197911b..002b223f53 100644 --- a/panda/src/testbed/test_native_net2.py +++ b/panda/src/testbed/test_native_net2.py @@ -15,7 +15,7 @@ SocketIP.InitNetworkDriver(); addr = SocketAddress() addr.setHost("127.0.0.1",6666) -print addr.getIpPort() +print(addr.getIpPort()) MyConection = BufferedDatagramConnection(0,4096000,4096000,102400); #help(BufferedDatagramConnection) @@ -42,8 +42,8 @@ dg1.addUint16(54321) while 1==1: for x in range(200000): if not MyConection.SendMessage(dg1): - print "Error Sending Message" + print("Error Sending Message") MyConection.Flush(); time.sleep(1) - print "loop" + print("loop") diff --git a/panda/src/testbed/test_native_net3.py b/panda/src/testbed/test_native_net3.py index dff516eb60..d1d9486ee6 100644 --- a/panda/src/testbed/test_native_net3.py +++ b/panda/src/testbed/test_native_net3.py @@ -15,7 +15,7 @@ SocketIP.InitNetworkDriver(); addr = SocketAddress() addr.setHost("127.0.0.1",6666) -print addr.getIpPort() +print(addr.getIpPort()) MyConection = BufferedDatagramConnection(0,4096000,4096000,102400); #help(BufferedDatagramConnection) @@ -47,4 +47,4 @@ while 1==1: MyConection.Flush(); time.sleep(1) - print "loop" + print("loop") From c958919037d80455e6b64bbb62b1bb2ace97a020 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 8 May 2023 10:32:50 +0200 Subject: [PATCH 11/15] Make API documentation for Filename and VirtualFileSystem clearer Mention specifically that Filename methods act on the physical disk whereas VirtualFileSystem methods act on the VFS Fixes #1493 [skip ci] --- dtool/src/dtoolutil/filename.cxx | 25 +++++++++++++++++-------- dtool/src/dtoolutil/filename.h | 5 +++++ panda/src/express/virtualFileSystem.I | 11 ++++++----- 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/dtool/src/dtoolutil/filename.cxx b/dtool/src/dtoolutil/filename.cxx index da5657dd9d..7d3ce1693f 100644 --- a/dtool/src/dtoolutil/filename.cxx +++ b/dtool/src/dtoolutil/filename.cxx @@ -1259,9 +1259,12 @@ to_os_long_name() const { } /** - * Returns true if the filename exists on the disk, false otherwise. If the - * type is indicated to be executable, this also tests that the file has + * Returns true if the filename exists on the physical disk, false otherwise. + * If the type is indicated to be executable, this also tests that the file has * execute permission. + * + * @see VirtualFileSystem::exists() for checking whether the filename exists in + * the virtual file system. */ bool Filename:: exists() const { @@ -1290,8 +1293,11 @@ exists() const { } /** - * Returns true if the filename exists and is the name of a regular file (i.e. - * not a directory or device), false otherwise. + * Returns true if the filename exists on the physical disk and is the name of + * a regular file (i.e. not a directory or device), false otherwise. + * + * @see VirtualFileSystem::is_regular_file() for checking whether the filename + * exists and is a regular file in the virtual file system. */ bool Filename:: is_regular_file() const { @@ -1320,8 +1326,8 @@ is_regular_file() const { } /** - * Returns true if the filename exists and is either a directory or a regular - * file that can be written to, or false otherwise. + * Returns true if the filename exists on the physical disk and is either a + * directory or a regular file that can be written to, or false otherwise. */ bool Filename:: is_writable() const { @@ -1352,8 +1358,11 @@ is_writable() const { } /** - * Returns true if the filename exists and is a directory name, false - * otherwise. + * Returns true if the filename exists on the physical disk and is a directory + * name, false otherwise. + * + * @see VirtualFileSystem::is_directory() for checking whether the filename + * exists as a directory in the virtual file system. */ bool Filename:: is_directory() const { diff --git a/dtool/src/dtoolutil/filename.h b/dtool/src/dtoolutil/filename.h index 99d94af5a6..35d18044f1 100644 --- a/dtool/src/dtoolutil/filename.h +++ b/dtool/src/dtoolutil/filename.h @@ -35,6 +35,11 @@ class DSearchPath; * convention, and it knows how to perform basic OS-specific I/O, like testing * for file existence and searching a searchpath, as well as the best way to * open an fstream for reading or writing. + * + * Note that the methods of Filename that interact with the filesystem (such + * as exists(), open_read(), etc.) directly interface with the operating system + * and are not aware of Panda's virtual file system. To interact with the VFS, + * use the methods on VirtualFileSystem instead. */ class EXPCL_DTOOL_DTOOLUTIL Filename { PUBLISHED: diff --git a/panda/src/express/virtualFileSystem.I b/panda/src/express/virtualFileSystem.I index b74b9edbee..713b992147 100644 --- a/panda/src/express/virtualFileSystem.I +++ b/panda/src/express/virtualFileSystem.I @@ -12,7 +12,8 @@ */ /** - * Convenience function; returns true if the named file exists. + * Convenience function; returns true if the named file exists in the virtual + * file system hierarchy. */ INLINE bool VirtualFileSystem:: exists(const Filename &filename) const { @@ -20,8 +21,8 @@ exists(const Filename &filename) const { } /** - * Convenience function; returns true if the named file exists and is a - * directory. + * Convenience function; returns true if the named file exists as a directory in + * the virtual file system hierarchy. */ INLINE bool VirtualFileSystem:: is_directory(const Filename &filename) const { @@ -30,8 +31,8 @@ is_directory(const Filename &filename) const { } /** - * Convenience function; returns true if the named file exists and is a - * regular file. + * Convenience function; returns true if the named file exists as a regular file + * in the virtual file system hierarchy. */ INLINE bool VirtualFileSystem:: is_regular_file(const Filename &filename) const { From 4b276826b66bb5c8c5fd3fbab1ee8a590d95e595 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 8 May 2023 11:20:54 +0200 Subject: [PATCH 12/15] workflow: Update GitHub CI runner OS versions --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 78f845c5e3..72795cdd0a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,12 +6,12 @@ jobs: if: "!contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, '[ci skip]')" strategy: matrix: - os: [ubuntu-18.04, windows-2019, macOS-10.15] + os: [ubuntu-20.04, windows-2019, macOS-11] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v1 - name: Install dependencies (Ubuntu) - if: matrix.os == 'ubuntu-18.04' + if: matrix.os == 'ubuntu-20.04' run: | sudo apt-get update sudo apt-get install build-essential bison flex libfreetype6-dev libgl1-mesa-dev libjpeg-dev libode-dev libopenal-dev libpng-dev libssl-dev libvorbis-dev libx11-dev libxcursor-dev libxrandr-dev nvidia-cg-toolkit zlib1g-dev From 3f76f4aa7018ca7e7fe0726abfdcca8c6c840481 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 8 May 2023 18:18:42 +0200 Subject: [PATCH 13/15] dist: Strip out delvewheel patch from packaged Python code Fixes #1492 --- direct/src/dist/FreezeTool.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/direct/src/dist/FreezeTool.py b/direct/src/dist/FreezeTool.py index 04dad43c7d..2361c7f16d 100644 --- a/direct/src/dist/FreezeTool.py +++ b/direct/src/dist/FreezeTool.py @@ -2495,6 +2495,21 @@ class PandaModuleFinder(modulefinder.ModuleFinder): else: code = fp.read() + # Strip out delvewheel patch (see GitHub issue #1492) + if isinstance(code, bytes): + # Don't look for \n at the end, it may also be \r\n + start_marker = b'# start delvewheel patch' + end_marker = b'# end delvewheel patch' + else: + start_marker = '# start delvewheel patch' + end_marker = '# end delvewheel patch' + + start = code.find(start_marker) + while start >= 0: + end = code.find(end_marker, start) + len(end_marker) + code = code[:start] + code[end:] + start = code.find(start_marker) + code += b'\n' if isinstance(code, bytes) else '\n' if sys.version_info >= (3, 2): co = compile(code, pathname, 'exec', optimize=self.optimize) From 1072e6bf1a32b7dc32a8c2fce54ded81c09af7c2 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 8 May 2023 18:24:41 +0200 Subject: [PATCH 14/15] dist: Show better error message when targeting outdated platform This occurs if someone explicitly mentions eg. manylinux1 in their platforms list and then updates to Python 3.10 --- direct/src/dist/commands.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/direct/src/dist/commands.py b/direct/src/dist/commands.py index 2619cac2ad..a37f043849 100644 --- a/direct/src/dist/commands.py +++ b/direct/src/dist/commands.py @@ -551,7 +551,20 @@ class build_apps(setuptools.Command): for index in self.pypi_extra_indexes: pip_args += ['--extra-index-url', index] - subprocess.check_call([sys.executable, '-m', 'pip'] + pip_args) + try: + subprocess.check_call([sys.executable, '-m', 'pip'] + pip_args) + except: + # Display a more helpful message for these common issues. + if platform.startswith('manylinux2010_') and sys.version_info >= (3, 11): + new_platform = platform.replace('manylinux2010_', 'manylinux2014_') + self.announce('This error likely occurs because {} is not a supported target as of Python 3.11.\nChange the target platform to {} instead.'.format(platform, new_platform), distutils.log.ERROR) + elif platform.startswith('manylinux1_') and sys.version_info >= (3, 10): + new_platform = platform.replace('manylinux1_', 'manylinux2014_') + self.announce('This error likely occurs because {} is not a supported target as of Python 3.10.\nChange the target platform to {} instead.'.format(platform, new_platform), distutils.log.ERROR) + elif platform.startswith('macosx_10_6_') and sys.version_info >= (3, 8): + new_platform = platform.replace('macosx_10_6_', 'macosx_10_9_') + self.announce('This error likely occurs because {} is not a supported target as of Python 3.8.\nChange the target platform to {} instead.'.format(platform, new_platform), distutils.log.ERROR) + raise # Return a list of paths to the downloaded whls return [ From 3df594a6dd351bbfa08ca4d84cc8b61f1d72e8a7 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 8 May 2023 19:50:14 +0200 Subject: [PATCH 15/15] dist: Add hidden import for shapely [skip ci] --- direct/src/dist/FreezeTool.py | 1 + 1 file changed, 1 insertion(+) diff --git a/direct/src/dist/FreezeTool.py b/direct/src/dist/FreezeTool.py index 2361c7f16d..3cfdafe1e9 100644 --- a/direct/src/dist/FreezeTool.py +++ b/direct/src/dist/FreezeTool.py @@ -96,6 +96,7 @@ hiddenImports = { 'scipy.special._ufuncs': ['scipy.special._ufuncs_cxx'], 'scipy.stats._stats': ['scipy.special.cython_special'], 'setuptools.monkey': ['setuptools.msvc'], + 'shapely._geometry_helpers': ['shapely._geos'], } if sys.version_info >= (3,):