diff --git a/BACKERS.md b/BACKERS.md index d1a9dd8727..a3eb53177b 100644 --- a/BACKERS.md +++ b/BACKERS.md @@ -4,10 +4,11 @@ This is a list of all the people who are contributing financially to Panda3D. I ## Bronze Sponsors -[ChangeCrab](https://changecrab.com/) ![Bronze Sponsors](https://opencollective.com/panda3d/tiers/bronze-sponsor.svg?avatarHeight=48&width=600) +[Route4Me](https://route4me.com/) * [Daniel Stokes](https://opencollective.com/daniel-stokes) * [David Rose](https://opencollective.com/david-rose) +* [Route4Me](https://route4me.com/) ## Benefactors diff --git a/dtool/src/dtoolbase/pdtoa.cxx b/dtool/src/dtoolbase/pdtoa.cxx index 2b508654ba..8055f6d49d 100644 --- a/dtool/src/dtoolbase/pdtoa.cxx +++ b/dtool/src/dtoolbase/pdtoa.cxx @@ -428,3 +428,161 @@ void pdtoa(double value, char *buffer) { Prettify(buffer, length, K); } } + +/** + * Version of pdtoa that tries hard to find the minimal string representation + * for a single-precision floating-point number. + */ +void pftoa(float value, char *buffer) { +#ifdef _MSC_VER + if (copysign(1.0f, value) < 0) { +#else + if (std::signbit(value)) { +#endif + *buffer++ = '-'; + value = -value; + } + if (cinf(value)) { + buffer[0] = 'i'; + buffer[1] = 'n'; + buffer[2] = 'f'; + buffer[3] = '\0'; + } else if (cnan(value)) { + buffer[0] = 'n'; + buffer[1] = 'a'; + buffer[2] = 'n'; + buffer[3] = '\0'; + } else if (value == 0.0f) { + buffer[0] = '0'; + buffer[1] = '.'; + buffer[2] = '0'; + buffer[3] = '\0'; + } else if (value == 1.0f) { + buffer[0] = '1'; + buffer[1] = '.'; + buffer[2] = '0'; + buffer[3] = '\0'; + } else { + int length, k; + Grisu2(value, buffer, &length, &k); + + const int kk = length + k; // 10^(kk-1) <= v < 10^kk + + if (length <= kk && kk <= 21) { + // 1234e7 -> 12340000000 + for (int i = length; i < kk; i++) + buffer[i] = '0'; + buffer[kk] = '.'; + buffer[kk + 1] = '0'; + buffer[kk + 2] = '\0'; + } + else if (0 < kk && kk <= 21) { + // 1234e-2 -> 12.34 + memmove(&buffer[kk + 1], &buffer[kk], length - kk); + + // We want the shortest possible representation, so keep reading digits + // until strtod would give the correct float value. + buffer[kk] = '\0'; + double v = (double)atoi(buffer); + buffer[kk] = '.'; + + double multiplicand = 0.1; + for (int i = kk + 1; i <= length; ++i) { + double vplus = v + (buffer[i] - '0' + 1) * multiplicand; + v += (buffer[i] - '0') * multiplicand; + multiplicand *= 0.1; + + if ((float)v == value) { + length = i; + break; + } + if (buffer[i] < '9' && (float)vplus == value) { + ++buffer[i]; + length = i; + break; + } + } + + buffer[length + 1] = '\0'; + } + else if (-6 < kk && kk <= 0) { + // 1234e-6 -> 0.001234 + const int offset = 2 - kk; + memmove(&buffer[offset], &buffer[0], length); + buffer[0] = '0'; + buffer[1] = '.'; + + // We want the shortest possible representation, so keep reading digits + // until strtod would give the correct float value. + double multiplicand = 1.0; + for (int i = 2; i < offset; i++) { + buffer[i] = '0'; + multiplicand *= 0.1; + } + if ((float)multiplicand == value) { + length = 0; + buffer[offset - 1] = '1'; + } else { + multiplicand *= 0.1; + double v = 0.0; + for (int i = offset; i < length + offset; ++i) { + double vplus = v + (buffer[i] - '0' + 1) * multiplicand; + v += (buffer[i] - '0') * multiplicand; + multiplicand *= 0.1; + + if ((float)v == value) { + buffer[i + 1] = '\0'; + break; + } + if (buffer[i] < '9' && (float)vplus == value) { + buffer[i]++; + buffer[i + 1] = '\0'; + break; + } + } + } + buffer[length + offset] = '\0'; + } + else if (length == 1) { + // 1e30 + buffer[1] = 'e'; + WriteExponent(kk - 1, &buffer[2]); + } + else { + // 1234e30 -> 1.234e33 + memmove(&buffer[2], &buffer[1], length - 1); + buffer[1] = '.'; + buffer[length + 1] = 'e'; + + double e_mult = pow(10.0, kk - 1); + if ((float)(10.0 * e_mult) == value) { + buffer[0] = '1'; + buffer[1] = 'e'; + WriteExponent(kk, &buffer[2]); + } else { + // We want the shortest possible representation, so keep reading + // digits until strtod would give the correct float value. + double v = buffer[0] - '0'; + double multiplicand = 0.1; + for (int i = 2; i < length + 2; ++i) { + double vplus = v + (buffer[i] - '0' + 1) * multiplicand; + v += (buffer[i] - '0') * multiplicand; + multiplicand *= 0.1; + + if ((float)(v * e_mult) == value) { + length = i; + buffer[i + 1] = 'e'; + break; + } + if (buffer[i] < '9' && (float)(vplus * e_mult) == value) { + buffer[i]++; + length = i; + buffer[i + 1] = 'e'; + break; + } + } + WriteExponent(kk - 1, &buffer[0 + length + 2]); + } + } + } +} diff --git a/dtool/src/dtoolbase/pdtoa.h b/dtool/src/dtoolbase/pdtoa.h index 908ca24deb..44b0d9e271 100644 --- a/dtool/src/dtoolbase/pdtoa.h +++ b/dtool/src/dtoolbase/pdtoa.h @@ -16,6 +16,7 @@ extern "C" { #endif EXPCL_DTOOL_DTOOLBASE void pdtoa(double value, char *buffer); +EXPCL_DTOOL_DTOOLBASE void pftoa(float value, char *buffer); #ifdef __cplusplus }; /* end of extern "C" */ diff --git a/dtool/src/dtoolutil/string_utils.I b/dtool/src/dtoolutil/string_utils.I index 1861e86ffa..d821deffdf 100644 --- a/dtool/src/dtoolutil/string_utils.I +++ b/dtool/src/dtoolutil/string_utils.I @@ -32,7 +32,7 @@ format_string(bool value) { INLINE std::string format_string(float value) { char buffer[32]; - pdtoa((double)value, buffer); + pftoa(value, buffer); return std::string(buffer); } diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index d13054624f..162eaa4925 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -922,12 +922,19 @@ write_prototypes(ostream &out_code, ostream *out_h) { // Write out a table of the externally imported types that will be filled in // upon module initialization. - if (!_external_imports.empty()) { + std::vector ext_imports(_external_imports.begin(), _external_imports.end()); + if (!ext_imports.empty()) { out_code << "#ifndef LINK_ALL_STATIC\n"; out_code << "static Dtool_TypeDef imports[] = {\n"; + // Ensure that there is a deterministic ordering of external imports. + std::sort(ext_imports.begin(), ext_imports.end(), + [] (const CPPType *a, const CPPType *b) { + return a->get_local_name(&parser) < b->get_local_name(&parser); + }); + int idx = 0; - for (CPPType *type : _external_imports) { + for (CPPType *type : ext_imports) { string class_name = type->get_local_name(&parser); string safe_name = make_safe_name(class_name); @@ -940,7 +947,7 @@ write_prototypes(ostream &out_code, ostream *out_h) { out_code << "#endif\n\n"; } - for (CPPType *type : _external_imports) { + for (CPPType *type : ext_imports) { string class_name = type->get_local_name(&parser); string safe_name = make_safe_name(class_name); diff --git a/dtool/src/interrogatedb/py_panda.h b/dtool/src/interrogatedb/py_panda.h index 9d8fc113ff..ca79501601 100644 --- a/dtool/src/interrogatedb/py_panda.h +++ b/dtool/src/interrogatedb/py_panda.h @@ -162,6 +162,9 @@ static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self) {\ Py_TYPE(self)->tp_free(self);\ } +// Extract the PyTypeObject pointer corresponding to a Dtool_PyTypedObject. +#define Dtool_GetPyTypeObject(type) (&(type)->_PyType) + // Use DtoolInstance_Check to check whether a PyObject* is a DtoolInstance. #define DtoolInstance_Check(obj) \ (Py_TYPE(obj)->tp_basicsize >= (int)sizeof(Dtool_PyInstDef) && \ diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 1cecc7dbe8..50e83cdaac 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -3002,7 +3002,7 @@ if not PkgSkip("PYTHON"): # This is just some basic stuff since setuptools just needs this file to # exist, otherwise it will not read the entry_points.txt file. Maybe we will # eventually want to merge this with the metadata generator in makewheel.py. -METADATA = """Metadata-Version: 2.0 +METADATA = """Metadata-Version: 2.1 Name: Panda3D Version: {version} License: BSD diff --git a/makepanda/makewheel.py b/makepanda/makewheel.py index 3b2f332260..5c6e68d200 100644 --- a/makepanda/makewheel.py +++ b/makepanda/makewheel.py @@ -105,7 +105,7 @@ PROJECT_URLS = dict([line.split('=', 1) for line in GetMetadataValue('project_ur METADATA = { "license": GetMetadataValue('license'), "name": GetMetadataValue('name'), - "metadata_version": "2.0", + "metadata_version": "2.1", "generator": "makepanda", "summary": GetMetadataValue('description'), "extensions": { diff --git a/panda/src/glstuff/glGraphicsBuffer_src.cxx b/panda/src/glstuff/glGraphicsBuffer_src.cxx index 0a26277ea9..cd87938288 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.cxx +++ b/panda/src/glstuff/glGraphicsBuffer_src.cxx @@ -16,6 +16,18 @@ using std::max; using std::min; +/** + * Returns a copy of the FrameBufferProperties, but without back buffers. + * This is used since the GraphicsOutput constructor makes some decisions + * based on whether this is set, so we need to unset it early. + */ +static FrameBufferProperties +without_back_buffers(const FrameBufferProperties &fb_prop) { + FrameBufferProperties copy(fb_prop); + copy.set_back_buffers(0); + return copy; +} + TypeHandle CLP(GraphicsBuffer)::_type_handle; /** @@ -29,7 +41,7 @@ CLP(GraphicsBuffer)(GraphicsEngine *engine, GraphicsPipe *pipe, int flags, GraphicsStateGuardian *gsg, GraphicsOutput *host) : - GraphicsBuffer(engine, pipe, name, fb_prop, win_prop, flags, gsg, host), + GraphicsBuffer(engine, pipe, name, without_back_buffers(fb_prop), win_prop, flags, gsg, host), _requested_multisamples(0), _requested_coverage_samples(0), _rb_context(nullptr), diff --git a/panda/src/linmath/dblnames.h b/panda/src/linmath/dblnames.h index c2c646b750..a2e7363e3e 100644 --- a/panda/src/linmath/dblnames.h +++ b/panda/src/linmath/dblnames.h @@ -33,6 +33,7 @@ #undef FLOATTYPE_IS_INT #undef STRINGIFY #undef FLOATNAME_STR +#undef FLOATTYPE_REPR #define FLOATTYPE double #define FLOATNAME(ARG) ARG##d @@ -41,3 +42,15 @@ #define STRINGIFY(ARG) #ARG #define FLOATNAME_STR(ARG) STRINGIFY(ARG##d) + +#define FLOATTYPE_REPR(v, str) do { \ + double v_copy = (v); \ + char *into_str = (str); \ + if ((double)(long long)v_copy == v_copy) { \ + snprintf(into_str, 32, "%lld", (long long)v_copy); \ + } else { \ + pdtoa(v_copy, into_str); \ + } \ +} while (0) + +#include "pdtoa.h" diff --git a/panda/src/linmath/fltnames.h b/panda/src/linmath/fltnames.h index d8d4762ddb..a69d651f51 100644 --- a/panda/src/linmath/fltnames.h +++ b/panda/src/linmath/fltnames.h @@ -33,6 +33,7 @@ #undef FLOATTYPE_IS_INT #undef STRINGIFY #undef FLOATNAME_STR +#undef FLOATTYPE_REPR #define FLOATTYPE float #define FLOATNAME(ARG) ARG##f @@ -41,3 +42,15 @@ #define STRINGIFY(ARG) #ARG #define FLOATNAME_STR(ARG) STRINGIFY(ARG##f) + +#define FLOATTYPE_REPR(v, str) do { \ + float v_copy = (v); \ + char *into_str = (str); \ + if ((float)(int)v_copy == v_copy) { \ + snprintf(into_str, 32, "%d", (int)v_copy); \ + } else { \ + pftoa(v_copy, into_str); \ + } \ +} while (0) + +#include "pdtoa.h" diff --git a/panda/src/linmath/intnames.h b/panda/src/linmath/intnames.h index 2a01d71e05..a7e1ae7cb8 100644 --- a/panda/src/linmath/intnames.h +++ b/panda/src/linmath/intnames.h @@ -33,6 +33,7 @@ #undef FLOATTYPE_IS_INT #undef STRINGIFY #undef FLOATNAME_STR +#undef FLOATTYPE_REPR #define FLOATTYPE int #define FLOATNAME(ARG) ARG##i @@ -42,3 +43,5 @@ #define STRINGIFY(ARG) #ARG #define FLOATNAME_STR(ARG) STRINGIFY(ARG##i) + +#define FLOATTYPE_REPR(v, str) (snprintf((str), 12, "%d", (v))) diff --git a/panda/src/linmath/lmatrix3_ext_src.I b/panda/src/linmath/lmatrix3_ext_src.I index 38b47f4c04..f5759e3821 100644 --- a/panda/src/linmath/lmatrix3_ext_src.I +++ b/panda/src/linmath/lmatrix3_ext_src.I @@ -47,18 +47,21 @@ __rmul__(FLOATTYPE scalar) const { */ INLINE_LINMATH std::string Extension:: __repr__() const { - std::ostringstream out; - out << "LMatrix3" << FLOATTOKEN << "(" - << MAYBE_ZERO(_this->_m(0, 0)) << ", " - << MAYBE_ZERO(_this->_m(0, 1)) << ", " - << MAYBE_ZERO(_this->_m(0, 2)) << ", " + char buf[32 * 17] = "LMatrix4"; + char *p = buf + strlen(buf); + *(p++) = FLOATTOKEN; + *(p++) = '('; + FLOATTYPE_REPR(_this->_m(0, 0), p); + p += strlen(p); - << MAYBE_ZERO(_this->_m(1, 0)) << ", " - << MAYBE_ZERO(_this->_m(1, 1)) << ", " - << MAYBE_ZERO(_this->_m(1, 2)) << ", " + for (int i = 1; i < 9; ++i) { + *(p++) = ','; + *(p++) = ' '; + FLOATTYPE_REPR(_this->get_data()[i], p); + p += strlen(p); + } - << MAYBE_ZERO(_this->_m(2, 0)) << ", " - << MAYBE_ZERO(_this->_m(2, 1)) << ", " - << MAYBE_ZERO(_this->_m(2, 2)) << ")"; - return out.str(); + *(p++) = ')'; + *p = '\0'; + return std::string(buf, p - buf); } diff --git a/panda/src/linmath/lmatrix4_ext_src.I b/panda/src/linmath/lmatrix4_ext_src.I index 2d4e6d07fb..9370b5d3b9 100644 --- a/panda/src/linmath/lmatrix4_ext_src.I +++ b/panda/src/linmath/lmatrix4_ext_src.I @@ -48,26 +48,21 @@ __rmul__(FLOATTYPE scalar) const { */ INLINE_LINMATH std::string Extension:: __repr__() const { - std::ostringstream out; - out << "LMatrix4" << FLOATTOKEN << "(" - << MAYBE_ZERO(_this->_m(0, 0)) << ", " - << MAYBE_ZERO(_this->_m(0, 1)) << ", " - << MAYBE_ZERO(_this->_m(0, 2)) << ", " - << MAYBE_ZERO(_this->_m(0, 3)) << ", " + char buf[32 * 17] = "LMatrix4"; + char *p = buf + strlen(buf); + *(p++) = FLOATTOKEN; + *(p++) = '('; + FLOATTYPE_REPR(_this->_m(0, 0), p); + p += strlen(p); - << MAYBE_ZERO(_this->_m(1, 0)) << ", " - << MAYBE_ZERO(_this->_m(1, 1)) << ", " - << MAYBE_ZERO(_this->_m(1, 2)) << ", " - << MAYBE_ZERO(_this->_m(1, 3)) << ", " + for (int i = 1; i < 16; ++i) { + *(p++) = ','; + *(p++) = ' '; + FLOATTYPE_REPR(_this->get_data()[i], p); + p += strlen(p); + } - << MAYBE_ZERO(_this->_m(2, 0)) << ", " - << MAYBE_ZERO(_this->_m(2, 1)) << ", " - << MAYBE_ZERO(_this->_m(2, 2)) << ", " - << MAYBE_ZERO(_this->_m(2, 3)) << ", " - - << MAYBE_ZERO(_this->_m(3, 0)) << ", " - << MAYBE_ZERO(_this->_m(3, 1)) << ", " - << MAYBE_ZERO(_this->_m(3, 2)) << ", " - << MAYBE_ZERO(_this->_m(3, 3)) << ")"; - return out.str(); + *(p++) = ')'; + *p = '\0'; + return std::string(buf, p - buf); } diff --git a/panda/src/linmath/lpoint2_ext_src.I b/panda/src/linmath/lpoint2_ext_src.I index 09f357686f..44bd412ebf 100644 --- a/panda/src/linmath/lpoint2_ext_src.I +++ b/panda/src/linmath/lpoint2_ext_src.I @@ -16,11 +16,19 @@ */ INLINE_LINMATH std::string Extension:: __repr__() const { - std::ostringstream out; - out << "LPoint2" << FLOATTOKEN << "(" - << MAYBE_ZERO(_this->_v(0)) << ", " - << MAYBE_ZERO(_this->_v(1)) << ")"; - return out.str(); + char buf[96] = "LPoint2"; + char *p = buf + strlen(buf); + *(p++) = FLOATTOKEN; + *(p++) = '('; + FLOATTYPE_REPR(_this->_v(0), p); + p += strlen(p); + *(p++) = ','; + *(p++) = ' '; + FLOATTYPE_REPR(_this->_v(1), p); + p += strlen(p); + *(p++) = ')'; + *p = '\0'; + return std::string(buf, p - buf); } /** diff --git a/panda/src/linmath/lpoint3_ext_src.I b/panda/src/linmath/lpoint3_ext_src.I index b45b62e936..a1bb81f329 100644 --- a/panda/src/linmath/lpoint3_ext_src.I +++ b/panda/src/linmath/lpoint3_ext_src.I @@ -16,12 +16,23 @@ */ INLINE_LINMATH std::string Extension:: __repr__() const { - std::ostringstream out; - out << "LPoint3" << FLOATTOKEN << "(" - << MAYBE_ZERO(_this->_v(0)) << ", " - << MAYBE_ZERO(_this->_v(1)) << ", " - << MAYBE_ZERO(_this->_v(2)) << ")"; - return out.str(); + char buf[128] = "LPoint3"; + char *p = buf + strlen(buf); + *(p++) = FLOATTOKEN; + *(p++) = '('; + FLOATTYPE_REPR(_this->_v(0), p); + p += strlen(p); + *(p++) = ','; + *(p++) = ' '; + FLOATTYPE_REPR(_this->_v(1), p); + p += strlen(p); + *(p++) = ','; + *(p++) = ' '; + FLOATTYPE_REPR(_this->_v(2), p); + p += strlen(p); + *(p++) = ')'; + *p = '\0'; + return std::string(buf, p - buf); } /** diff --git a/panda/src/linmath/lpoint4_ext_src.I b/panda/src/linmath/lpoint4_ext_src.I index ee64b2c287..bbab239c91 100644 --- a/panda/src/linmath/lpoint4_ext_src.I +++ b/panda/src/linmath/lpoint4_ext_src.I @@ -16,13 +16,27 @@ */ INLINE_LINMATH std::string Extension:: __repr__() const { - std::ostringstream out; - out << "LPoint4" << FLOATTOKEN << "(" - << MAYBE_ZERO(_this->_v(0)) << ", " - << MAYBE_ZERO(_this->_v(1)) << ", " - << MAYBE_ZERO(_this->_v(2)) << ", " - << MAYBE_ZERO(_this->_v(3)) << ")"; - return out.str(); + char buf[160] = "LPoint4"; + char *p = buf + strlen(buf); + *(p++) = FLOATTOKEN; + *(p++) = '('; + FLOATTYPE_REPR(_this->_v(0), p); + p += strlen(p); + *(p++) = ','; + *(p++) = ' '; + FLOATTYPE_REPR(_this->_v(1), p); + p += strlen(p); + *(p++) = ','; + *(p++) = ' '; + FLOATTYPE_REPR(_this->_v(2), p); + p += strlen(p); + *(p++) = ','; + *(p++) = ' '; + FLOATTYPE_REPR(_this->_v(3), p); + p += strlen(p); + *(p++) = ')'; + *p = '\0'; + return std::string(buf, p - buf); } /** diff --git a/panda/src/linmath/lvecBase2_ext_src.I b/panda/src/linmath/lvecBase2_ext_src.I index d435399721..f860917257 100644 --- a/panda/src/linmath/lvecBase2_ext_src.I +++ b/panda/src/linmath/lvecBase2_ext_src.I @@ -24,11 +24,19 @@ */ INLINE_LINMATH std::string Extension:: __repr__() const { - std::ostringstream out; - out << "LVecBase2" << FLOATTOKEN << "(" - << MAYBE_ZERO(_this->_v(0)) << ", " - << MAYBE_ZERO(_this->_v(1)) << ")"; - return out.str(); + char buf[96] = "LVecBase2"; + char *p = buf + strlen(buf); + *(p++) = FLOATTOKEN; + *(p++) = '('; + FLOATTYPE_REPR(_this->_v(0), p); + p += strlen(p); + *(p++) = ','; + *(p++) = ' '; + FLOATTYPE_REPR(_this->_v(1), p); + p += strlen(p); + *(p++) = ')'; + *p = '\0'; + return std::string(buf, p - buf); } /** diff --git a/panda/src/linmath/lvecBase3_ext_src.I b/panda/src/linmath/lvecBase3_ext_src.I index e69e0f00de..67bc4b65b0 100644 --- a/panda/src/linmath/lvecBase3_ext_src.I +++ b/panda/src/linmath/lvecBase3_ext_src.I @@ -24,12 +24,23 @@ */ INLINE_LINMATH std::string Extension:: __repr__() const { - std::ostringstream out; - out << "LVecBase3" << FLOATTOKEN << "(" - << MAYBE_ZERO(_this->_v(0)) << ", " - << MAYBE_ZERO(_this->_v(1)) << ", " - << MAYBE_ZERO(_this->_v(2)) << ")"; - return out.str(); + char buf[128] = "LVecBase3"; + char *p = buf + strlen(buf); + *(p++) = FLOATTOKEN; + *(p++) = '('; + FLOATTYPE_REPR(_this->_v(0), p); + p += strlen(p); + *(p++) = ','; + *(p++) = ' '; + FLOATTYPE_REPR(_this->_v(1), p); + p += strlen(p); + *(p++) = ','; + *(p++) = ' '; + FLOATTYPE_REPR(_this->_v(2), p); + p += strlen(p); + *(p++) = ')'; + *p = '\0'; + return std::string(buf, p - buf); } /** @@ -408,3 +419,4 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) const { #undef PYNUMBER_FLOATTYPE #undef PY_AS_FLOATTYPE +#undef FLOATTYPE_TO_STR diff --git a/panda/src/linmath/lvecBase4_ext_src.I b/panda/src/linmath/lvecBase4_ext_src.I index 44c97033d7..9b396af666 100644 --- a/panda/src/linmath/lvecBase4_ext_src.I +++ b/panda/src/linmath/lvecBase4_ext_src.I @@ -24,13 +24,27 @@ */ INLINE_LINMATH std::string Extension:: __repr__() const { - std::ostringstream out; - out << "LVecBase4" << FLOATTOKEN << "(" - << MAYBE_ZERO(_this->_v(0)) << ", " - << MAYBE_ZERO(_this->_v(1)) << ", " - << MAYBE_ZERO(_this->_v(2)) << ", " - << MAYBE_ZERO(_this->_v(3)) << ")"; - return out.str(); + char buf[160] = "LVecBase4"; + char *p = buf + strlen(buf); + *(p++) = FLOATTOKEN; + *(p++) = '('; + FLOATTYPE_REPR(_this->_v(0), p); + p += strlen(p); + *(p++) = ','; + *(p++) = ' '; + FLOATTYPE_REPR(_this->_v(1), p); + p += strlen(p); + *(p++) = ','; + *(p++) = ' '; + FLOATTYPE_REPR(_this->_v(2), p); + p += strlen(p); + *(p++) = ','; + *(p++) = ' '; + FLOATTYPE_REPR(_this->_v(3), p); + p += strlen(p); + *(p++) = ')'; + *p = '\0'; + return std::string(buf, p - buf); } /** diff --git a/panda/src/linmath/lvector2_ext_src.I b/panda/src/linmath/lvector2_ext_src.I index dba65a1b61..88449328ec 100644 --- a/panda/src/linmath/lvector2_ext_src.I +++ b/panda/src/linmath/lvector2_ext_src.I @@ -16,11 +16,19 @@ */ INLINE_LINMATH std::string Extension:: __repr__() const { - std::ostringstream out; - out << "LVector2" << FLOATTOKEN << "(" - << MAYBE_ZERO(_this->_v(0)) << ", " - << MAYBE_ZERO(_this->_v(1)) << ")"; - return out.str(); + char buf[96] = "LVector2"; + char *p = buf + strlen(buf); + *(p++) = FLOATTOKEN; + *(p++) = '('; + FLOATTYPE_REPR(_this->_v(0), p); + p += strlen(p); + *(p++) = ','; + *(p++) = ' '; + FLOATTYPE_REPR(_this->_v(1), p); + p += strlen(p); + *(p++) = ')'; + *p = '\0'; + return std::string(buf, p - buf); } /** diff --git a/panda/src/linmath/lvector3_ext_src.I b/panda/src/linmath/lvector3_ext_src.I index 1c309ef87e..7b7403384b 100644 --- a/panda/src/linmath/lvector3_ext_src.I +++ b/panda/src/linmath/lvector3_ext_src.I @@ -16,12 +16,23 @@ */ INLINE_LINMATH std::string Extension:: __repr__() const { - std::ostringstream out; - out << "LVector3" << FLOATTOKEN << "(" - << MAYBE_ZERO(_this->_v(0)) << ", " - << MAYBE_ZERO(_this->_v(1)) << ", " - << MAYBE_ZERO(_this->_v(2)) << ")"; - return out.str(); + char buf[128] = "LVector3"; + char *p = buf + strlen(buf); + *(p++) = FLOATTOKEN; + *(p++) = '('; + FLOATTYPE_REPR(_this->_v(0), p); + p += strlen(p); + *(p++) = ','; + *(p++) = ' '; + FLOATTYPE_REPR(_this->_v(1), p); + p += strlen(p); + *(p++) = ','; + *(p++) = ' '; + FLOATTYPE_REPR(_this->_v(2), p); + p += strlen(p); + *(p++) = ')'; + *p = '\0'; + return std::string(buf, p - buf); } /** diff --git a/panda/src/linmath/lvector4_ext_src.I b/panda/src/linmath/lvector4_ext_src.I index dd8b3a6b48..4a2fc80ca6 100644 --- a/panda/src/linmath/lvector4_ext_src.I +++ b/panda/src/linmath/lvector4_ext_src.I @@ -16,13 +16,27 @@ */ INLINE_LINMATH std::string Extension:: __repr__() const { - std::ostringstream out; - out << "LVector4" << FLOATTOKEN << "(" - << MAYBE_ZERO(_this->_v(0)) << ", " - << MAYBE_ZERO(_this->_v(1)) << ", " - << MAYBE_ZERO(_this->_v(2)) << ", " - << MAYBE_ZERO(_this->_v(3)) << ")"; - return out.str(); + char buf[160] = "LVector4"; + char *p = buf + strlen(buf); + *(p++) = FLOATTOKEN; + *(p++) = '('; + FLOATTYPE_REPR(_this->_v(0), p); + p += strlen(p); + *(p++) = ','; + *(p++) = ' '; + FLOATTYPE_REPR(_this->_v(1), p); + p += strlen(p); + *(p++) = ','; + *(p++) = ' '; + FLOATTYPE_REPR(_this->_v(2), p); + p += strlen(p); + *(p++) = ','; + *(p++) = ' '; + FLOATTYPE_REPR(_this->_v(3), p); + p += strlen(p); + *(p++) = ')'; + *p = '\0'; + return std::string(buf, p - buf); } /** diff --git a/panda/src/x11display/x11GraphicsWindow.cxx b/panda/src/x11display/x11GraphicsWindow.cxx index 3fc30c5692..49c1e19b13 100644 --- a/panda/src/x11display/x11GraphicsWindow.cxx +++ b/panda/src/x11display/x11GraphicsWindow.cxx @@ -1321,6 +1321,15 @@ set_wm_properties(const WindowProperties &properties, bool already_mapped) { if (XStringListToTextProperty((char **)&name, 1, &window_name) != 0) { window_name_p = &window_name; } + +#ifdef X_HAVE_UTF8_STRING + XTextProperty wm_name; + if (Xutf8TextListToTextProperty(_display, (char **)&name, 1, + XUTF8StringStyle, &wm_name) == Success) { + XSetTextProperty(_display, _xwindow, &wm_name, x11_pipe->_net_wm_name); + XFree(wm_name.value); + } +#endif } // The size hints request a window of a particular size andor a particular diff --git a/tests/linmath/test_lvector2.py b/tests/linmath/test_lvector2.py index 84bda15444..542ba2fe83 100644 --- a/tests/linmath/test_lvector2.py +++ b/tests/linmath/test_lvector2.py @@ -145,6 +145,17 @@ def test_vec2_floordiv(type): assert v.x == i // -j +def test_vec2_repr(): + assert repr(Vec2F(0.1, 0.2)) == "LVector2f(0.1, 0.2)" + assert repr(Vec2F(0.3, 0.4)) == "LVector2f(0.3, 0.4)" + assert repr(Vec2F(-0.9999999403953552, 1.00000001)) == "LVector2f(-0.99999994, 1)" + assert repr(Vec2F(0.00000001, 0.0)) == "LVector2f(1e-8, 0)" + assert repr(Vec2D(0.1, 0.2)) == "LVector2d(0.1, 0.2)" + assert repr(Vec2D(0.3, 0.4)) == "LVector2d(0.3, 0.4)" + assert repr(Vec2D(-0.9999999403953552, 1.00000001)) == "LVector2d(-0.9999999403953552, 1.00000001)" + assert repr(Vec2D(0.00000001, 0.0)) == "LVector2d(1e-8, 0)" + + def test_vec2_buffer(): v = Vec2(1.5, -10.0) m = memoryview(v) diff --git a/tests/linmath/test_lvector3.py b/tests/linmath/test_lvector3.py index e12a1650f0..ee4828d687 100644 --- a/tests/linmath/test_lvector3.py +++ b/tests/linmath/test_lvector3.py @@ -130,6 +130,19 @@ def test_vec3_floordiv(type): assert v.x == i // -j +def test_vec3_repr(): + assert repr(Vec3F(0.1, 0.2, 0.3)) == "LVector3f(0.1, 0.2, 0.3)" + assert repr(Vec3F(-0.9999999403953552, 1.00000001, 1)) == "LVector3f(-0.99999994, 1, 1)" + assert repr(Vec3F(-9.451235e29, 9.451234e-19, 1e-11)) == "LVector3f(-9.451235e29, 9.451234e-19, 1e-11)" + assert repr(Vec3F(0.001, 0.0001, 0.00001)) == "LVector3f(0.001, 0.0001, 0.00001)" + assert repr(Vec3F(-0.001, -0.0001, -0.00001)) == "LVector3f(-0.001, -0.0001, -0.00001)" + assert repr(Vec3D(0.1, 0.2, 0.3)) == "LVector3d(0.1, 0.2, 0.3)" + assert repr(Vec3D(-0.9999999403953552, 1.00000001, 1)) == "LVector3d(-0.9999999403953552, 1.00000001, 1)" + assert repr(Vec3D(-9.451235e29, 9.451234e-19, 1e-11)) == "LVector3d(-9.451235e29, 9.451234e-19, 1e-11)" + assert repr(Vec3D(0.001, 0.0001, 0.00001)) == "LVector3d(0.001, 0.0001, 0.00001)" + assert repr(Vec3D(-0.001, -0.0001, -0.00001)) == "LVector3d(-0.001, -0.0001, -0.00001)" + + def test_vec3_buffer(): v = Vec3(0.5, 2.0, -10.0) m = memoryview(v) diff --git a/tests/linmath/test_lvector4.py b/tests/linmath/test_lvector4.py index 060953fbc8..f061191fb5 100644 --- a/tests/linmath/test_lvector4.py +++ b/tests/linmath/test_lvector4.py @@ -146,6 +146,13 @@ def test_vec4_floordiv(type): assert v.x == i // -j +def test_vec4_repr(): + assert repr(Vec4F(0.1, 0.2, 0.3, 0.4)) == "LVector4f(0.1, 0.2, 0.3, 0.4)" + assert repr(Vec4F(-0.9999999403953552, 1.000001, 1e-8, 0.0)) == "LVector4f(-0.99999994, 1.000001, 1e-8, 0)" + assert repr(Vec4D(0.1, 0.2, 0.3, 0.4)) == "LVector4d(0.1, 0.2, 0.3, 0.4)" + assert repr(Vec4D(-0.9999999403953552, 1.00000001, 1e-8, 0.0)) == "LVector4d(-0.9999999403953552, 1.00000001, 1e-8, 0)" + + def test_vec4_buffer(): v = Vec4(0, 0.5, 2.0, -4.0) m = memoryview(v) diff --git a/tests/showbase/test_Loader.py b/tests/showbase/test_Loader.py index dbbe78e8e8..fe0c433326 100644 --- a/tests/showbase/test_Loader.py +++ b/tests/showbase/test_Loader.py @@ -90,7 +90,7 @@ class FnargleLoader: """) (tmp_path / "fnargle.dist-info").mkdir() (tmp_path / "fnargle.dist-info" / "METADATA").write_text(""" -Metadata-Version: 2.0 +Metadata-Version: 2.1 Name: fnargle Version: 1.0.0 """)