From e6036b5209f5458d6e534bd08c8b029d8d824253 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 10 Oct 2022 15:05:04 +0200 Subject: [PATCH 01/10] interrogatedb: More queries for function wrappers: - `interrogate_wrapper_function(wrapper)` - `interrogate_wrapper_is_copy_constructor(wrapper)` - `interrogate_wrapper_is_coerce_constructor(wrapper)` --- dtool/metalibs/dtoolconfig/pydtool.cxx | 52 +++++++++++++++++++ dtool/src/interrogate/functionRemap.cxx | 8 +++ .../interrogateFunctionWrapper.I | 16 ++++++ .../interrogateFunctionWrapper.h | 6 ++- .../interrogatedb/interrogate_interface.cxx | 18 +++++++ .../src/interrogatedb/interrogate_interface.h | 9 ++++ 6 files changed, 108 insertions(+), 1 deletion(-) diff --git a/dtool/metalibs/dtoolconfig/pydtool.cxx b/dtool/metalibs/dtoolconfig/pydtool.cxx index fa5474a18c..86b409dfa0 100644 --- a/dtool/metalibs/dtoolconfig/pydtool.cxx +++ b/dtool/metalibs/dtoolconfig/pydtool.cxx @@ -74,7 +74,10 @@ static PyObject *_inP07yt3zru(PyObject *self, PyObject *args); static PyObject *_inP07ytRrg2(PyObject *self, PyObject *args); static PyObject *_inP07ytEJCx(PyObject *self, PyObject *args); static PyObject *_inP07ytWAZr(PyObject *self, PyObject *args); +static PyObject *_inP07ytHQi6(PyObject *self, PyObject *args); static PyObject *_inP07ytrD_M(PyObject *self, PyObject *args); +static PyObject *_inP07ytYaah(PyObject *self, PyObject *args); +static PyObject *_inP07yt2otr(PyObject *self, PyObject *args); static PyObject *_inP07ytjolz(PyObject *self, PyObject *args); static PyObject *_inP07ytt_JD(PyObject *self, PyObject *args); static PyObject *_inP07ytwEts(PyObject *self, PyObject *args); @@ -1060,6 +1063,24 @@ _inP07ytWAZr(PyObject *, PyObject *args) { return nullptr; } +/* + * Python simple wrapper for + * FunctionIndex interrogate_wrapper_function(FunctionWrapperIndex wrapper) + */ +static PyObject * +_inP07ytHQi6(PyObject *, PyObject *args) { + int param0; + if (PyArg_ParseTuple(args, "i", ¶m0)) { + FunctionIndex return_value = (::interrogate_wrapper_function)((FunctionWrapperIndex)param0); +#if PY_MAJOR_VERSION >= 3 + return PyLong_FromLong(return_value); +#else + return PyInt_FromLong(return_value); +#endif + } + return nullptr; +} + /* * Python simple wrapper for * bool interrogate_wrapper_is_callable_by_name(FunctionWrapperIndex wrapper) @@ -1074,6 +1095,34 @@ _inP07ytrD_M(PyObject *, PyObject *args) { return nullptr; } +/* + * Python simple wrapper for + * bool interrogate_wrapper_is_copy_constructor(FunctionWrapperIndex wrapper) + */ +static PyObject * +_inP07ytYaah(PyObject *, PyObject *args) { + int param0; + if (PyArg_ParseTuple(args, "i", ¶m0)) { + bool return_value = (::interrogate_wrapper_is_copy_constructor)((FunctionWrapperIndex)param0); + return PyBool_FromLong(return_value); + } + return nullptr; +} + +/* + * Python simple wrapper for + * bool interrogate_wrapper_is_coerce_constructor(FunctionWrapperIndex wrapper) + */ +static PyObject * +_inP07yt2otr(PyObject *, PyObject *args) { + int param0; + if (PyArg_ParseTuple(args, "i", ¶m0)) { + bool return_value = (::interrogate_wrapper_is_coerce_constructor)((FunctionWrapperIndex)param0); + return PyBool_FromLong(return_value); + } + return nullptr; +} + /* * Python simple wrapper for * bool interrogate_wrapper_has_comment(FunctionWrapperIndex wrapper) @@ -2681,7 +2730,10 @@ static PyMethodDef python_simple_funcs[] = { { "interrogate_function_number_of_python_wrappers", &_inP07ytRrg2, METH_VARARGS }, { "interrogate_function_python_wrapper", &_inP07ytEJCx, METH_VARARGS }, { "interrogate_wrapper_name", &_inP07ytWAZr, METH_VARARGS }, + { "interrogate_wrapper_function", &_inP07ytHQi6, METH_VARARGS }, { "interrogate_wrapper_is_callable_by_name", &_inP07ytrD_M, METH_VARARGS }, + { "interrogate_wrapper_is_copy_constructor", &_inP07ytYaah, METH_VARARGS }, + { "interrogate_wrapper_is_coerce_constructor", &_inP07yt2otr, METH_VARARGS }, { "interrogate_wrapper_has_comment", &_inP07ytjolz, METH_VARARGS }, { "interrogate_wrapper_comment", &_inP07ytt_JD, METH_VARARGS }, { "interrogate_wrapper_has_return_value", &_inP07ytwEts, METH_VARARGS }, diff --git a/dtool/src/interrogate/functionRemap.cxx b/dtool/src/interrogate/functionRemap.cxx index cb8f9906a8..a66126c56b 100644 --- a/dtool/src/interrogate/functionRemap.cxx +++ b/dtool/src/interrogate/functionRemap.cxx @@ -312,6 +312,14 @@ make_wrapper_entry(FunctionIndex function_index) { iwrapper._flags |= InterrogateFunctionWrapper::F_callable_by_name; } + if (_flags & F_copy_constructor) { + iwrapper._flags |= InterrogateFunctionWrapper::F_copy_constructor; + } + + if (_flags & F_coerce_constructor) { + iwrapper._flags |= InterrogateFunctionWrapper::F_coerce_constructor; + } + Parameters::const_iterator pi; for (pi = _parameters.begin(); pi != _parameters.end(); diff --git a/dtool/src/interrogatedb/interrogateFunctionWrapper.I b/dtool/src/interrogatedb/interrogateFunctionWrapper.I index b0ec398623..67225f0c72 100644 --- a/dtool/src/interrogatedb/interrogateFunctionWrapper.I +++ b/dtool/src/interrogatedb/interrogateFunctionWrapper.I @@ -63,6 +63,22 @@ is_callable_by_name() const { return (_flags & F_callable_by_name) != 0; } +/** + * @since 1.10.13 + */ +INLINE bool InterrogateFunctionWrapper:: +is_copy_constructor() const { + return (_flags & F_copy_constructor) != 0; +} + +/** + * @since 1.10.13 + */ +INLINE bool InterrogateFunctionWrapper:: +is_coerce_constructor() const { + return (_flags & F_coerce_constructor) != 0; +} + /** * */ diff --git a/dtool/src/interrogatedb/interrogateFunctionWrapper.h b/dtool/src/interrogatedb/interrogateFunctionWrapper.h index 29e59ed259..6af5e49d72 100644 --- a/dtool/src/interrogatedb/interrogateFunctionWrapper.h +++ b/dtool/src/interrogatedb/interrogateFunctionWrapper.h @@ -34,6 +34,8 @@ public: INLINE FunctionIndex get_function() const; INLINE bool is_callable_by_name() const; + INLINE bool is_copy_constructor() const; + INLINE bool is_coerce_constructor() const; INLINE bool has_return_value() const; INLINE TypeIndex get_return_type() const; @@ -61,7 +63,9 @@ private: enum Flags { F_caller_manages = 0x0001, F_has_return = 0x0002, - F_callable_by_name = 0x0004 + F_callable_by_name = 0x0004, + F_copy_constructor = 0x0008, + F_coerce_constructor = 0x0010, }; enum ParameterFlags { diff --git a/dtool/src/interrogatedb/interrogate_interface.cxx b/dtool/src/interrogatedb/interrogate_interface.cxx index d7f4ce58dd..4ec3f28e24 100644 --- a/dtool/src/interrogatedb/interrogate_interface.cxx +++ b/dtool/src/interrogatedb/interrogate_interface.cxx @@ -359,12 +359,30 @@ interrogate_wrapper_name(FunctionWrapperIndex wrapper) { return result.c_str(); } +FunctionIndex +interrogate_wrapper_function(FunctionWrapperIndex wrapper) { + // cerr << "interrogate_wrapper_function(" << wrapper << ")\n"; + return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).get_function(); +} + bool interrogate_wrapper_is_callable_by_name(FunctionWrapperIndex wrapper) { // cerr << "interrogate_wrapper_is_callable_by_name(" << wrapper << ")\n"; return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).is_callable_by_name(); } +bool +interrogate_wrapper_is_copy_constructor(FunctionWrapperIndex wrapper) { + // cerr << "interrogate_wrapper_is_copy_constructor(" << wrapper << ")\n"; + return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).is_copy_constructor(); +} + +bool +interrogate_wrapper_is_coerce_constructor(FunctionWrapperIndex wrapper) { + // cerr << "interrogate_wrapper_is_coerce_constructor(" << wrapper << ")\n"; + return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).is_coerce_constructor(); +} + bool interrogate_wrapper_has_comment(FunctionWrapperIndex wrapper) { // cerr << "interrogate_wrapper_has_comment(" << wrapper << ")\n"; diff --git a/dtool/src/interrogatedb/interrogate_interface.h b/dtool/src/interrogatedb/interrogate_interface.h index a44f9fef92..4f9d045df5 100644 --- a/dtool/src/interrogatedb/interrogate_interface.h +++ b/dtool/src/interrogatedb/interrogate_interface.h @@ -261,10 +261,19 @@ EXPCL_INTERROGATEDB FunctionWrapperIndex interrogate_function_python_wrapper(Fun // not identical. EXPCL_INTERROGATEDB const char *interrogate_wrapper_name(FunctionWrapperIndex wrapper); +// Returns the function that this wrapper belongs to. +EXPCL_INTERROGATEDB FunctionIndex interrogate_wrapper_function(FunctionWrapperIndex wrapper); + // This returns true if -fnames was given to interrogate, making the wrapper // function callable directly by its name. EXPCL_INTERROGATEDB bool interrogate_wrapper_is_callable_by_name(FunctionWrapperIndex wrapper); +// This returns true if this is a copy constructor. +EXPCL_INTERROGATEDB bool interrogate_wrapper_is_copy_constructor(FunctionWrapperIndex wrapper); + +// This returns true if this is a constructor that is not marked "explicit". +EXPCL_INTERROGATEDB bool interrogate_wrapper_is_coerce_constructor(FunctionWrapperIndex wrapper); + // This returns the C++ comment written for the function wrapper, usually from // the .cpp file. There may be a different comment for each overload of a // given function. From 834be5c7a01b3873f6716749a21c08797c7fb325 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 10 Oct 2022 15:10:53 +0200 Subject: [PATCH 02/10] interrogate: Fix some badly formatted code --- dtool/src/interrogate/interrogate.cxx | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/dtool/src/interrogate/interrogate.cxx b/dtool/src/interrogate/interrogate.cxx index 162621a580..2b2a756727 100644 --- a/dtool/src/interrogate/interrogate.cxx +++ b/dtool/src/interrogate/interrogate.cxx @@ -417,8 +417,8 @@ main(int argc, char **argv) { break; case CO_python_native: - build_python_native = true; - break; + build_python_native = true; + break; case CO_track_interpreter: track_interpreter = true; @@ -595,22 +595,21 @@ main(int argc, char **argv) { << " *\n" << " */\n\n"; - if(the_output_include != nullptr) - { - output_code << "#include \""< Date: Mon, 17 Oct 2022 16:39:42 +0200 Subject: [PATCH 03/10] makepanda: Copy missing CMotionTrail header file --- makepanda/makepanda.py | 1 + 1 file changed, 1 insertion(+) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index f8ff2e1725..ec7754ad58 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -3680,6 +3680,7 @@ if (PkgSkip("DIRECT")==0): CopyAllHeaders('direct/src/distributed') CopyAllHeaders('direct/src/interval') CopyAllHeaders('direct/src/showbase') + CopyAllHeaders('direct/src/motiontrail') CopyAllHeaders('direct/src/dcparse') if (RUNTIME or RTDIST): From a8eef28708aad83c7364c7e86391aab39044ab8f Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 19 Oct 2022 12:20:06 +0200 Subject: [PATCH 04/10] glgsg: Fix error when downloading luminance8 texture --- panda/src/glstuff/glGraphicsStateGuardian_src.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index fc304d8a96..24bd54134d 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -14460,6 +14460,7 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { break; case GL_LUMINANCE: #ifndef OPENGLES + case GL_LUMINANCE8_EXT: case GL_LUMINANCE16: case GL_LUMINANCE16F_ARB: #endif From 77e3033c428ed3bc9f1f86d35cf1d3c49f4f0aec Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 19 Oct 2022 15:45:40 +0200 Subject: [PATCH 05/10] makepanda: Fix ExecutionEnvironment.args being empty on Linux --- makepanda/makepanda.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index ec7754ad58..c7d2c5d309 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -2617,7 +2617,7 @@ DTOOL_CONFIG=[ ("HAVE_PROC_SELF_CMDLINE", 'UNDEF', '1'), ("HAVE_PROC_CURPROC_FILE", 'UNDEF', 'UNDEF'), ("HAVE_PROC_CURPROC_MAP", 'UNDEF', 'UNDEF'), - ("HAVE_PROC_SELF_CMDLINE", 'UNDEF', 'UNDEF'), + ("HAVE_PROC_CURPROC_CMDLINE", 'UNDEF', 'UNDEF'), ("HAVE_GLOBAL_ARGV", '1', 'UNDEF'), ("PROTOTYPE_GLOBAL_ARGV", 'UNDEF', 'UNDEF'), ("GLOBAL_ARGV", '__argv', 'UNDEF'), From 0c03dfca05f795ddf0964b4e0034ec980d054fd0 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 19 Oct 2022 16:04:15 +0200 Subject: [PATCH 06/10] egg: Some comment reformatting [skip ci] --- panda/src/egg/eggPrimitive.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/panda/src/egg/eggPrimitive.h b/panda/src/egg/eggPrimitive.h index 4b8a035952..ebf3bab2c5 100644 --- a/panda/src/egg/eggPrimitive.h +++ b/panda/src/egg/eggPrimitive.h @@ -134,10 +134,9 @@ PUBLISHED: virtual bool joint_has_primitives() const; virtual bool has_normals() const; - // The EggPrimitive itself appears to be an STL container of pointers to // EggVertex objects. The set of vertices is read-only, however, except - // through the limited add_vertexremove_vertex or inserterase interface. + // through the limited add_vertex/remove_vertex or insert/erase interface. // The following implements this. public: #if defined(WIN32_VC) || defined(WIN64_VC) @@ -203,8 +202,8 @@ protected: Vertices _vertices; // Don't try to use these private functions. User code should add and - // remove vertices via add_vertex()remove_vertex(), or via the STL-like - // push_back()pop_back() or insert()erase(), above. + // remove vertices via add_vertex() / remove_vertex(), or via the STL-like + // push_back() / pop_back() or insert() / erase(), above. virtual void prepare_add_vertex(EggVertex *vertex, int i, int n); virtual void prepare_remove_vertex(EggVertex *vertex, int i, int n); From 25d11b3b17b1f1a037c53f4febacc2b719890ed3 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 19 Oct 2022 16:04:37 +0200 Subject: [PATCH 07/10] interrogatedb: Add more query functions for seq/map elements --- dtool/metalibs/dtoolconfig/pydtool.cxx | 200 ++++++++++++++++++ .../interrogatedb/interrogate_interface.cxx | 66 ++++++ .../src/interrogatedb/interrogate_interface.h | 11 + 3 files changed, 277 insertions(+) diff --git a/dtool/metalibs/dtoolconfig/pydtool.cxx b/dtool/metalibs/dtoolconfig/pydtool.cxx index 86b409dfa0..a3112f2a58 100644 --- a/dtool/metalibs/dtoolconfig/pydtool.cxx +++ b/dtool/metalibs/dtoolconfig/pydtool.cxx @@ -45,6 +45,17 @@ static PyObject *_inP07ytDId0(PyObject *self, PyObject *args); static PyObject *_inP07ytHuAm(PyObject *self, PyObject *args); static PyObject *_inP07yt_xr0(PyObject *self, PyObject *args); static PyObject *_inP07ytH5qp(PyObject *self, PyObject *args); +static PyObject *_inP07ytLfJw(PyObject *self, PyObject *args); +static PyObject *_inP07yt_Atg(PyObject *self, PyObject *args); +static PyObject *_inP07ytlBqc(PyObject *self, PyObject *args); +static PyObject *_inP07ytNdUp(PyObject *self, PyObject *args); +static PyObject *_inP07ytlS0p(PyObject *self, PyObject *args); +static PyObject *_inP07ytZZe7(PyObject *self, PyObject *args); +static PyObject *_inP07ytV5S_(PyObject *self, PyObject *args); +static PyObject *_inP07yto9vD(PyObject *self, PyObject *args); +static PyObject *_inP07ytv7tF(PyObject *self, PyObject *args); +static PyObject *_inP07ythOg6(PyObject *self, PyObject *args); +static PyObject *_inP07ytoZUn(PyObject *self, PyObject *args); static PyObject *_inP07ytq45U(PyObject *self, PyObject *args); static PyObject *_inP07yt6IPa(PyObject *self, PyObject *args); static PyObject *_inP07ytU2_B(PyObject *self, PyObject *args); @@ -586,6 +597,184 @@ _inP07ytH5qp(PyObject *, PyObject *args) { return nullptr; } +/* + * Python simple wrapper for + * bool interrogate_element_has_has_function(ElementIndex element) + */ +static PyObject * +_inP07ytLfJw(PyObject *, PyObject *args) { + int param0; + if (PyArg_ParseTuple(args, "i", ¶m0)) { + bool return_value = (::interrogate_element_has_has_function)((ElementIndex)param0); + return PyBool_FromLong(return_value); + } + return nullptr; +} + +/* + * Python simple wrapper for + * FunctionIndex interrogate_element_has_function(ElementIndex element) + */ +static PyObject * +_inP07yt_Atg(PyObject *, PyObject *args) { + int param0; + if (PyArg_ParseTuple(args, "i", ¶m0)) { + FunctionIndex return_value = (::interrogate_element_has_function)((ElementIndex)param0); +#if PY_MAJOR_VERSION >= 3 + return PyLong_FromLong(return_value); +#else + return PyInt_FromLong(return_value); +#endif + } + return nullptr; +} + +/* + * Python simple wrapper for + * bool interrogate_element_has_clear_function(ElementIndex element) + */ +static PyObject * +_inP07ytlBqc(PyObject *, PyObject *args) { + int param0; + if (PyArg_ParseTuple(args, "i", ¶m0)) { + bool return_value = (::interrogate_element_has_clear_function)((ElementIndex)param0); + return PyBool_FromLong(return_value); + } + return nullptr; +} + +/* + * Python simple wrapper for + * FunctionIndex interrogate_element_clear_function(ElementIndex element) + */ +static PyObject * +_inP07ytNdUp(PyObject *, PyObject *args) { + int param0; + if (PyArg_ParseTuple(args, "i", ¶m0)) { + FunctionIndex return_value = (::interrogate_element_clear_function)((ElementIndex)param0); +#if PY_MAJOR_VERSION >= 3 + return PyLong_FromLong(return_value); +#else + return PyInt_FromLong(return_value); +#endif + } + return nullptr; +} + +/* + * Python simple wrapper for + * bool interrogate_element_has_del_function(ElementIndex element) + */ +static PyObject * +_inP07ytlS0p(PyObject *, PyObject *args) { + int param0; + if (PyArg_ParseTuple(args, "i", ¶m0)) { + bool return_value = (::interrogate_element_has_del_function)((ElementIndex)param0); + return PyBool_FromLong(return_value); + } + return nullptr; +} + +/* + * Python simple wrapper for + * FunctionIndex interrogate_element_del_function(ElementIndex element) + */ +static PyObject * +_inP07ytZZe7(PyObject *, PyObject *args) { + int param0; + if (PyArg_ParseTuple(args, "i", ¶m0)) { + FunctionIndex return_value = (::interrogate_element_del_function)((ElementIndex)param0); +#if PY_MAJOR_VERSION >= 3 + return PyLong_FromLong(return_value); +#else + return PyInt_FromLong(return_value); +#endif + } + return nullptr; +} + +/* + * Python simple wrapper for + * bool interrogate_element_has_insert_function(ElementIndex element) + */ +static PyObject * +_inP07ytV5S_(PyObject *, PyObject *args) { + int param0; + if (PyArg_ParseTuple(args, "i", ¶m0)) { + bool return_value = (::interrogate_element_has_insert_function)((ElementIndex)param0); + return PyBool_FromLong(return_value); + } + return nullptr; +} + +/* + * Python simple wrapper for + * FunctionIndex interrogate_element_insert_function(ElementIndex element) + */ +static PyObject * +_inP07yto9vD(PyObject *, PyObject *args) { + int param0; + if (PyArg_ParseTuple(args, "i", ¶m0)) { + FunctionIndex return_value = (::interrogate_element_insert_function)((ElementIndex)param0); +#if PY_MAJOR_VERSION >= 3 + return PyLong_FromLong(return_value); +#else + return PyInt_FromLong(return_value); +#endif + } + return nullptr; +} + +/* + * Python simple wrapper for + * bool interrogate_element_has_getkey_function(ElementIndex element) + */ +static PyObject * +_inP07ytv7tF(PyObject *, PyObject *args) { + int param0; + if (PyArg_ParseTuple(args, "i", ¶m0)) { + bool return_value = (::interrogate_element_has_getkey_function)((ElementIndex)param0); + return PyBool_FromLong(return_value); + } + return nullptr; +} + +/* + * Python simple wrapper for + * FunctionIndex interrogate_element_getkey_function(ElementIndex element) + */ +static PyObject * +_inP07ythOg6(PyObject *, PyObject *args) { + int param0; + if (PyArg_ParseTuple(args, "i", ¶m0)) { + FunctionIndex return_value = (::interrogate_element_getkey_function)((ElementIndex)param0); +#if PY_MAJOR_VERSION >= 3 + return PyLong_FromLong(return_value); +#else + return PyInt_FromLong(return_value); +#endif + } + return nullptr; +} + +/* + * Python simple wrapper for + * FunctionIndex interrogate_element_length_function(ElementIndex element) + */ +static PyObject * +_inP07ytoZUn(PyObject *, PyObject *args) { + int param0; + if (PyArg_ParseTuple(args, "i", ¶m0)) { + FunctionIndex return_value = (::interrogate_element_length_function)((ElementIndex)param0); +#if PY_MAJOR_VERSION >= 3 + return PyLong_FromLong(return_value); +#else + return PyInt_FromLong(return_value); +#endif + } + return nullptr; +} + /* * Python simple wrapper for * bool interrogate_element_is_sequence(ElementIndex element) @@ -2701,6 +2890,17 @@ static PyMethodDef python_simple_funcs[] = { { "interrogate_element_getter", &_inP07ytHuAm, METH_VARARGS }, { "interrogate_element_has_setter", &_inP07yt_xr0, METH_VARARGS }, { "interrogate_element_setter", &_inP07ytH5qp, METH_VARARGS }, + { "interrogate_element_has_has_function", &_inP07ytLfJw, METH_VARARGS }, + { "interrogate_element_has_function", &_inP07yt_Atg, METH_VARARGS }, + { "interrogate_element_has_clear_function", &_inP07ytlBqc, METH_VARARGS }, + { "interrogate_element_clear_function", &_inP07ytNdUp, METH_VARARGS }, + { "interrogate_element_has_del_function", &_inP07ytlS0p, METH_VARARGS }, + { "interrogate_element_del_function", &_inP07ytZZe7, METH_VARARGS }, + { "interrogate_element_has_insert_function", &_inP07ytV5S_, METH_VARARGS }, + { "interrogate_element_insert_function", &_inP07yto9vD, METH_VARARGS }, + { "interrogate_element_has_getkey_function", &_inP07ytv7tF, METH_VARARGS }, + { "interrogate_element_getkey_function", &_inP07ythOg6, METH_VARARGS }, + { "interrogate_element_length_function", &_inP07ytoZUn, METH_VARARGS }, { "interrogate_element_is_sequence", &_inP07ytq45U, METH_VARARGS }, { "interrogate_element_is_mapping", &_inP07yt6IPa, METH_VARARGS }, { "interrogate_number_of_globals", &_inP07ytU2_B, METH_VARARGS }, diff --git a/dtool/src/interrogatedb/interrogate_interface.cxx b/dtool/src/interrogatedb/interrogate_interface.cxx index 4ec3f28e24..b4515f72c9 100644 --- a/dtool/src/interrogatedb/interrogate_interface.cxx +++ b/dtool/src/interrogatedb/interrogate_interface.cxx @@ -176,6 +176,72 @@ interrogate_element_setter(ElementIndex element) { return InterrogateDatabase::get_ptr()->get_element(element).get_setter(); } +bool +interrogate_element_has_has_function(ElementIndex element) { + // cerr << "interrogate_element_has_has_function(" << element << ")\n"; + return InterrogateDatabase::get_ptr()->get_element(element).has_has_function(); +} + +FunctionIndex +interrogate_element_has_function(ElementIndex element) { + // cerr << "interrogate_element_has_function(" << element << ")\n"; + return InterrogateDatabase::get_ptr()->get_element(element).get_has_function(); +} + +bool +interrogate_element_has_clear_function(ElementIndex element) { + // cerr << "interrogate_element_has_clear_function(" << element << ")\n"; + return InterrogateDatabase::get_ptr()->get_element(element).has_clear_function(); +} + +FunctionIndex +interrogate_element_clear_function(ElementIndex element) { + // cerr << "interrogate_element_clear_function(" << element << ")\n"; + return InterrogateDatabase::get_ptr()->get_element(element).get_clear_function(); +} + +bool +interrogate_element_has_del_function(ElementIndex element) { + // cerr << "interrogate_element_has_del_function(" << element << ")\n"; + return InterrogateDatabase::get_ptr()->get_element(element).has_del_function(); +} + +FunctionIndex +interrogate_element_del_function(ElementIndex element) { + // cerr << "interrogate_element_del_function(" << element << ")\n"; + return InterrogateDatabase::get_ptr()->get_element(element).get_del_function(); +} + +bool +interrogate_element_has_insert_function(ElementIndex element) { + // cerr << "interrogate_element_has_insert_function(" << element << ")\n"; + return InterrogateDatabase::get_ptr()->get_element(element).has_insert_function(); +} + +FunctionIndex +interrogate_element_insert_function(ElementIndex element) { + // cerr << "interrogate_element_insert_function(" << element << ")\n"; + return InterrogateDatabase::get_ptr()->get_element(element).get_insert_function(); +} + +bool +interrogate_element_has_getkey_function(ElementIndex element) { + // cerr << "interrogate_element_has_getkey_function(" << element << ")\n"; + return InterrogateDatabase::get_ptr()->get_element(element).has_getkey_function(); +} + +FunctionIndex +interrogate_element_getkey_function(ElementIndex element) { + // cerr << "interrogate_element_getkey_function(" << element << ")\n"; + return InterrogateDatabase::get_ptr()->get_element(element).get_getkey_function(); +} + +FunctionIndex +interrogate_element_length_function(ElementIndex element) { + // cerr << "interrogate_element_length_function(" << element << ")\n"; + return InterrogateDatabase::get_ptr()->get_element(element).get_length_function(); +} + bool interrogate_element_is_sequence(ElementIndex element) { // cerr << "interrogate_element_is_sequence(" << element << ")\n"; diff --git a/dtool/src/interrogatedb/interrogate_interface.h b/dtool/src/interrogatedb/interrogate_interface.h index 4f9d045df5..be5562ec40 100644 --- a/dtool/src/interrogatedb/interrogate_interface.h +++ b/dtool/src/interrogatedb/interrogate_interface.h @@ -152,6 +152,17 @@ EXPCL_INTERROGATEDB bool interrogate_element_has_getter(ElementIndex element); EXPCL_INTERROGATEDB FunctionIndex interrogate_element_getter(ElementIndex element); EXPCL_INTERROGATEDB bool interrogate_element_has_setter(ElementIndex element); EXPCL_INTERROGATEDB FunctionIndex interrogate_element_setter(ElementIndex element); +EXPCL_INTERROGATEDB bool interrogate_element_has_has_function(ElementIndex element); +EXPCL_INTERROGATEDB FunctionIndex interrogate_element_has_function(ElementIndex element); +EXPCL_INTERROGATEDB bool interrogate_element_has_clear_function(ElementIndex element); +EXPCL_INTERROGATEDB FunctionIndex interrogate_element_clear_function(ElementIndex element); +EXPCL_INTERROGATEDB bool interrogate_element_has_del_function(ElementIndex element); +EXPCL_INTERROGATEDB FunctionIndex interrogate_element_del_function(ElementIndex element); +EXPCL_INTERROGATEDB bool interrogate_element_has_insert_function(ElementIndex element); +EXPCL_INTERROGATEDB FunctionIndex interrogate_element_insert_function(ElementIndex element); +EXPCL_INTERROGATEDB bool interrogate_element_has_getkey_function(ElementIndex element); +EXPCL_INTERROGATEDB FunctionIndex interrogate_element_getkey_function(ElementIndex element); +EXPCL_INTERROGATEDB FunctionIndex interrogate_element_length_function(ElementIndex element); EXPCL_INTERROGATEDB bool interrogate_element_is_sequence(ElementIndex element); EXPCL_INTERROGATEDB bool interrogate_element_is_mapping(ElementIndex element); From 0b7c694f10da1812beb42d9192db755e61b8d142 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 19 Oct 2022 16:04:57 +0200 Subject: [PATCH 08/10] linmath: Make mat.rows[n] and mat.cols[n] assignable to --- panda/src/linmath/lmatrix3_src.h | 4 ++-- panda/src/linmath/lmatrix4_src.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/panda/src/linmath/lmatrix3_src.h b/panda/src/linmath/lmatrix3_src.h index 2138f0fc39..920d2c2509 100644 --- a/panda/src/linmath/lmatrix3_src.h +++ b/panda/src/linmath/lmatrix3_src.h @@ -90,8 +90,8 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LVecBase3) get_col(int col) const; MAKE_SEQ(get_rows, size, get_row); MAKE_SEQ(get_cols, size, get_col); - MAKE_SEQ_PROPERTY(rows, size, get_row); - MAKE_SEQ_PROPERTY(cols, size, get_col); + MAKE_SEQ_PROPERTY(rows, size, get_row, set_row); + MAKE_SEQ_PROPERTY(cols, size, get_col, set_col); INLINE_LINMATH FLOATNAME(LVecBase2) get_row2(int row) const; INLINE_LINMATH FLOATNAME(LVecBase2) get_col2(int col) const; diff --git a/panda/src/linmath/lmatrix4_src.h b/panda/src/linmath/lmatrix4_src.h index a66a5ab45f..caa38b6788 100644 --- a/panda/src/linmath/lmatrix4_src.h +++ b/panda/src/linmath/lmatrix4_src.h @@ -105,8 +105,8 @@ PUBLISHED: MAKE_SEQ(get_rows, size, get_row); MAKE_SEQ(get_cols, size, get_col); MAKE_SEQ(get_row3s, size, get_row3); - MAKE_SEQ_PROPERTY(rows, size, get_row); - MAKE_SEQ_PROPERTY(cols, size, get_col); + MAKE_SEQ_PROPERTY(rows, size, get_row, set_row); + MAKE_SEQ_PROPERTY(cols, size, get_col, set_col); // these versions inline better INLINE_LINMATH void get_row(FLOATNAME(LVecBase4) &result_vec, int row) const; From bb8b08a69077f704e2f8afdbaa16734c3b2e6eff Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 20 Oct 2022 10:09:45 +0200 Subject: [PATCH 09/10] interrogatedb: Add `interrogate_wrapper_is_extension()` function --- dtool/metalibs/dtoolconfig/pydtool.cxx | 16 ++++++++++++++++ dtool/src/interrogate/functionRemap.cxx | 4 ++++ .../interrogatedb/interrogateFunctionWrapper.I | 8 ++++++++ .../interrogatedb/interrogateFunctionWrapper.h | 2 ++ .../src/interrogatedb/interrogate_interface.cxx | 6 ++++++ dtool/src/interrogatedb/interrogate_interface.h | 4 ++++ 6 files changed, 40 insertions(+) diff --git a/dtool/metalibs/dtoolconfig/pydtool.cxx b/dtool/metalibs/dtoolconfig/pydtool.cxx index a3112f2a58..cdfdb3e14f 100644 --- a/dtool/metalibs/dtoolconfig/pydtool.cxx +++ b/dtool/metalibs/dtoolconfig/pydtool.cxx @@ -89,6 +89,7 @@ static PyObject *_inP07ytHQi6(PyObject *self, PyObject *args); static PyObject *_inP07ytrD_M(PyObject *self, PyObject *args); static PyObject *_inP07ytYaah(PyObject *self, PyObject *args); static PyObject *_inP07yt2otr(PyObject *self, PyObject *args); +static PyObject *_inP07ytNP_b(PyObject *self, PyObject *args); static PyObject *_inP07ytjolz(PyObject *self, PyObject *args); static PyObject *_inP07ytt_JD(PyObject *self, PyObject *args); static PyObject *_inP07ytwEts(PyObject *self, PyObject *args); @@ -1312,6 +1313,20 @@ _inP07yt2otr(PyObject *, PyObject *args) { return nullptr; } +/* + * Python simple wrapper for + * bool interrogate_wrapper_is_extension(FunctionWrapperIndex wrapper) + */ +static PyObject * +_inP07ytNP_b(PyObject *, PyObject *args) { + int param0; + if (PyArg_ParseTuple(args, "i", ¶m0)) { + bool return_value = (::interrogate_wrapper_is_extension)((FunctionWrapperIndex)param0); + return PyBool_FromLong(return_value); + } + return nullptr; +} + /* * Python simple wrapper for * bool interrogate_wrapper_has_comment(FunctionWrapperIndex wrapper) @@ -2934,6 +2949,7 @@ static PyMethodDef python_simple_funcs[] = { { "interrogate_wrapper_is_callable_by_name", &_inP07ytrD_M, METH_VARARGS }, { "interrogate_wrapper_is_copy_constructor", &_inP07ytYaah, METH_VARARGS }, { "interrogate_wrapper_is_coerce_constructor", &_inP07yt2otr, METH_VARARGS }, + { "interrogate_wrapper_is_extension", &_inP07ytNP_b, METH_VARARGS }, { "interrogate_wrapper_has_comment", &_inP07ytjolz, METH_VARARGS }, { "interrogate_wrapper_comment", &_inP07ytt_JD, METH_VARARGS }, { "interrogate_wrapper_has_return_value", &_inP07ytwEts, METH_VARARGS }, diff --git a/dtool/src/interrogate/functionRemap.cxx b/dtool/src/interrogate/functionRemap.cxx index a66126c56b..2e984c652b 100644 --- a/dtool/src/interrogate/functionRemap.cxx +++ b/dtool/src/interrogate/functionRemap.cxx @@ -320,6 +320,10 @@ make_wrapper_entry(FunctionIndex function_index) { iwrapper._flags |= InterrogateFunctionWrapper::F_coerce_constructor; } + if (_extension) { + iwrapper._flags |= InterrogateFunctionWrapper::F_extension; + } + Parameters::const_iterator pi; for (pi = _parameters.begin(); pi != _parameters.end(); diff --git a/dtool/src/interrogatedb/interrogateFunctionWrapper.I b/dtool/src/interrogatedb/interrogateFunctionWrapper.I index 67225f0c72..111eba10c1 100644 --- a/dtool/src/interrogatedb/interrogateFunctionWrapper.I +++ b/dtool/src/interrogatedb/interrogateFunctionWrapper.I @@ -79,6 +79,14 @@ is_coerce_constructor() const { return (_flags & F_coerce_constructor) != 0; } +/** + * @since 1.10.13 + */ +INLINE bool InterrogateFunctionWrapper:: +is_extension() const { + return (_flags & F_extension) != 0; +} + /** * */ diff --git a/dtool/src/interrogatedb/interrogateFunctionWrapper.h b/dtool/src/interrogatedb/interrogateFunctionWrapper.h index 6af5e49d72..6c41a46cab 100644 --- a/dtool/src/interrogatedb/interrogateFunctionWrapper.h +++ b/dtool/src/interrogatedb/interrogateFunctionWrapper.h @@ -36,6 +36,7 @@ public: INLINE bool is_callable_by_name() const; INLINE bool is_copy_constructor() const; INLINE bool is_coerce_constructor() const; + INLINE bool is_extension() const; INLINE bool has_return_value() const; INLINE TypeIndex get_return_type() const; @@ -66,6 +67,7 @@ private: F_callable_by_name = 0x0004, F_copy_constructor = 0x0008, F_coerce_constructor = 0x0010, + F_extension = 0x0020, }; enum ParameterFlags { diff --git a/dtool/src/interrogatedb/interrogate_interface.cxx b/dtool/src/interrogatedb/interrogate_interface.cxx index b4515f72c9..e4dbef1a76 100644 --- a/dtool/src/interrogatedb/interrogate_interface.cxx +++ b/dtool/src/interrogatedb/interrogate_interface.cxx @@ -449,6 +449,12 @@ interrogate_wrapper_is_coerce_constructor(FunctionWrapperIndex wrapper) { return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).is_coerce_constructor(); } +bool +interrogate_wrapper_is_extension(FunctionWrapperIndex wrapper) { + // cerr << "interrogate_wrapper_is_extension(" << wrapper << ")\n"; + return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).is_extension(); +} + bool interrogate_wrapper_has_comment(FunctionWrapperIndex wrapper) { // cerr << "interrogate_wrapper_has_comment(" << wrapper << ")\n"; diff --git a/dtool/src/interrogatedb/interrogate_interface.h b/dtool/src/interrogatedb/interrogate_interface.h index be5562ec40..5c776e70eb 100644 --- a/dtool/src/interrogatedb/interrogate_interface.h +++ b/dtool/src/interrogatedb/interrogate_interface.h @@ -285,6 +285,10 @@ EXPCL_INTERROGATEDB bool interrogate_wrapper_is_copy_constructor(FunctionWrapper // This returns true if this is a constructor that is not marked "explicit". EXPCL_INTERROGATEDB bool interrogate_wrapper_is_coerce_constructor(FunctionWrapperIndex wrapper); +// This returns true if this is an extension function, rather than a real +// function defined in the C++ code. +EXPCL_INTERROGATEDB bool interrogate_wrapper_is_extension(FunctionWrapperIndex wrapper); + // This returns the C++ comment written for the function wrapper, usually from // the .cpp file. There may be a different comment for each overload of a // given function. From 9efdf9919c059628e49ff0dfb580d9fe2a617046 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 20 Oct 2022 17:14:54 +0200 Subject: [PATCH 10/10] collide: Implement capsule-into-polygon intersection test There is one edge case (literally) where the reported interior point isn't deep enough, which is when the capsule hits the edge of a polygon at a steep angle, but it will still push it out eventually, so whatever. Fixes #1369 --- panda/src/collide/collisionPolygon.cxx | 194 +++++++++++++++++++++++++ panda/src/collide/collisionPolygon.h | 2 + 2 files changed, 196 insertions(+) diff --git a/panda/src/collide/collisionPolygon.cxx b/panda/src/collide/collisionPolygon.cxx index 791cbdea87..eafffdde90 100644 --- a/panda/src/collide/collisionPolygon.cxx +++ b/panda/src/collide/collisionPolygon.cxx @@ -755,6 +755,200 @@ test_intersection_from_segment(const CollisionEntry &entry) const { return new_entry; } +/** + * + */ +PT(CollisionEntry) CollisionPolygon:: +test_intersection_from_capsule(const CollisionEntry &entry) const { + const CollisionCapsule *capsule; + DCAST_INTO_R(capsule, entry.get_from(), nullptr); + + const LMatrix4 &wrt_mat = entry.get_wrt_mat(); + + LPoint3 from_a = capsule->get_point_a() * wrt_mat; + LPoint3 from_b = capsule->get_point_b() * wrt_mat; + LVector3 from_radius_v = + LVector3(capsule->get_radius(), 0.0f, 0.0f) * wrt_mat; + PN_stdfloat from_radius_2 = from_radius_v.length_squared(); + PN_stdfloat from_radius = csqrt(from_radius_2); + + PN_stdfloat dist_a = get_plane().dist_to_plane(from_a); + PN_stdfloat dist_b = get_plane().dist_to_plane(from_b); + + // Some early-outs (optional) + if (dist_a >= from_radius && dist_b >= from_radius) { + // Entirely in front of the plane means no intersection. + return nullptr; + } + + if (dist_a <= -from_radius && dist_b <= -from_radius) { + // Entirely behind the plane also means no intersection. + return nullptr; + } + + LMatrix4 to_3d_mat; + rederive_to_3d_mat(to_3d_mat); + + // Find the intersection point between the capsule's axis and the plane. + LPoint3 intersect_3d; + if (!get_plane().intersects_line(intersect_3d, from_a, from_b)) { + // Completely parallel. Take an arbitrary point along the capsule axis. + intersect_3d = (from_a + from_b) * 0.5f; + } + + // Find the closest point on the polygon to this intersection point. + LPoint2 intersect_2d = to_2d(intersect_3d); + LPoint2 closest_p_2d = intersect_2d; + PN_stdfloat best_dist_2 = -1; + + size_t num_points = _points.size(); + for (size_t i = 0; i < num_points; ++i) { + const LPoint2 &p1 = _points[i]._p; + const LPoint2 &p2 = _points[(i + 1) % num_points]._p; + + // Is the intersection outside the polygon? + LVector2 v = intersect_2d - p1; + LVector2 pv = p2 - p1; + if (is_right(v, pv)) { + PN_stdfloat t = v.dot(pv) / pv.length_squared(); + t = max(min(t, (PN_stdfloat)1), (PN_stdfloat)0); + + LPoint2 p = p1 + pv * t; + PN_stdfloat d = (p - intersect_2d).length_squared(); + if (best_dist_2 < 0 || d < best_dist_2) { + closest_p_2d = p; + best_dist_2 = d; + } + } + } + + LPoint3 closest_p_3d = to_3d(closest_p_2d, to_3d_mat); + + // Now find the closest point on the capsule axis to this point. + LVector3 from_v = from_b - from_a; + + PN_stdfloat t = (closest_p_3d - from_a).dot(from_v) / from_v.length_squared(); + LPoint3 ref_point_3d = from_a + from_v * max(min(t, (PN_stdfloat)1), (PN_stdfloat)0); + + // Okay, now we have a point to apply the sphere test on. + + // The nearest point within the plane to our reference is the intersection of + // the line (reference, reference - normal) with the plane. + PN_stdfloat dist; + if (!get_plane().intersects_line(dist, ref_point_3d, -get_normal())) { + // No intersection with plane? This means the plane's effective normal + // was within the plane itself. A useless polygon. + return nullptr; + } + + if (dist > from_radius || dist < -from_radius) { + // No intersection with the plane. + return nullptr; + } + + LPoint2 ref_point_2d = to_2d(ref_point_3d); + LPoint2 surface_point_2d = ref_point_2d; + PN_stdfloat edge_dist_2 = -1; + + for (size_t i = 0; i < num_points; ++i) { + const LPoint2 &p1 = _points[i]._p; + const LPoint2 &p2 = _points[(i + 1) % num_points]._p; + + // Is the intersection outside the polygon? + LVector2 v = ref_point_2d - p1; + LVector2 pv = p2 - p1; + if (is_right(v, pv)) { + PN_stdfloat t = v.dot(pv) / pv.length_squared(); + t = max(min(t, (PN_stdfloat)1), (PN_stdfloat)0); + + LPoint2 p = p1 + pv * t; + PN_stdfloat d = (p - ref_point_2d).length_squared(); + if (edge_dist_2 < 0 || d < edge_dist_2) { + surface_point_2d = p; + edge_dist_2 = d; + } + } + } + + // Now we have edge_dist_2, which is the square of the distance from the + // reference point to the nearest edge of the polygon, within the polygon's + // plane. + + if (edge_dist_2 > from_radius_2) { + // No intersection; the circle is outside the polygon. + return nullptr; + } + + // The sphere appears to intersect the polygon. If the edge is less than + // from_radius away, the sphere may be resting on an edge of the polygon. + // Determine how far the center of the sphere must remain from the plane, + // based on its distance from the nearest edge. + + PN_stdfloat max_dist = from_radius; + if (edge_dist_2 >= 0.0f) { + PN_stdfloat max_dist_2 = max(from_radius_2 - edge_dist_2, (PN_stdfloat)0.0); + max_dist = csqrt(max_dist_2); + } + + if (dist > max_dist || -dist > max_dist) { + // There's no intersection: the sphere is hanging above or under the edge. + return nullptr; + } + + if (collide_cat.is_debug()) { + collide_cat.debug() + << "intersection detected from " << entry.get_from_node_path() + << " into " << entry.get_into_node_path() << "\n"; + } + PT(CollisionEntry) new_entry = new CollisionEntry(entry); + + LVector3 normal = (has_effective_normal() && capsule->get_respect_effective_normal()) ? get_effective_normal() : get_normal(); + new_entry->set_surface_normal(normal); + + if ((dist_a < 0 || dist_b < 0) && !IS_NEARLY_EQUAL(dist_a, dist_b)) { + // We need to report the deepest point below the polygon as the interior + // point so that the pusher will completely push it out. + LPoint3 deepest_3d = (dist_a < dist_b) ? from_a : from_b; + LPoint2 deepest_2d = to_2d(deepest_3d); + surface_point_2d = deepest_2d; + PN_stdfloat best_dist_2 = -1; + + for (size_t i = 0; i < num_points; ++i) { + const LPoint2 &p1 = _points[i]._p; + const LPoint2 &p2 = _points[(i + 1) % num_points]._p; + + // Is the deepest point outside the polygon? + LVector2 v = deepest_2d - p1; + LVector2 pv = p2 - p1; + if (is_right(v, pv)) { + PN_stdfloat t = v.dot(pv) / pv.length_squared(); + t = max(min(t, (PN_stdfloat)1), (PN_stdfloat)0); + + LPoint2 p = p1 + pv * t; + PN_stdfloat d = (p - deepest_2d).length_squared(); + if (best_dist_2 < 0 || d < best_dist_2) { + surface_point_2d = p; + best_dist_2 = d; + } + } + } + + if (best_dist_2 < 0) { + // Deepest point is completely within the polygon, easy case. + new_entry->set_surface_point(deepest_3d - normal * min(dist_a, dist_b)); + new_entry->set_interior_point(deepest_3d - normal * from_radius); + return new_entry; + } + } + + // Colliding with an edge, use the sphere test results. + LPoint3 surface_point = to_3d(surface_point_2d, to_3d_mat); + LPoint3 interior_point = ref_point_3d - normal * max_dist; + new_entry->set_surface_point(surface_point); + new_entry->set_interior_point((interior_point - surface_point).project(normal) + surface_point); + return new_entry; +} + /** * This is part of the double-dispatch implementation of test_intersection(). * It is called when the "from" object is a parabola. diff --git a/panda/src/collide/collisionPolygon.h b/panda/src/collide/collisionPolygon.h index 2711f98fa0..302c410263 100644 --- a/panda/src/collide/collisionPolygon.h +++ b/panda/src/collide/collisionPolygon.h @@ -92,6 +92,8 @@ protected: virtual PT(CollisionEntry) test_intersection_from_segment(const CollisionEntry &entry) const; virtual PT(CollisionEntry) + test_intersection_from_capsule(const CollisionEntry &entry) const; + virtual PT(CollisionEntry) test_intersection_from_parabola(const CollisionEntry &entry) const; virtual PT(CollisionEntry) test_intersection_from_box(const CollisionEntry &entry) const;