mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-28 15:53:55 -04:00
Merge branch 'release/1.10.x'
This commit is contained in:
commit
8cbe36b352
@ -151,7 +151,7 @@ PUBLISHED:
|
|||||||
|
|
||||||
void obstacle_avoidance(float feeler_length = 1.0);
|
void obstacle_avoidance(float feeler_length = 1.0);
|
||||||
|
|
||||||
void path_follow(float follow_wt);
|
void path_follow(float follow_wt = 1.0f);
|
||||||
void add_to_path(LVecBase3 pos);
|
void add_to_path(LVecBase3 pos);
|
||||||
void start_follow(std::string type = "normal");
|
void start_follow(std::string type = "normal");
|
||||||
|
|
||||||
|
@ -331,7 +331,7 @@ update_motion_trail (PN_stdfloat current_time, LMatrix4 *transform) {
|
|||||||
|
|
||||||
frame_iterator = _frame_list.begin ( );
|
frame_iterator = _frame_list.begin ( );
|
||||||
motion_trail_frame = *frame_iterator;
|
motion_trail_frame = *frame_iterator;
|
||||||
if (*transform == motion_trail_frame._transform) {
|
if (motion_trail_frame._transform == UnalignedLMatrix4(*transform)) {
|
||||||
// duplicate transform
|
// duplicate transform
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ pallocator_single(TypeHandle type_handle) noexcept :
|
|||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
INLINE Type *pallocator_single<Type>::
|
INLINE Type *pallocator_single<Type>::
|
||||||
allocate(typename pallocator_single<Type>::size_type n, typename std::allocator<void>::const_pointer) {
|
allocate(typename pallocator_single<Type>::size_type n, const void *) {
|
||||||
TAU_PROFILE("pallocator_single:allocate()", " ", TAU_USER);
|
TAU_PROFILE("pallocator_single:allocate()", " ", TAU_USER);
|
||||||
// This doesn't support allocating arrays.
|
// This doesn't support allocating arrays.
|
||||||
assert(n == 1);
|
assert(n == 1);
|
||||||
@ -30,7 +30,7 @@ allocate(typename pallocator_single<Type>::size_type n, typename std::allocator<
|
|||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
INLINE void pallocator_single<Type>::
|
INLINE void pallocator_single<Type>::
|
||||||
deallocate(typename pallocator_single<Type>::pointer p, typename pallocator_single<Type>::size_type) {
|
deallocate(Type *p, typename pallocator_single<Type>::size_type) {
|
||||||
TAU_PROFILE("pallocator_single:deallocate()", " ", TAU_USER);
|
TAU_PROFILE("pallocator_single:deallocate()", " ", TAU_USER);
|
||||||
StaticDeletedChain<Type>::deallocate(p, _type_handle);
|
StaticDeletedChain<Type>::deallocate(p, _type_handle);
|
||||||
}
|
}
|
||||||
@ -44,13 +44,13 @@ pallocator_array(TypeHandle type_handle) noexcept :
|
|||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
INLINE Type *pallocator_array<Type>::
|
INLINE Type *pallocator_array<Type>::
|
||||||
allocate(typename pallocator_array<Type>::size_type n, typename std::allocator<void>::const_pointer) {
|
allocate(typename pallocator_array<Type>::size_type n, const void *) {
|
||||||
return (typename pallocator_array<Type>::pointer)
|
return (Type *)
|
||||||
ASSUME_ALIGNED(_type_handle.allocate_array(n * sizeof(Type)), MEMORY_HOOK_ALIGNMENT);
|
ASSUME_ALIGNED(_type_handle.allocate_array(n * sizeof(Type)), MEMORY_HOOK_ALIGNMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
INLINE void pallocator_array<Type>::
|
INLINE void pallocator_array<Type>::
|
||||||
deallocate(typename pallocator_array<Type>::pointer p, typename pallocator_array<Type>::size_type) {
|
deallocate(Type *p, typename pallocator_array<Type>::size_type) {
|
||||||
_type_handle.deallocate_array((void *)p);
|
_type_handle.deallocate_array((void *)p);
|
||||||
}
|
}
|
||||||
|
@ -46,10 +46,10 @@ class pallocator_single : public std::allocator<Type> {
|
|||||||
public:
|
public:
|
||||||
// Nowadays we cannot implicitly inherit typedefs from base classes in a
|
// Nowadays we cannot implicitly inherit typedefs from base classes in a
|
||||||
// template class; we must explicitly copy them here.
|
// template class; we must explicitly copy them here.
|
||||||
typedef typename std::allocator<Type>::pointer pointer;
|
typedef Type *pointer;
|
||||||
typedef typename std::allocator<Type>::reference reference;
|
typedef Type &reference;
|
||||||
typedef typename std::allocator<Type>::const_pointer const_pointer;
|
typedef const Type *const_pointer;
|
||||||
typedef typename std::allocator<Type>::const_reference const_reference;
|
typedef const Type &const_reference;
|
||||||
typedef typename std::allocator<Type>::size_type size_type;
|
typedef typename std::allocator<Type>::size_type size_type;
|
||||||
|
|
||||||
INLINE pallocator_single(TypeHandle type_handle) noexcept;
|
INLINE pallocator_single(TypeHandle type_handle) noexcept;
|
||||||
@ -59,9 +59,9 @@ public:
|
|||||||
INLINE pallocator_single(const pallocator_single<U> ©) noexcept :
|
INLINE pallocator_single(const pallocator_single<U> ©) noexcept :
|
||||||
_type_handle(copy._type_handle) { }
|
_type_handle(copy._type_handle) { }
|
||||||
|
|
||||||
INLINE Type *allocate(size_type n, std::allocator<void>::const_pointer hint = 0)
|
INLINE Type *allocate(size_type n, const void *hint = 0)
|
||||||
RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
|
RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
|
||||||
INLINE void deallocate(pointer p, size_type n);
|
INLINE void deallocate(Type *p, size_type n);
|
||||||
|
|
||||||
template<class U> struct rebind {
|
template<class U> struct rebind {
|
||||||
typedef pallocator_single<U> other;
|
typedef pallocator_single<U> other;
|
||||||
@ -75,10 +75,10 @@ class pallocator_array : public std::allocator<Type> {
|
|||||||
public:
|
public:
|
||||||
// Nowadays we cannot implicitly inherit typedefs from base classes in a
|
// Nowadays we cannot implicitly inherit typedefs from base classes in a
|
||||||
// template class; we must explicitly copy them here.
|
// template class; we must explicitly copy them here.
|
||||||
typedef typename std::allocator<Type>::pointer pointer;
|
typedef Type *pointer;
|
||||||
typedef typename std::allocator<Type>::reference reference;
|
typedef Type &reference;
|
||||||
typedef typename std::allocator<Type>::const_pointer const_pointer;
|
typedef const Type *const_pointer;
|
||||||
typedef typename std::allocator<Type>::const_reference const_reference;
|
typedef const Type &const_reference;
|
||||||
typedef typename std::allocator<Type>::size_type size_type;
|
typedef typename std::allocator<Type>::size_type size_type;
|
||||||
|
|
||||||
INLINE pallocator_array(TypeHandle type_handle = TypeHandle::none()) noexcept;
|
INLINE pallocator_array(TypeHandle type_handle = TypeHandle::none()) noexcept;
|
||||||
@ -88,9 +88,9 @@ public:
|
|||||||
INLINE pallocator_array(const pallocator_array<U> ©) noexcept :
|
INLINE pallocator_array(const pallocator_array<U> ©) noexcept :
|
||||||
_type_handle(copy._type_handle) { }
|
_type_handle(copy._type_handle) { }
|
||||||
|
|
||||||
INLINE Type *allocate(size_type n, std::allocator<void>::const_pointer hint = 0)
|
INLINE Type *allocate(size_type n, const void *hint = 0)
|
||||||
RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
|
RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
|
||||||
INLINE void deallocate(pointer p, size_type n);
|
INLINE void deallocate(Type *p, size_type n);
|
||||||
|
|
||||||
template<class U> struct rebind {
|
template<class U> struct rebind {
|
||||||
typedef pallocator_array<U> other;
|
typedef pallocator_array<U> other;
|
||||||
|
@ -4306,21 +4306,22 @@ int get_type_sort(CPPType *type) {
|
|||||||
TypeManager::is_struct(type)) {
|
TypeManager::is_struct(type)) {
|
||||||
answer = 20;
|
answer = 20;
|
||||||
int deepest = 0;
|
int deepest = 0;
|
||||||
TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(type)), false);
|
|
||||||
InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
|
|
||||||
const InterrogateType &itype = idb->get_type(type_index);
|
|
||||||
|
|
||||||
if (itype.is_class() || itype.is_struct()) {
|
// Sort such that more derived classes come first.
|
||||||
int num_derivations = itype.number_of_derivations();
|
type = TypeManager::unwrap(TypeManager::resolve_type(type));
|
||||||
for (int di = 0; di < num_derivations; di++) {
|
if (type != nullptr) {
|
||||||
TypeIndex d_type_Index = itype.get_derivation(di);
|
CPPStructType *struct_type = type->as_struct_type();
|
||||||
const InterrogateType &d_itype = idb->get_type(d_type_Index);
|
if (struct_type != nullptr) {
|
||||||
int this_one = get_type_sort(d_itype._cpptype);
|
for (const CPPStructType::Base &base : struct_type->_derivation) {
|
||||||
|
if (base._base != nullptr) {
|
||||||
|
int this_one = get_type_sort(base._base);
|
||||||
if (this_one > deepest) {
|
if (this_one > deepest) {
|
||||||
deepest = this_one;
|
deepest = this_one;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
answer += deepest;
|
answer += deepest;
|
||||||
// printf(" Class Name %s %d\n",itype.get_name().c_str(),answer);
|
// printf(" Class Name %s %d\n",itype.get_name().c_str(),answer);
|
||||||
}
|
}
|
||||||
|
@ -137,6 +137,11 @@ typedef long Py_hash_t;
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Python 3.4 */
|
||||||
|
#if PY_VERSION_HEX < 0x03040000
|
||||||
|
#define PyGILState_Check() (PyGILState_GetThisThreadState() == _PyThreadState_Current)
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Python 3.6 */
|
/* Python 3.6 */
|
||||||
|
|
||||||
#if PY_VERSION_HEX < 0x03080000 && !defined(_PyObject_CallNoArg)
|
#if PY_VERSION_HEX < 0x03080000 && !defined(_PyObject_CallNoArg)
|
||||||
|
@ -84,13 +84,14 @@ PUBLISHED:
|
|||||||
BLOCKING void wait();
|
BLOCKING void wait();
|
||||||
BLOCKING void wait(double timeout);
|
BLOCKING void wait(double timeout);
|
||||||
|
|
||||||
|
EXTENSION(void set_result(PyObject *));
|
||||||
|
|
||||||
|
public:
|
||||||
INLINE void set_result(std::nullptr_t);
|
INLINE void set_result(std::nullptr_t);
|
||||||
INLINE void set_result(TypedObject *result);
|
INLINE void set_result(TypedObject *result);
|
||||||
INLINE void set_result(TypedReferenceCount *result);
|
INLINE void set_result(TypedReferenceCount *result);
|
||||||
INLINE void set_result(TypedWritableReferenceCount *result);
|
INLINE void set_result(TypedWritableReferenceCount *result);
|
||||||
INLINE void set_result(const EventParameter &result);
|
INLINE void set_result(const EventParameter &result);
|
||||||
|
|
||||||
public:
|
|
||||||
void set_result(TypedObject *ptr, ReferenceCount *ref_ptr);
|
void set_result(TypedObject *ptr, ReferenceCount *ref_ptr);
|
||||||
|
|
||||||
INLINE TypedObject *get_result() const;
|
INLINE TypedObject *get_result() const;
|
||||||
|
@ -15,14 +15,20 @@
|
|||||||
#include "asyncTaskSequence.h"
|
#include "asyncTaskSequence.h"
|
||||||
#include "eventParameter.h"
|
#include "eventParameter.h"
|
||||||
#include "paramValue.h"
|
#include "paramValue.h"
|
||||||
|
#include "paramPyObject.h"
|
||||||
#include "pythonTask.h"
|
#include "pythonTask.h"
|
||||||
|
#include "asyncTaskManager.h"
|
||||||
|
#include "config_event.h"
|
||||||
|
|
||||||
#ifdef HAVE_PYTHON
|
#ifdef HAVE_PYTHON
|
||||||
|
|
||||||
#ifndef CPPPARSER
|
#ifndef CPPPARSER
|
||||||
extern struct Dtool_PyTypedObject Dtool_AsyncFuture;
|
extern struct Dtool_PyTypedObject Dtool_AsyncFuture;
|
||||||
|
extern struct Dtool_PyTypedObject Dtool_EventParameter;
|
||||||
extern struct Dtool_PyTypedObject Dtool_ParamValueBase;
|
extern struct Dtool_PyTypedObject Dtool_ParamValueBase;
|
||||||
extern struct Dtool_PyTypedObject Dtool_TypedObject;
|
extern struct Dtool_PyTypedObject Dtool_TypedObject;
|
||||||
|
extern struct Dtool_PyTypedObject Dtool_TypedReferenceCount;
|
||||||
|
extern struct Dtool_PyTypedObject Dtool_TypedWritableReferenceCount;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -90,20 +96,24 @@ static PyObject *get_done_result(const AsyncFuture *future) {
|
|||||||
// EventStoreInt and Double are not exposed to Python for some reason.
|
// EventStoreInt and Double are not exposed to Python for some reason.
|
||||||
if (type == EventStoreInt::get_class_type()) {
|
if (type == EventStoreInt::get_class_type()) {
|
||||||
return Dtool_WrapValue(((EventStoreInt *)ptr)->get_value());
|
return Dtool_WrapValue(((EventStoreInt *)ptr)->get_value());
|
||||||
} else if (type == EventStoreDouble::get_class_type()) {
|
}
|
||||||
|
else if (type == EventStoreDouble::get_class_type()) {
|
||||||
return Dtool_WrapValue(((EventStoreDouble *)ptr)->get_value());
|
return Dtool_WrapValue(((EventStoreDouble *)ptr)->get_value());
|
||||||
}
|
}
|
||||||
|
else if (type == ParamPyObject::get_class_type()) {
|
||||||
|
return ((ParamPyObject *)ptr)->get_value();
|
||||||
|
}
|
||||||
|
|
||||||
ParamValueBase *value = (ParamValueBase *)ptr;
|
ParamValueBase *value = (ParamValueBase *)ptr;
|
||||||
PyObject *wrap = DTool_CreatePyInstanceTyped
|
PyObject *wrap = DTool_CreatePyInstanceTyped
|
||||||
((void *)value, Dtool_ParamValueBase, false, false, type.get_index());
|
((void *)value, Dtool_ParamValueBase, false, false, type.get_index());
|
||||||
if (wrap != nullptr) {
|
if (wrap != nullptr) {
|
||||||
PyObject *value = PyObject_GetAttrString(wrap, "value");
|
PyObject *value = PyObject_GetAttrString(wrap, "value");
|
||||||
|
Py_DECREF(wrap);
|
||||||
if (value != nullptr) {
|
if (value != nullptr) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
Py_DECREF(wrap);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,6 +164,58 @@ __await__(PyObject *self) {
|
|||||||
return Dtool_NewGenerator(self, &gen_next);
|
return Dtool_NewGenerator(self, &gen_next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets this future's result. Can only be called if done() returns false.
|
||||||
|
*/
|
||||||
|
void Extension<AsyncFuture>::
|
||||||
|
set_result(PyObject *result) {
|
||||||
|
if (result == Py_None) {
|
||||||
|
_this->set_result(nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (DtoolInstance_Check(result)) {
|
||||||
|
void *ptr;
|
||||||
|
if ((ptr = DtoolInstance_UPCAST(result, Dtool_EventParameter))) {
|
||||||
|
_this->set_result(*(const EventParameter *)ptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((ptr = DtoolInstance_UPCAST(result, Dtool_TypedWritableReferenceCount))) {
|
||||||
|
_this->set_result((TypedWritableReferenceCount *)ptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((ptr = DtoolInstance_UPCAST(result, Dtool_TypedReferenceCount))) {
|
||||||
|
_this->set_result((TypedReferenceCount *)ptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((ptr = DtoolInstance_UPCAST(result, Dtool_TypedObject))) {
|
||||||
|
_this->set_result((TypedObject *)ptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (PyUnicode_Check(result)) {
|
||||||
|
Py_ssize_t result_len;
|
||||||
|
wchar_t *result_str = PyUnicode_AsWideCharString(result, &result_len);
|
||||||
|
_this->set_result(new EventStoreWstring(std::wstring(result_str, result_len)));
|
||||||
|
PyMem_Free(result_str);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (PyLongOrInt_Check(result)) {
|
||||||
|
long result_val = PyLongOrInt_AS_LONG(result);
|
||||||
|
if (result_val >= INT_MIN && result_val <= INT_MAX) {
|
||||||
|
_this->set_result(new EventStoreInt((int)result_val));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (PyNumber_Check(result)) {
|
||||||
|
_this->set_result(new EventStoreDouble(PyFloat_AsDouble(result)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we don't recognize the type, store it as a generic PyObject pointer.
|
||||||
|
ParamPyObject::init_type();
|
||||||
|
_this->set_result(new ParamPyObject(result));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the result of this future, unless it was cancelled, in which case
|
* Returns the result of this future, unless it was cancelled, in which case
|
||||||
* it returns CancelledError.
|
* it returns CancelledError.
|
||||||
@ -285,8 +347,19 @@ gather(PyObject *args) {
|
|||||||
}
|
}
|
||||||
} else if (PyCoro_CheckExact(item)) {
|
} else if (PyCoro_CheckExact(item)) {
|
||||||
// We allow passing in a coroutine instead of a future. This causes it
|
// We allow passing in a coroutine instead of a future. This causes it
|
||||||
// to be scheduled as a task.
|
// to be scheduled as a task on the current task manager.
|
||||||
futures.push_back(new PythonTask(item));
|
PT(AsyncTask) task = new PythonTask(item);
|
||||||
|
Thread *current_thread = Thread::get_current_thread();
|
||||||
|
AsyncTask *current_task = (AsyncTask *)current_thread->get_current_task();
|
||||||
|
if (current_task != nullptr) {
|
||||||
|
task->set_task_chain(current_task->get_task_chain());
|
||||||
|
current_task->get_manager()->add(task);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
event_cat.warning()
|
||||||
|
<< "gather() with coroutine not called from within a task; not scheduling with task manager.\n";
|
||||||
|
}
|
||||||
|
futures.push_back(task);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return Dtool_Raise_ArgTypeError(item, i, "gather", "coroutine, task or future");
|
return Dtool_Raise_ArgTypeError(item, i, "gather", "coroutine, task or future");
|
||||||
|
@ -29,6 +29,7 @@ public:
|
|||||||
static PyObject *__await__(PyObject *self);
|
static PyObject *__await__(PyObject *self);
|
||||||
static PyObject *__iter__(PyObject *self) { return __await__(self); }
|
static PyObject *__iter__(PyObject *self) { return __await__(self); }
|
||||||
|
|
||||||
|
void set_result(PyObject *result);
|
||||||
PyObject *result(PyObject *timeout = Py_None) const;
|
PyObject *result(PyObject *timeout = Py_None) const;
|
||||||
|
|
||||||
PyObject *add_done_callback(PyObject *self, PyObject *fn);
|
PyObject *add_done_callback(PyObject *self, PyObject *fn);
|
||||||
|
@ -84,7 +84,6 @@ PythonTask(PyObject *func_or_coro, const std::string &name) :
|
|||||||
*/
|
*/
|
||||||
PythonTask::
|
PythonTask::
|
||||||
~PythonTask() {
|
~PythonTask() {
|
||||||
#ifndef NDEBUG
|
|
||||||
// If the coroutine threw an exception, and there was no opportunity to
|
// If the coroutine threw an exception, and there was no opportunity to
|
||||||
// handle it, let the user know.
|
// handle it, let the user know.
|
||||||
if (_exception != nullptr && !_retrieved_exception) {
|
if (_exception != nullptr && !_retrieved_exception) {
|
||||||
@ -97,7 +96,6 @@ PythonTask::
|
|||||||
_exc_value = nullptr;
|
_exc_value = nullptr;
|
||||||
_exc_traceback = nullptr;
|
_exc_traceback = nullptr;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
Py_XDECREF(_function);
|
Py_XDECREF(_function);
|
||||||
Py_DECREF(_args);
|
Py_DECREF(_args);
|
||||||
|
@ -3054,6 +3054,37 @@ glsl_report_program_errors(GLuint program, bool fatal) {
|
|||||||
if (strcmp(info_log, "Success.\n") != 0 &&
|
if (strcmp(info_log, "Success.\n") != 0 &&
|
||||||
strcmp(info_log, "No errors.\n") != 0 &&
|
strcmp(info_log, "No errors.\n") != 0 &&
|
||||||
strcmp(info_log, "Validation successful.\n") != 0) {
|
strcmp(info_log, "Validation successful.\n") != 0) {
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
// Filter out these unhelpful warnings that Apple always generates.
|
||||||
|
while (true) {
|
||||||
|
if (info_log[0] == '\n') {
|
||||||
|
++info_log;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (info_log[0] == '\0') {
|
||||||
|
// We reached the end without finding anything interesting.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int linelen = 0;
|
||||||
|
if ((sscanf(info_log, "WARNING: Could not find vertex shader attribute %*s to match BindAttributeLocation request.%*[\n]%n", &linelen) == 0 && linelen > 0) ||
|
||||||
|
(sscanf(info_log, "WARNING: Could not find fragment shader output %*s to match FragDataBinding request.%*[\n]%n", &linelen) == 0 && linelen > 0)) {
|
||||||
|
info_log += linelen;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
info_log = strchr(info_log, '\n');
|
||||||
|
if (info_log == nullptr) {
|
||||||
|
// We reached the end without finding anything interesting.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
++info_log;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!fatal) {
|
if (!fatal) {
|
||||||
GLCAT.warning()
|
GLCAT.warning()
|
||||||
<< "Shader " << _shader->get_filename() << " produced the "
|
<< "Shader " << _shader->get_filename() << " produced the "
|
||||||
|
@ -258,7 +258,9 @@ call_python_func(PyObject *function, PyObject *args) {
|
|||||||
|
|
||||||
PyGILState_Release(gstate);
|
PyGILState_Release(gstate);
|
||||||
|
|
||||||
|
if (PyGILState_Check()) {
|
||||||
PyErr_Restore(exc, val, tb);
|
PyErr_Restore(exc, val, tb);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// No exception. Restore the thread state normally.
|
// No exception. Restore the thread state normally.
|
||||||
PyGILState_Release(gstate);
|
PyGILState_Release(gstate);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "bamReader_ext.cxx"
|
#include "bamReader_ext.cxx"
|
||||||
#include "bitArray_ext.cxx"
|
#include "bitArray_ext.cxx"
|
||||||
|
#include "paramPyObject.cxx"
|
||||||
#include "pythonCallbackObject.cxx"
|
#include "pythonCallbackObject.cxx"
|
||||||
#include "sparseArray_ext.cxx"
|
#include "sparseArray_ext.cxx"
|
||||||
#include "typedWritable_ext.cxx"
|
#include "typedWritable_ext.cxx"
|
||||||
|
31
panda/src/putil/paramPyObject.I
Normal file
31
panda/src/putil/paramPyObject.I
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* PANDA 3D SOFTWARE
|
||||||
|
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||||
|
*
|
||||||
|
* All use of this software is subject to the terms of the revised BSD
|
||||||
|
* license. You should have received a copy of this license along
|
||||||
|
* with this source code in a file named "LICENSE."
|
||||||
|
*
|
||||||
|
* @file paramPyObject.I
|
||||||
|
* @author rdb
|
||||||
|
* @date 2021-03-01
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "paramPyObject.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increments the reference count. Assumes the GIL is held.
|
||||||
|
*/
|
||||||
|
INLINE ParamPyObject::
|
||||||
|
ParamPyObject(PyObject *value) : _value(value) {
|
||||||
|
Py_INCREF(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new reference to the stored value.
|
||||||
|
*/
|
||||||
|
INLINE PyObject *ParamPyObject::
|
||||||
|
get_value() const {
|
||||||
|
Py_INCREF(_value);
|
||||||
|
return _value;
|
||||||
|
}
|
42
panda/src/putil/paramPyObject.cxx
Normal file
42
panda/src/putil/paramPyObject.cxx
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* PANDA 3D SOFTWARE
|
||||||
|
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||||
|
*
|
||||||
|
* All use of this software is subject to the terms of the revised BSD
|
||||||
|
* license. You should have received a copy of this license along
|
||||||
|
* with this source code in a file named "LICENSE."
|
||||||
|
*
|
||||||
|
* @file paramPyObject.cxx
|
||||||
|
* @author rdb
|
||||||
|
* @date 2021-03-01
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "paramPyObject.h"
|
||||||
|
|
||||||
|
TypeHandle ParamPyObject::_type_handle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrements the reference count.
|
||||||
|
*/
|
||||||
|
ParamPyObject::
|
||||||
|
~ParamPyObject() {
|
||||||
|
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
|
||||||
|
PyGILState_STATE gstate;
|
||||||
|
gstate = PyGILState_Ensure();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Py_DECREF(_value);
|
||||||
|
|
||||||
|
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
|
||||||
|
PyGILState_Release(gstate);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void ParamPyObject::
|
||||||
|
output(std::ostream &out) const {
|
||||||
|
out << "<" << Py_TYPE(_value)->tp_name
|
||||||
|
<< " object at " << (void *)_value << ">";
|
||||||
|
}
|
61
panda/src/putil/paramPyObject.h
Normal file
61
panda/src/putil/paramPyObject.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/**
|
||||||
|
* PANDA 3D SOFTWARE
|
||||||
|
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||||
|
*
|
||||||
|
* All use of this software is subject to the terms of the revised BSD
|
||||||
|
* license. You should have received a copy of this license along
|
||||||
|
* with this source code in a file named "LICENSE."
|
||||||
|
*
|
||||||
|
* @file paramPyObject.h
|
||||||
|
* @author rdb
|
||||||
|
* @date 2021-03-01
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PARAMPYOBJECT_H
|
||||||
|
#define PARAMPYOBJECT_H
|
||||||
|
|
||||||
|
#include "pandabase.h"
|
||||||
|
#include "paramValue.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
|
||||||
|
#include "py_panda.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class object for storing an arbitrary Python object.
|
||||||
|
*/
|
||||||
|
class ParamPyObject final : public ParamValueBase {
|
||||||
|
public:
|
||||||
|
INLINE ParamPyObject(PyObject *value);
|
||||||
|
virtual ~ParamPyObject();
|
||||||
|
|
||||||
|
INLINE PyObject *get_value() const;
|
||||||
|
|
||||||
|
void output(std::ostream &out) const override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PyObject *_value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual TypeHandle get_type() const override {
|
||||||
|
return get_class_type();
|
||||||
|
}
|
||||||
|
virtual TypeHandle force_init_type() override {init_type(); return get_class_type();}
|
||||||
|
static TypeHandle get_class_type() {
|
||||||
|
return _type_handle;
|
||||||
|
}
|
||||||
|
static void init_type() {
|
||||||
|
ParamValueBase::init_type();
|
||||||
|
register_type(_type_handle, "ParamPyObject",
|
||||||
|
ParamValueBase::get_class_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static TypeHandle _type_handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "paramPyObject.I"
|
||||||
|
|
||||||
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
|
#endif
|
@ -163,6 +163,71 @@ def test_coro_exception():
|
|||||||
task.result()
|
task.result()
|
||||||
|
|
||||||
|
|
||||||
|
def test_future_result():
|
||||||
|
# Cancelled
|
||||||
|
fut = core.AsyncFuture()
|
||||||
|
assert not fut.done()
|
||||||
|
fut.cancel()
|
||||||
|
with pytest.raises(CancelledError):
|
||||||
|
fut.result()
|
||||||
|
|
||||||
|
# None
|
||||||
|
fut = core.AsyncFuture()
|
||||||
|
fut.set_result(None)
|
||||||
|
assert fut.done()
|
||||||
|
assert fut.result() is None
|
||||||
|
|
||||||
|
# Store int
|
||||||
|
fut = core.AsyncFuture()
|
||||||
|
fut.set_result(123)
|
||||||
|
assert fut.result() == 123
|
||||||
|
|
||||||
|
# Store string
|
||||||
|
fut = core.AsyncFuture()
|
||||||
|
fut.set_result("test\000\u1234")
|
||||||
|
assert fut.result() == "test\000\u1234"
|
||||||
|
|
||||||
|
# Store TypedWritableReferenceCount
|
||||||
|
tex = core.Texture()
|
||||||
|
rc = tex.get_ref_count()
|
||||||
|
fut = core.AsyncFuture()
|
||||||
|
fut.set_result(tex)
|
||||||
|
assert tex.get_ref_count() == rc + 1
|
||||||
|
assert fut.result() == tex
|
||||||
|
assert tex.get_ref_count() == rc + 1
|
||||||
|
assert fut.result() == tex
|
||||||
|
assert tex.get_ref_count() == rc + 1
|
||||||
|
fut = None
|
||||||
|
assert tex.get_ref_count() == rc
|
||||||
|
|
||||||
|
# Store EventParameter (gets unwrapped)
|
||||||
|
ep = core.EventParameter(0.5)
|
||||||
|
fut = core.AsyncFuture()
|
||||||
|
fut.set_result(ep)
|
||||||
|
assert fut.result() == 0.5
|
||||||
|
assert fut.result() == 0.5
|
||||||
|
|
||||||
|
# Store TypedObject
|
||||||
|
dg = core.Datagram(b"test")
|
||||||
|
fut = core.AsyncFuture()
|
||||||
|
fut.set_result(dg)
|
||||||
|
assert fut.result() == dg
|
||||||
|
assert fut.result() == dg
|
||||||
|
|
||||||
|
# Store arbitrary Python object
|
||||||
|
obj = object()
|
||||||
|
rc = sys.getrefcount(obj)
|
||||||
|
fut = core.AsyncFuture()
|
||||||
|
fut.set_result(obj)
|
||||||
|
assert sys.getrefcount(obj) == rc + 1
|
||||||
|
assert fut.result() is obj
|
||||||
|
assert sys.getrefcount(obj) == rc + 1
|
||||||
|
assert fut.result() is obj
|
||||||
|
assert sys.getrefcount(obj) == rc + 1
|
||||||
|
fut = None
|
||||||
|
assert sys.getrefcount(obj) == rc
|
||||||
|
|
||||||
|
|
||||||
def test_future_gather():
|
def test_future_gather():
|
||||||
fut1 = core.AsyncFuture()
|
fut1 = core.AsyncFuture()
|
||||||
fut2 = core.AsyncFuture()
|
fut2 = core.AsyncFuture()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user