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
-[
](https://changecrab.com/) 
+[
](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
""")