Merge branch 'master' into deploy-ng
This commit is contained in:
commit
d90e59ca2d
File diff suppressed because it is too large
Load Diff
|
|
@ -143,51 +143,52 @@ extern int cppyydebug;
|
|||
KW_IS_TRIVIAL = 353,
|
||||
KW_IS_UNION = 354,
|
||||
KW_LONG = 355,
|
||||
KW_MAKE_MAP_PROPERTY = 356,
|
||||
KW_MAKE_PROPERTY = 357,
|
||||
KW_MAKE_PROPERTY2 = 358,
|
||||
KW_MAKE_SEQ = 359,
|
||||
KW_MAKE_SEQ_PROPERTY = 360,
|
||||
KW_MUTABLE = 361,
|
||||
KW_NAMESPACE = 362,
|
||||
KW_NEW = 363,
|
||||
KW_NOEXCEPT = 364,
|
||||
KW_NULLPTR = 365,
|
||||
KW_OPERATOR = 366,
|
||||
KW_OVERRIDE = 367,
|
||||
KW_PRIVATE = 368,
|
||||
KW_PROTECTED = 369,
|
||||
KW_PUBLIC = 370,
|
||||
KW_REGISTER = 371,
|
||||
KW_REINTERPRET_CAST = 372,
|
||||
KW_RETURN = 373,
|
||||
KW_SHORT = 374,
|
||||
KW_SIGNED = 375,
|
||||
KW_SIZEOF = 376,
|
||||
KW_STATIC = 377,
|
||||
KW_STATIC_ASSERT = 378,
|
||||
KW_STATIC_CAST = 379,
|
||||
KW_STRUCT = 380,
|
||||
KW_TEMPLATE = 381,
|
||||
KW_THREAD_LOCAL = 382,
|
||||
KW_THROW = 383,
|
||||
KW_TRUE = 384,
|
||||
KW_TRY = 385,
|
||||
KW_TYPEDEF = 386,
|
||||
KW_TYPEID = 387,
|
||||
KW_TYPENAME = 388,
|
||||
KW_UNDERLYING_TYPE = 389,
|
||||
KW_UNION = 390,
|
||||
KW_UNSIGNED = 391,
|
||||
KW_USING = 392,
|
||||
KW_VIRTUAL = 393,
|
||||
KW_VOID = 394,
|
||||
KW_VOLATILE = 395,
|
||||
KW_WCHAR_T = 396,
|
||||
KW_WHILE = 397,
|
||||
START_CPP = 398,
|
||||
START_CONST_EXPR = 399,
|
||||
START_TYPE = 400
|
||||
KW_MAKE_MAP_KEYS_SEQ = 356,
|
||||
KW_MAKE_MAP_PROPERTY = 357,
|
||||
KW_MAKE_PROPERTY = 358,
|
||||
KW_MAKE_PROPERTY2 = 359,
|
||||
KW_MAKE_SEQ = 360,
|
||||
KW_MAKE_SEQ_PROPERTY = 361,
|
||||
KW_MUTABLE = 362,
|
||||
KW_NAMESPACE = 363,
|
||||
KW_NEW = 364,
|
||||
KW_NOEXCEPT = 365,
|
||||
KW_NULLPTR = 366,
|
||||
KW_OPERATOR = 367,
|
||||
KW_OVERRIDE = 368,
|
||||
KW_PRIVATE = 369,
|
||||
KW_PROTECTED = 370,
|
||||
KW_PUBLIC = 371,
|
||||
KW_REGISTER = 372,
|
||||
KW_REINTERPRET_CAST = 373,
|
||||
KW_RETURN = 374,
|
||||
KW_SHORT = 375,
|
||||
KW_SIGNED = 376,
|
||||
KW_SIZEOF = 377,
|
||||
KW_STATIC = 378,
|
||||
KW_STATIC_ASSERT = 379,
|
||||
KW_STATIC_CAST = 380,
|
||||
KW_STRUCT = 381,
|
||||
KW_TEMPLATE = 382,
|
||||
KW_THREAD_LOCAL = 383,
|
||||
KW_THROW = 384,
|
||||
KW_TRUE = 385,
|
||||
KW_TRY = 386,
|
||||
KW_TYPEDEF = 387,
|
||||
KW_TYPEID = 388,
|
||||
KW_TYPENAME = 389,
|
||||
KW_UNDERLYING_TYPE = 390,
|
||||
KW_UNION = 391,
|
||||
KW_UNSIGNED = 392,
|
||||
KW_USING = 393,
|
||||
KW_VIRTUAL = 394,
|
||||
KW_VOID = 395,
|
||||
KW_VOLATILE = 396,
|
||||
KW_WCHAR_T = 397,
|
||||
KW_WHILE = 398,
|
||||
START_CPP = 399,
|
||||
START_CONST_EXPR = 400,
|
||||
START_TYPE = 401
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
|
|
@ -289,51 +290,52 @@ extern int cppyydebug;
|
|||
#define KW_IS_TRIVIAL 353
|
||||
#define KW_IS_UNION 354
|
||||
#define KW_LONG 355
|
||||
#define KW_MAKE_MAP_PROPERTY 356
|
||||
#define KW_MAKE_PROPERTY 357
|
||||
#define KW_MAKE_PROPERTY2 358
|
||||
#define KW_MAKE_SEQ 359
|
||||
#define KW_MAKE_SEQ_PROPERTY 360
|
||||
#define KW_MUTABLE 361
|
||||
#define KW_NAMESPACE 362
|
||||
#define KW_NEW 363
|
||||
#define KW_NOEXCEPT 364
|
||||
#define KW_NULLPTR 365
|
||||
#define KW_OPERATOR 366
|
||||
#define KW_OVERRIDE 367
|
||||
#define KW_PRIVATE 368
|
||||
#define KW_PROTECTED 369
|
||||
#define KW_PUBLIC 370
|
||||
#define KW_REGISTER 371
|
||||
#define KW_REINTERPRET_CAST 372
|
||||
#define KW_RETURN 373
|
||||
#define KW_SHORT 374
|
||||
#define KW_SIGNED 375
|
||||
#define KW_SIZEOF 376
|
||||
#define KW_STATIC 377
|
||||
#define KW_STATIC_ASSERT 378
|
||||
#define KW_STATIC_CAST 379
|
||||
#define KW_STRUCT 380
|
||||
#define KW_TEMPLATE 381
|
||||
#define KW_THREAD_LOCAL 382
|
||||
#define KW_THROW 383
|
||||
#define KW_TRUE 384
|
||||
#define KW_TRY 385
|
||||
#define KW_TYPEDEF 386
|
||||
#define KW_TYPEID 387
|
||||
#define KW_TYPENAME 388
|
||||
#define KW_UNDERLYING_TYPE 389
|
||||
#define KW_UNION 390
|
||||
#define KW_UNSIGNED 391
|
||||
#define KW_USING 392
|
||||
#define KW_VIRTUAL 393
|
||||
#define KW_VOID 394
|
||||
#define KW_VOLATILE 395
|
||||
#define KW_WCHAR_T 396
|
||||
#define KW_WHILE 397
|
||||
#define START_CPP 398
|
||||
#define START_CONST_EXPR 399
|
||||
#define START_TYPE 400
|
||||
#define KW_MAKE_MAP_KEYS_SEQ 356
|
||||
#define KW_MAKE_MAP_PROPERTY 357
|
||||
#define KW_MAKE_PROPERTY 358
|
||||
#define KW_MAKE_PROPERTY2 359
|
||||
#define KW_MAKE_SEQ 360
|
||||
#define KW_MAKE_SEQ_PROPERTY 361
|
||||
#define KW_MUTABLE 362
|
||||
#define KW_NAMESPACE 363
|
||||
#define KW_NEW 364
|
||||
#define KW_NOEXCEPT 365
|
||||
#define KW_NULLPTR 366
|
||||
#define KW_OPERATOR 367
|
||||
#define KW_OVERRIDE 368
|
||||
#define KW_PRIVATE 369
|
||||
#define KW_PROTECTED 370
|
||||
#define KW_PUBLIC 371
|
||||
#define KW_REGISTER 372
|
||||
#define KW_REINTERPRET_CAST 373
|
||||
#define KW_RETURN 374
|
||||
#define KW_SHORT 375
|
||||
#define KW_SIGNED 376
|
||||
#define KW_SIZEOF 377
|
||||
#define KW_STATIC 378
|
||||
#define KW_STATIC_ASSERT 379
|
||||
#define KW_STATIC_CAST 380
|
||||
#define KW_STRUCT 381
|
||||
#define KW_TEMPLATE 382
|
||||
#define KW_THREAD_LOCAL 383
|
||||
#define KW_THROW 384
|
||||
#define KW_TRUE 385
|
||||
#define KW_TRY 386
|
||||
#define KW_TYPEDEF 387
|
||||
#define KW_TYPEID 388
|
||||
#define KW_TYPENAME 389
|
||||
#define KW_UNDERLYING_TYPE 390
|
||||
#define KW_UNION 391
|
||||
#define KW_UNSIGNED 392
|
||||
#define KW_USING 393
|
||||
#define KW_VIRTUAL 394
|
||||
#define KW_VOID 395
|
||||
#define KW_VOLATILE 396
|
||||
#define KW_WCHAR_T 397
|
||||
#define KW_WHILE 398
|
||||
#define START_CPP 399
|
||||
#define START_CONST_EXPR 400
|
||||
#define START_TYPE 401
|
||||
|
||||
/* Value type. */
|
||||
|
||||
|
|
|
|||
|
|
@ -304,6 +304,7 @@ pop_struct() {
|
|||
%token KW_IS_TRIVIAL
|
||||
%token KW_IS_UNION
|
||||
%token KW_LONG
|
||||
%token KW_MAKE_MAP_KEYS_SEQ
|
||||
%token KW_MAKE_MAP_PROPERTY
|
||||
%token KW_MAKE_PROPERTY
|
||||
%token KW_MAKE_PROPERTY2
|
||||
|
|
@ -680,6 +681,49 @@ declaration:
|
|||
make_property->_del_function = deleter->as_function_group();
|
||||
}
|
||||
|
||||
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
||||
}
|
||||
}
|
||||
| KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';'
|
||||
{
|
||||
CPPDeclaration *length_getter = $5->find_symbol(current_scope, global_scope, current_lexer);
|
||||
if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||
yyerror("reference to non-existent or invalid length method: " + $5->get_fully_scoped_name(), @5);
|
||||
length_getter = NULL;
|
||||
}
|
||||
|
||||
CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer);
|
||||
if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||
yyerror("Reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7);
|
||||
getter = nullptr;
|
||||
}
|
||||
|
||||
if (getter != nullptr && length_getter != nullptr) {
|
||||
CPPMakeProperty *make_property = new CPPMakeProperty($3, CPPMakeProperty::T_sequence, current_scope, @1.file);
|
||||
make_property->_get_function = getter->as_function_group();
|
||||
make_property->_length_function = length_getter->as_function_group();
|
||||
|
||||
CPPDeclaration *setter = $9->find_symbol(current_scope, global_scope, current_lexer);
|
||||
if (setter == nullptr || setter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||
yyerror("Reference to non-existent or invalid setter: " + $9->get_fully_scoped_name(), @9);
|
||||
} else {
|
||||
make_property->_set_function = setter->as_function_group();
|
||||
}
|
||||
|
||||
CPPDeclaration *deleter = $11->find_symbol(current_scope, global_scope, current_lexer);
|
||||
if (deleter == nullptr || deleter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||
yyerror("reference to non-existent or invalid delete method: " + $11->get_fully_scoped_name(), @11);
|
||||
} else {
|
||||
make_property->_del_function = deleter->as_function_group();
|
||||
}
|
||||
|
||||
CPPDeclaration *inserter = $13->find_symbol(current_scope, global_scope, current_lexer);
|
||||
if (inserter == nullptr || inserter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||
yyerror("reference to non-existent or invalid append method: " + $13->get_fully_scoped_name(), @13);
|
||||
} else {
|
||||
make_property->_insert_function = inserter->as_function_group();
|
||||
}
|
||||
|
||||
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
||||
}
|
||||
}
|
||||
|
|
@ -751,6 +795,40 @@ declaration:
|
|||
|
||||
current_scope->add_declaration(make_property, global_scope, current_lexer, @1);
|
||||
}
|
||||
}
|
||||
| KW_MAKE_MAP_KEYS_SEQ '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';'
|
||||
{
|
||||
CPPDeclaration *length_getter = $5->find_symbol(current_scope, global_scope, current_lexer);
|
||||
if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||
yyerror("reference to non-existent or invalid length method: " + $5->get_fully_scoped_name(), @5);
|
||||
length_getter = nullptr;
|
||||
}
|
||||
|
||||
CPPDeclaration *getter = $7->find_symbol(current_scope, global_scope, current_lexer);
|
||||
if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||
yyerror("reference to non-existent or invalid getter: " + $7->get_fully_scoped_name(), @7);
|
||||
getter = nullptr;
|
||||
}
|
||||
|
||||
if (getter != nullptr && length_getter != nullptr) {
|
||||
CPPMakeProperty *make_property = nullptr;
|
||||
for (size_t i = 0; i < current_scope->_declarations.size(); ++i) {
|
||||
make_property = current_scope->_declarations[i]->as_make_property();
|
||||
if (make_property != nullptr) {
|
||||
if (make_property->get_fully_scoped_name() == $3->get_fully_scoped_name()) {
|
||||
break;
|
||||
} else {
|
||||
make_property = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (make_property != nullptr) {
|
||||
make_property->_get_key_function = getter->as_function_group();
|
||||
make_property->_length_function = length_getter->as_function_group();
|
||||
} else {
|
||||
yyerror("reference to non-existent MAKE_MAP_PROPERTY: " + $3->get_fully_scoped_name(), @3);
|
||||
}
|
||||
}
|
||||
}
|
||||
| KW_MAKE_PROPERTY2 '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';'
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,7 +28,9 @@ CPPMakeProperty(CPPIdentifier *ident, Type type,
|
|||
_get_function(nullptr),
|
||||
_set_function(nullptr),
|
||||
_clear_function(nullptr),
|
||||
_del_function(nullptr)
|
||||
_del_function(nullptr),
|
||||
_insert_function(nullptr),
|
||||
_get_key_function(nullptr)
|
||||
{
|
||||
_ident->_native_scope = current_scope;
|
||||
}
|
||||
|
|
@ -96,6 +98,10 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
|
|||
out << ", " << _del_function->_name;
|
||||
}
|
||||
|
||||
if (_insert_function != NULL) {
|
||||
out << ", " << _insert_function->_name;
|
||||
}
|
||||
|
||||
out << ");";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -109,6 +109,8 @@ public:
|
|||
CPPFunctionGroup *_set_function;
|
||||
CPPFunctionGroup *_clear_function;
|
||||
CPPFunctionGroup *_del_function;
|
||||
CPPFunctionGroup *_insert_function;
|
||||
CPPFunctionGroup *_get_key_function;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2641,6 +2641,7 @@ check_keyword(const string &name) {
|
|||
if (name == "__is_trivial") return KW_IS_TRIVIAL;
|
||||
if (name == "__is_union") return KW_IS_UNION;
|
||||
if (name == "long") return KW_LONG;
|
||||
if (name == "__make_map_keys_seq") return KW_MAKE_MAP_KEYS_SEQ;
|
||||
if (name == "__make_map_property") return KW_MAKE_MAP_PROPERTY;
|
||||
if (name == "__make_property") return KW_MAKE_PROPERTY;
|
||||
if (name == "__make_property2") return KW_MAKE_PROPERTY2;
|
||||
|
|
|
|||
|
|
@ -465,6 +465,7 @@ typedef struct _object PyObject;
|
|||
#define MAKE_SEQ(seq_name, num_name, element_name) __make_seq(seq_name, num_name, element_name)
|
||||
#define MAKE_SEQ_PROPERTY(property_name, ...) __make_seq_property(property_name, __VA_ARGS__)
|
||||
#define MAKE_MAP_PROPERTY(property_name, ...) __make_map_property(property_name, __VA_ARGS__)
|
||||
#define MAKE_MAP_KEYS_SEQ(property_name, ...) __make_map_keys_seq(property_name, __VA_ARGS__)
|
||||
#define EXTENSION(x) __extension x
|
||||
#define EXTEND __extension
|
||||
#else
|
||||
|
|
@ -476,6 +477,7 @@ typedef struct _object PyObject;
|
|||
#define MAKE_SEQ(seq_name, num_name, element_name)
|
||||
#define MAKE_SEQ_PROPERTY(property_name, ...)
|
||||
#define MAKE_MAP_PROPERTY(property_name, ...)
|
||||
#define MAKE_MAP_KEYS_SEQ(property_name, ...)
|
||||
#define EXTENSION(x)
|
||||
#define EXTEND
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -47,7 +47,9 @@ static_assert(MEMORY_HOOK_ALIGNMENT * 8 >= NATIVE_WORDSIZE,
|
|||
static_assert((MEMORY_HOOK_ALIGNMENT & (MEMORY_HOOK_ALIGNMENT - 1)) == 0,
|
||||
"MEMORY_HOOK_ALIGNMENT should be a power of two");
|
||||
|
||||
#if defined(USE_MEMORY_DLMALLOC)
|
||||
#if defined(CPPPARSER)
|
||||
|
||||
#elif defined(USE_MEMORY_DLMALLOC)
|
||||
|
||||
// Memory manager: DLMALLOC This is Doug Lea's memory manager. It is very
|
||||
// fast, but it is not thread-safe. However, we provide thread locking within
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@ Property(const InterrogateElement &ielement) :
|
|||
_has_function(nullptr),
|
||||
_clear_function(nullptr),
|
||||
_deleter(nullptr),
|
||||
_inserter(nullptr),
|
||||
_getkey_function(nullptr),
|
||||
_has_this(false)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,6 +132,8 @@ public:
|
|||
Function *_has_function;
|
||||
Function *_clear_function;
|
||||
Function *_deleter;
|
||||
Function *_inserter;
|
||||
Function *_getkey_function;
|
||||
bool _has_this;
|
||||
};
|
||||
typedef vector<Property *> Properties;
|
||||
|
|
|
|||
|
|
@ -6391,6 +6391,8 @@ write_getset(ostream &out, Object *obj, Property *property) {
|
|||
|
||||
FunctionRemap *len_remap = nullptr;
|
||||
if (property->_length_function != nullptr) {
|
||||
assert(!property->_length_function->_remaps.empty());
|
||||
|
||||
// This is actually a sequence. Wrap this with a special class.
|
||||
len_remap = property->_length_function->_remaps.front();
|
||||
|
||||
|
|
@ -6416,6 +6418,7 @@ write_getset(ostream &out, Object *obj, Property *property) {
|
|||
}
|
||||
|
||||
if (ielem.is_sequence()) {
|
||||
assert(len_remap != nullptr);
|
||||
out <<
|
||||
"/**\n"
|
||||
" * sequence getter for property " << ielem.get_scoped_name() << "\n"
|
||||
|
|
@ -6543,6 +6546,35 @@ write_getset(ostream &out, Object *obj, Property *property) {
|
|||
out << " return -1;\n";
|
||||
out << "}\n\n";
|
||||
}
|
||||
|
||||
// Finally, add the inserter, if one exists.
|
||||
if (property->_inserter != nullptr) {
|
||||
out << "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Sequence_insert(PyObject *self, size_t index, PyObject *arg) {\n";
|
||||
if (property->_has_this) {
|
||||
out << " " << cClassName << " *local_this = NULL;\n";
|
||||
out << " if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this, \""
|
||||
<< classNameFromCppName(cClassName, false) << "." << ielem.get_name() << "\")) {\n";
|
||||
out << " return NULL;\n";
|
||||
out << " }\n\n";
|
||||
}
|
||||
|
||||
std::set<FunctionRemap*> remaps;
|
||||
remaps.insert(property->_inserter->_remaps.begin(),
|
||||
property->_inserter->_remaps.end());
|
||||
|
||||
string expected_params;
|
||||
write_function_forset(out, remaps, 2, 2,
|
||||
expected_params, 2, true, true, AT_single_arg,
|
||||
RF_pyobject | RF_err_null, false, false, "index");
|
||||
|
||||
out << " if (!_PyErr_OCCURRED()) {\n";
|
||||
out << " Dtool_Raise_BadArgumentsError(\n";
|
||||
output_quoted(out, 6, expected_params);
|
||||
out << ");\n";
|
||||
out << " }\n";
|
||||
out << " return NULL;\n";
|
||||
out << "}\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -6674,7 +6706,7 @@ write_getset(ostream &out, Object *obj, Property *property) {
|
|||
remaps.insert(property->_setter_remaps.begin(),
|
||||
property->_setter_remaps.end());
|
||||
|
||||
// We have to create an args tuple only to unpack it alter, ugh.
|
||||
// We have to create an args tuple only to unpack it later, ugh.
|
||||
out << " PyObject *args = PyTuple_New(2);\n"
|
||||
<< " PyTuple_SET_ITEM(args, 0, key);\n"
|
||||
<< " PyTuple_SET_ITEM(args, 1, value);\n"
|
||||
|
|
@ -6695,86 +6727,117 @@ write_getset(ostream &out, Object *obj, Property *property) {
|
|||
out << " return -1;\n";
|
||||
out << "}\n\n";
|
||||
}
|
||||
|
||||
if (property->_getkey_function != nullptr) {
|
||||
out <<
|
||||
"/**\n"
|
||||
" * mapping key-getter for property " << ielem.get_scoped_name() << "\n"
|
||||
" */\n"
|
||||
"static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Mapping_Getkey(PyObject *self, Py_ssize_t index) {\n";
|
||||
|
||||
if (property->_has_this) {
|
||||
out <<
|
||||
" " << cClassName << " *local_this = NULL;\n"
|
||||
" if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"
|
||||
" return NULL;\n"
|
||||
" }\n";
|
||||
}
|
||||
|
||||
// We need to raise IndexError if we're out of bounds.
|
||||
if (len_remap != nullptr) {
|
||||
out << " if (index < 0 || index >= (Py_ssize_t)"
|
||||
<< len_remap->get_call_str("local_this", pexprs) << ") {\n";
|
||||
out << " PyErr_SetString(PyExc_IndexError, \"" << ClassName << "." << ielem.get_name() << "[] index out of range\");\n";
|
||||
out << " return NULL;\n";
|
||||
out << " }\n";
|
||||
}
|
||||
|
||||
std::set<FunctionRemap*> remaps;
|
||||
|
||||
// Extract only the getters that take one integral argument.
|
||||
Function::Remaps::iterator it;
|
||||
for (it = property->_getkey_function->_remaps.begin();
|
||||
it != property->_getkey_function->_remaps.end();
|
||||
++it) {
|
||||
FunctionRemap *remap = *it;
|
||||
int min_num_args = remap->get_min_num_args();
|
||||
int max_num_args = remap->get_max_num_args();
|
||||
if (min_num_args <= 1 && max_num_args >= 1 &&
|
||||
TypeManager::is_integer(remap->_parameters[(size_t)remap->_has_this]._remap->get_new_type())) {
|
||||
remaps.insert(remap);
|
||||
}
|
||||
}
|
||||
|
||||
string expected_params;
|
||||
write_function_forset(out, remaps, 1, 1, expected_params, 2, true, true,
|
||||
AT_no_args, RF_pyobject | RF_err_null, false, true, "index");
|
||||
|
||||
out << " if (!_PyErr_OCCURRED()) {\n";
|
||||
out << " return Dtool_Raise_BadArgumentsError(\n";
|
||||
output_quoted(out, 6, expected_params);
|
||||
out << ");\n"
|
||||
" }\n"
|
||||
"}\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Now write the actual getter wrapper. It will be a different wrapper
|
||||
// depending on whether it's a mapping, sequence, or both.
|
||||
if (ielem.is_mapping() && ielem.is_sequence()) {
|
||||
// depending on whether it's a mapping or a sequence.
|
||||
if (ielem.is_mapping()) {
|
||||
out << "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter(PyObject *self, void *) {\n";
|
||||
if (property->_has_this) {
|
||||
out << " nassertr(self != NULL, NULL);\n"
|
||||
" Py_INCREF(self);\n";
|
||||
} else {
|
||||
out << " Py_XINCREF(self);\n";
|
||||
out << " nassertr(self != NULL, NULL);\n";
|
||||
}
|
||||
out << " Dtool_SeqMapWrapper *wrap = PyObject_New(Dtool_SeqMapWrapper, &Dtool_SeqMapWrapper_Type);\n"
|
||||
" wrap->_map._base._self = self;\n"
|
||||
" wrap->_map._base._name = \"" << ClassName << "." << ielem.get_name() << "\";\n"
|
||||
" wrap->_len_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Len;\n"
|
||||
" wrap->_seq_getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Sequence_Getitem;\n"
|
||||
" wrap->_map._getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Mapping_Getitem;\n";
|
||||
if (property->_setter_remaps.empty()) {
|
||||
out << " Dtool_MappingWrapper *wrap = Dtool_NewMappingWrapper(self, \"" << ClassName << "." << ielem.get_name() << "\");\n";
|
||||
} else {
|
||||
out << " Dtool_MappingWrapper *wrap = Dtool_NewMutableMappingWrapper(self, \"" << ClassName << "." << ielem.get_name() << "\");\n";
|
||||
}
|
||||
out << " if (wrap != NULL) {\n"
|
||||
" wrap->_getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Mapping_Getitem;\n";
|
||||
if (!property->_setter_remaps.empty()) {
|
||||
out << " if (!((Dtool_PyInstDef *)self)->_is_const) {\n"
|
||||
" wrap->_seq_setitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Sequence_Setitem;\n"
|
||||
" wrap->_map._setitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Mapping_Setitem;\n"
|
||||
" } else {\n"
|
||||
" wrap->_seq_setitem_func = NULL;\n"
|
||||
" wrap->_map._setitem_func = NULL;\n"
|
||||
" }\n";
|
||||
} else {
|
||||
out << " wrap->_seq_setitem_func = NULL;\n";
|
||||
out << " wrap->_map._setitem_func = NULL;\n";
|
||||
out << " if (!((Dtool_PyInstDef *)self)->_is_const) {\n";
|
||||
out << " wrap->_setitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Mapping_Setitem;\n";
|
||||
out << " }\n";
|
||||
}
|
||||
out << " return (PyObject *)wrap;\n"
|
||||
if (property->_length_function != nullptr) {
|
||||
out << " wrap->_keys._len_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Len;\n";
|
||||
if (property->_getkey_function != nullptr) {
|
||||
out << " wrap->_keys._getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Mapping_Getkey;\n";
|
||||
}
|
||||
}
|
||||
out << " }\n"
|
||||
" return (PyObject *)wrap;\n"
|
||||
"}\n\n";
|
||||
|
||||
} else if (ielem.is_mapping()) {
|
||||
out << "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter(PyObject *self, void *) {\n";
|
||||
if (property->_has_this) {
|
||||
out << " nassertr(self != NULL, NULL);\n"
|
||||
" Py_INCREF(self);\n";
|
||||
} else {
|
||||
out << " Py_XINCREF(self);\n";
|
||||
}
|
||||
out << " Dtool_MappingWrapper *wrap = PyObject_New(Dtool_MappingWrapper, &Dtool_MappingWrapper_Type);\n"
|
||||
" wrap->_base._self = self;\n"
|
||||
" wrap->_base._name = \"" << ClassName << "." << ielem.get_name() << "\";\n"
|
||||
" wrap->_getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Mapping_Getitem;\n";
|
||||
if (!property->_setter_remaps.empty()) {
|
||||
out << " if (!((Dtool_PyInstDef *)self)->_is_const) {\n";
|
||||
out << " wrap->_setitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Mapping_Setitem;\n";
|
||||
out << " } else {\n";
|
||||
out << " wrap->_setitem_func = NULL;\n";
|
||||
out << " }\n";
|
||||
} else {
|
||||
out << " wrap->_setitem_func = NULL;\n";
|
||||
}
|
||||
out << " return (PyObject *)wrap;\n"
|
||||
"}\n\n";
|
||||
|
||||
} else if (ielem.is_sequence()) {
|
||||
out << "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter(PyObject *self, void *) {\n";
|
||||
if (property->_has_this) {
|
||||
out << " nassertr(self != NULL, NULL);\n"
|
||||
" Py_INCREF(self);\n";
|
||||
} else {
|
||||
out << " Py_XINCREF(self);\n";
|
||||
out << " nassertr(self != NULL, NULL);\n";
|
||||
}
|
||||
out << " Dtool_SequenceWrapper *wrap = PyObject_New(Dtool_SequenceWrapper, &Dtool_SequenceWrapper_Type);\n"
|
||||
" wrap->_base._self = self;\n"
|
||||
" wrap->_base._name = \"" << ClassName << "." << ielem.get_name() << "\";\n"
|
||||
" wrap->_len_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Len;\n"
|
||||
" wrap->_getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Sequence_Getitem;\n";
|
||||
if (!property->_setter_remaps.empty()) {
|
||||
out << " if (!((Dtool_PyInstDef *)self)->_is_const) {\n";
|
||||
out << " wrap->_setitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Sequence_Setitem;\n";
|
||||
out << " } else {\n";
|
||||
out << " wrap->_setitem_func = NULL;\n";
|
||||
out << " }\n";
|
||||
if (property->_setter_remaps.empty()) {
|
||||
out <<
|
||||
" Dtool_SequenceWrapper *wrap = Dtool_NewSequenceWrapper(self, \"" << ClassName << "." << ielem.get_name() << "\");\n"
|
||||
" if (wrap != NULL) {\n"
|
||||
" wrap->_len_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Len;\n"
|
||||
" wrap->_getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Sequence_Getitem;\n";
|
||||
} else {
|
||||
out << " wrap->_setitem_func = NULL;\n";
|
||||
out <<
|
||||
" Dtool_MutableSequenceWrapper *wrap = Dtool_NewMutableSequenceWrapper(self, \"" << ClassName << "." << ielem.get_name() << "\");\n"
|
||||
" if (wrap != NULL) {\n"
|
||||
" wrap->_len_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Len;\n"
|
||||
" wrap->_getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Sequence_Getitem;\n";
|
||||
if (!property->_setter_remaps.empty()) {
|
||||
out << " if (!((Dtool_PyInstDef *)self)->_is_const) {\n";
|
||||
out << " wrap->_setitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Sequence_Setitem;\n";
|
||||
if (property->_inserter != nullptr) {
|
||||
out << " wrap->_insert_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Sequence_insert;\n";
|
||||
}
|
||||
out << " }\n";
|
||||
}
|
||||
}
|
||||
out << " return (PyObject *)wrap;\n"
|
||||
out << " }\n"
|
||||
" return (PyObject *)wrap;\n"
|
||||
"}\n\n";
|
||||
|
||||
} else {
|
||||
|
|
@ -7083,9 +7146,30 @@ record_property(const InterrogateType &itype, ElementIndex element_index) {
|
|||
}
|
||||
}
|
||||
|
||||
if (ielement.is_sequence()) {
|
||||
if (ielement.is_sequence() || ielement.is_mapping()) {
|
||||
FunctionIndex func_index = ielement.get_length_function();
|
||||
property->_length_function = record_function(itype, func_index);
|
||||
if (func_index != 0) {
|
||||
property->_length_function = record_function(itype, func_index);
|
||||
}
|
||||
}
|
||||
|
||||
if (ielement.is_sequence() && ielement.has_insert_function()) {
|
||||
FunctionIndex func_index = ielement.get_insert_function();
|
||||
Function *insert_function = record_function(itype, func_index);
|
||||
if (is_function_legal(insert_function)) {
|
||||
property->_inserter = insert_function;
|
||||
property->_has_this |= insert_function->_has_this;
|
||||
}
|
||||
}
|
||||
|
||||
if (ielement.is_mapping() && ielement.has_getkey_function()) {
|
||||
FunctionIndex func_index = ielement.get_getkey_function();
|
||||
assert(func_index != 0);
|
||||
Function *getkey_function = record_function(itype, func_index);
|
||||
if (is_function_legal(getkey_function)) {
|
||||
property->_getkey_function = getkey_function;
|
||||
property->_has_this |= getkey_function->_has_this;
|
||||
}
|
||||
}
|
||||
|
||||
return property;
|
||||
|
|
|
|||
|
|
@ -1824,20 +1824,17 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
|
|||
// If we have a length function (ie. this is a sequence property), we should
|
||||
// find the function that will give us the length.
|
||||
FunctionIndex length_function = 0;
|
||||
if (make_property->_type & CPPMakeProperty::T_sequence) {
|
||||
CPPFunctionGroup *fgroup = make_property->_length_function;
|
||||
if (fgroup != nullptr) {
|
||||
CPPFunctionGroup::Instances::const_iterator fi;
|
||||
CPPFunctionGroup *fgroup = make_property->_length_function;
|
||||
if (fgroup != NULL) {
|
||||
for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
|
||||
CPPInstance *function = (*fi);
|
||||
CPPFunctionType *ftype =
|
||||
function->_type->as_function_type();
|
||||
if (ftype != NULL) {
|
||||
length_function = get_function(function, "", struct_type,
|
||||
struct_type->get_scope(), 0);
|
||||
if (length_function != 0) {
|
||||
break;
|
||||
}
|
||||
for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
|
||||
CPPInstance *function = (*fi);
|
||||
CPPFunctionType *ftype = function->_type->as_function_type();
|
||||
if (ftype != nullptr) {
|
||||
length_function = get_function(function, "", struct_type,
|
||||
struct_type->get_scope(), 0);
|
||||
if (length_function != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1855,7 +1852,7 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
|
|||
// How many arguments we expect the getter to have.
|
||||
size_t num_args = (size_t)(make_property->_type != CPPMakeProperty::T_normal);
|
||||
|
||||
CPPFunctionGroup *fgroup = make_property->_get_function;
|
||||
fgroup = make_property->_get_function;
|
||||
if (fgroup != NULL) {
|
||||
CPPFunctionGroup::Instances::const_iterator fi;
|
||||
for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
|
||||
|
|
@ -1942,9 +1939,13 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
|
|||
for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
|
||||
CPPInstance *function = (*fi);
|
||||
CPPFunctionType *ftype = function->_type->as_function_type();
|
||||
if (ftype != NULL && ftype->_parameters->_parameters.size() == num_args) {
|
||||
deleter = function;
|
||||
break;
|
||||
if (ftype != nullptr) {
|
||||
const CPPParameterList::Parameters ¶ms = ftype->_parameters->_parameters;
|
||||
if (params.size() == num_args ||
|
||||
(params.size() > num_args && params[num_args]->_initializer != nullptr)) {
|
||||
deleter = function;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1955,6 +1956,50 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
|
|||
}
|
||||
}
|
||||
|
||||
// And the "inserter".
|
||||
CPPInstance *inserter = nullptr;
|
||||
|
||||
fgroup = make_property->_insert_function;
|
||||
if (fgroup != nullptr) {
|
||||
CPPFunctionGroup::Instances::const_iterator fi;
|
||||
for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
|
||||
CPPInstance *function = (*fi);
|
||||
CPPFunctionType *ftype = function->_type->as_function_type();
|
||||
if (ftype != nullptr && ftype->_parameters->_parameters.size() == 2) {
|
||||
inserter = function;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (inserter == nullptr) {
|
||||
cerr << "No instance of insert-function '"
|
||||
<< fgroup->_name << "' is suitable!\n";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// And the function that returns a key by index.
|
||||
CPPInstance *getkey_function = nullptr;
|
||||
|
||||
fgroup = make_property->_get_key_function;
|
||||
if (fgroup != nullptr) {
|
||||
CPPFunctionGroup::Instances::const_iterator fi;
|
||||
for (fi = fgroup->_instances.begin(); fi != fgroup->_instances.end(); ++fi) {
|
||||
CPPInstance *function = (*fi);
|
||||
CPPFunctionType *ftype = function->_type->as_function_type();
|
||||
if (ftype != nullptr) {
|
||||
getkey_function = function;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (getkey_function == nullptr) {
|
||||
cerr << "No instance of get-key-function '"
|
||||
<< fgroup->_name << "' is suitable!\n";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == 0) {
|
||||
// It isn't here, so we'll have to define it.
|
||||
index = idb->get_next_index();
|
||||
|
|
@ -1980,10 +2025,12 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
|
|||
if (make_property->_type & CPPMakeProperty::T_sequence) {
|
||||
iproperty._flags |= InterrogateElement::F_sequence;
|
||||
iproperty._length_function = length_function;
|
||||
assert(length_function != 0);
|
||||
}
|
||||
|
||||
if (make_property->_type & CPPMakeProperty::T_mapping) {
|
||||
iproperty._flags |= InterrogateElement::F_mapping;
|
||||
iproperty._length_function = length_function;
|
||||
}
|
||||
|
||||
if (make_property->_type == CPPMakeProperty::T_normal) {
|
||||
|
|
@ -2029,6 +2076,20 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
|
|||
nassertr(iproperty._del_function, 0);
|
||||
}
|
||||
|
||||
if (inserter != NULL) {
|
||||
iproperty._flags |= InterrogateElement::F_has_insert_function;
|
||||
iproperty._insert_function = get_function(inserter, "", struct_type,
|
||||
struct_type->get_scope(), 0);
|
||||
nassertr(iproperty._insert_function, 0);
|
||||
}
|
||||
|
||||
if (getkey_function != NULL) {
|
||||
iproperty._flags |= InterrogateElement::F_has_getkey_function;
|
||||
iproperty._getkey_function = get_function(getkey_function, "", struct_type,
|
||||
struct_type->get_scope(), 0);
|
||||
nassertr(iproperty._getkey_function, 0);
|
||||
}
|
||||
|
||||
// See if there happens to be a comment before the MAKE_PROPERTY macro.
|
||||
if (make_property->_leading_comment != (CPPCommentBlock *)NULL) {
|
||||
iproperty._comment = trim_blanks(make_property->_leading_comment->_comment);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ InterrogateDatabase *InterrogateDatabase::_global_ptr = NULL;
|
|||
int InterrogateDatabase::_file_major_version = 0;
|
||||
int InterrogateDatabase::_file_minor_version = 0;
|
||||
int InterrogateDatabase::_current_major_version = 3;
|
||||
int InterrogateDatabase::_current_minor_version = 2;
|
||||
int InterrogateDatabase::_current_minor_version = 3;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ InterrogateElement(InterrogateModuleDef *def) :
|
|||
_has_function = 0;
|
||||
_clear_function = 0;
|
||||
_del_function = 0;
|
||||
_insert_function = 0;
|
||||
_getkey_function = 0;
|
||||
_length_function = 0;
|
||||
_make_property = nullptr;
|
||||
}
|
||||
|
|
@ -52,6 +54,8 @@ operator = (const InterrogateElement ©) {
|
|||
_has_function = copy._has_function;
|
||||
_clear_function = copy._clear_function;
|
||||
_del_function = copy._del_function;
|
||||
_insert_function = copy._insert_function;
|
||||
_getkey_function = copy._getkey_function;
|
||||
_length_function = copy._length_function;
|
||||
_make_property = copy._make_property;
|
||||
}
|
||||
|
|
@ -185,6 +189,38 @@ get_del_function() const {
|
|||
return _del_function;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE bool InterrogateElement::
|
||||
has_insert_function() const {
|
||||
return (_flags & F_has_insert_function) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE FunctionIndex InterrogateElement::
|
||||
get_insert_function() const {
|
||||
return _insert_function;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE bool InterrogateElement::
|
||||
has_getkey_function() const {
|
||||
return (_flags & F_has_getkey_function) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE FunctionIndex InterrogateElement::
|
||||
get_getkey_function() const {
|
||||
return _getkey_function;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -29,7 +29,9 @@ output(ostream &out) const {
|
|||
<< _has_function << " "
|
||||
<< _clear_function << " "
|
||||
<< _del_function << " "
|
||||
<< _length_function << " ";
|
||||
<< _length_function << " "
|
||||
<< _insert_function << " "
|
||||
<< _getkey_function << " ";
|
||||
idf_output_string(out, _scoped_name);
|
||||
idf_output_string(out, _comment, '\n');
|
||||
}
|
||||
|
|
@ -45,6 +47,9 @@ input(istream &in) {
|
|||
in >> _has_function >> _clear_function;
|
||||
if (InterrogateDatabase::get_file_minor_version() >= 2) {
|
||||
in >> _del_function >> _length_function;
|
||||
if (InterrogateDatabase::get_file_minor_version() >= 3) {
|
||||
in >> _insert_function >> _getkey_function;
|
||||
}
|
||||
}
|
||||
}
|
||||
idf_input_string(in, _scoped_name);
|
||||
|
|
@ -63,5 +68,7 @@ remap_indices(const IndexRemapper &remap) {
|
|||
_has_function = remap.map_from(_has_function);
|
||||
_clear_function = remap.map_from(_clear_function);
|
||||
_del_function = remap.map_from(_del_function);
|
||||
_insert_function = remap.map_from(_insert_function);
|
||||
_getkey_function = remap.map_from(_getkey_function);
|
||||
_length_function = remap.map_from(_length_function);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,10 @@ public:
|
|||
INLINE FunctionIndex get_clear_function() const;
|
||||
INLINE bool has_del_function() const;
|
||||
INLINE FunctionIndex get_del_function() const;
|
||||
INLINE bool has_insert_function() const;
|
||||
INLINE FunctionIndex get_insert_function() const;
|
||||
INLINE bool has_getkey_function() const;
|
||||
INLINE FunctionIndex get_getkey_function() const;
|
||||
INLINE bool is_sequence() const;
|
||||
INLINE FunctionIndex get_length_function() const;
|
||||
INLINE bool is_mapping() const;
|
||||
|
|
@ -69,6 +73,8 @@ private:
|
|||
F_has_del_function= 0x0020,
|
||||
F_sequence = 0x0040,
|
||||
F_mapping = 0x0080,
|
||||
F_has_insert_function= 0x0100,
|
||||
F_has_getkey_function= 0x0200,
|
||||
};
|
||||
|
||||
int _flags;
|
||||
|
|
@ -81,6 +87,8 @@ private:
|
|||
FunctionIndex _has_function;
|
||||
FunctionIndex _clear_function;
|
||||
FunctionIndex _del_function;
|
||||
FunctionIndex _insert_function;
|
||||
FunctionIndex _getkey_function;
|
||||
|
||||
CPPMakeProperty *_make_property;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,4 @@
|
|||
#include "interrogate_interface.cxx"
|
||||
#include "interrogate_request.cxx"
|
||||
#include "py_panda.cxx"
|
||||
|
||||
|
||||
|
||||
|
||||
#include "py_wrappers.cxx"
|
||||
|
|
|
|||
|
|
@ -614,12 +614,28 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
|
|||
return Dtool_Raise_TypeError("PyType_Ready(Dtool_SequenceWrapper)");
|
||||
}
|
||||
|
||||
if (PyType_Ready(&Dtool_MutableSequenceWrapper_Type) < 0) {
|
||||
return Dtool_Raise_TypeError("PyType_Ready(Dtool_MutableSequenceWrapper)");
|
||||
}
|
||||
|
||||
if (PyType_Ready(&Dtool_MappingWrapper_Type) < 0) {
|
||||
return Dtool_Raise_TypeError("PyType_Ready(Dtool_MappingWrapper)");
|
||||
}
|
||||
|
||||
if (PyType_Ready(&Dtool_SeqMapWrapper_Type) < 0) {
|
||||
return Dtool_Raise_TypeError("PyType_Ready(Dtool_SeqMapWrapper)");
|
||||
if (PyType_Ready(&Dtool_MutableMappingWrapper_Type) < 0) {
|
||||
return Dtool_Raise_TypeError("PyType_Ready(Dtool_MutableMappingWrapper)");
|
||||
}
|
||||
|
||||
if (PyType_Ready(&Dtool_MappingWrapper_Keys_Type) < 0) {
|
||||
return Dtool_Raise_TypeError("PyType_Ready(Dtool_MappingWrapper_Keys)");
|
||||
}
|
||||
|
||||
if (PyType_Ready(&Dtool_MappingWrapper_Values_Type) < 0) {
|
||||
return Dtool_Raise_TypeError("PyType_Ready(Dtool_MappingWrapper_Values)");
|
||||
}
|
||||
|
||||
if (PyType_Ready(&Dtool_MappingWrapper_Items_Type) < 0) {
|
||||
return Dtool_Raise_TypeError("PyType_Ready(Dtool_MappingWrapper_Items)");
|
||||
}
|
||||
|
||||
if (PyType_Ready(&Dtool_GeneratorWrapper_Type) < 0) {
|
||||
|
|
@ -1039,957 +1055,4 @@ bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args, PyObject *kwds)
|
|||
return (PyTuple_GET_SIZE(args) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* These classes are returned from properties that require a subscript
|
||||
* interface, ie. something.children[i] = 3.
|
||||
*/
|
||||
static void Dtool_WrapperBase_dealloc(PyObject *self) {
|
||||
Dtool_WrapperBase *wrap = (Dtool_WrapperBase *)self;
|
||||
nassertv(wrap);
|
||||
Py_XDECREF(wrap->_self);
|
||||
}
|
||||
|
||||
static PyObject *Dtool_WrapperBase_repr(PyObject *self) {
|
||||
Dtool_WrapperBase *wrap = (Dtool_WrapperBase *)self;
|
||||
nassertr(wrap, nullptr);
|
||||
|
||||
PyObject *repr = PyObject_Repr(wrap->_self);
|
||||
PyObject *result;
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
result = PyUnicode_FromFormat("<%s[] of %s>", wrap->_name, PyUnicode_AsUTF8(repr));
|
||||
#else
|
||||
result = PyString_FromFormat("<%s[] of %s>", wrap->_name, PyString_AS_STRING(repr));
|
||||
#endif
|
||||
Py_DECREF(repr);
|
||||
return result;
|
||||
}
|
||||
|
||||
static PyObject *Dtool_SequenceWrapper_repr(PyObject *self) {
|
||||
Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self;
|
||||
nassertr(wrap, nullptr);
|
||||
|
||||
Py_ssize_t len = -1;
|
||||
if (wrap->_len_func != nullptr) {
|
||||
len = wrap->_len_func(wrap->_base._self);
|
||||
}
|
||||
|
||||
if (len < 0) {
|
||||
PyErr_Restore(nullptr, nullptr, nullptr);
|
||||
return Dtool_WrapperBase_repr(self);
|
||||
}
|
||||
|
||||
PyObject *repr = PyObject_Repr(wrap->_base._self);
|
||||
PyObject *result;
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
result = PyUnicode_FromFormat("<%s[%zd] of %s>", wrap->_base._name, len, PyUnicode_AsUTF8(repr));
|
||||
#else
|
||||
result = PyString_FromFormat("<%s[%zd] of %s>", wrap->_base._name, len, PyString_AS_STRING(repr));
|
||||
#endif
|
||||
Py_DECREF(repr);
|
||||
return result;
|
||||
}
|
||||
|
||||
static Py_ssize_t Dtool_SequenceWrapper_length(PyObject *self) {
|
||||
Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self;
|
||||
nassertr(wrap, -1);
|
||||
if (wrap->_len_func != nullptr) {
|
||||
return wrap->_len_func(wrap->_base._self);
|
||||
} else {
|
||||
Dtool_Raise_TypeError("property does not support len()");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *Dtool_SequenceWrapper_getitem(PyObject *self, Py_ssize_t index) {
|
||||
Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self;
|
||||
nassertr(wrap, nullptr);
|
||||
nassertr(wrap->_getitem_func, nullptr);
|
||||
return wrap->_getitem_func(wrap->_base._self, index);
|
||||
}
|
||||
|
||||
static int Dtool_SequenceWrapper_setitem(PyObject *self, Py_ssize_t index, PyObject *value) {
|
||||
Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self;
|
||||
nassertr(wrap, -1);
|
||||
if (wrap->_setitem_func != nullptr) {
|
||||
return wrap->_setitem_func(wrap->_base._self, index, value);
|
||||
} else {
|
||||
Dtool_Raise_TypeError("property does not support item assignment");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of property.index(x) which returns the index of the first
|
||||
* occurrence of x in the sequence, or raises a ValueError if it isn't found.
|
||||
*/
|
||||
static PyObject *Dtool_SequenceWrapper_index(PyObject *self, PyObject *value) {
|
||||
Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self;
|
||||
nassertr(wrap, nullptr);
|
||||
Py_ssize_t length = 0;
|
||||
if (wrap->_len_func != nullptr && wrap->_setitem_func != nullptr) {
|
||||
length = wrap->_len_func(wrap->_base._self);
|
||||
} else {
|
||||
return Dtool_Raise_TypeError("property does not support remove()");
|
||||
}
|
||||
|
||||
// Iterate through the items, invoking the equality function for each, until
|
||||
// we have found the right one.
|
||||
nassertr(wrap->_getitem_func, nullptr);
|
||||
for (Py_ssize_t index = 0; index < length; ++index) {
|
||||
PyObject *item = wrap->_getitem_func(wrap->_base._self, index);
|
||||
if (item != nullptr) {
|
||||
int cmp = PyObject_RichCompareBool(item, value, Py_EQ);
|
||||
if (cmp > 0) {
|
||||
return Dtool_WrapValue(index);
|
||||
}
|
||||
if (cmp < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
// Not found, raise ValueError.
|
||||
return PyErr_Format(PyExc_ValueError, "%s.index() did not find value", wrap->_base._name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of property.count(x) which returns the number of occurrences
|
||||
* of x in the sequence.
|
||||
*/
|
||||
static PyObject *Dtool_SequenceWrapper_count(PyObject *self, PyObject *value) {
|
||||
Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self;
|
||||
nassertr(wrap, nullptr);
|
||||
Py_ssize_t index = 0;
|
||||
if (wrap->_len_func != nullptr) {
|
||||
index = wrap->_len_func(wrap->_base._self);
|
||||
} else {
|
||||
return Dtool_Raise_TypeError("property does not support count()");
|
||||
}
|
||||
// Iterate through the items, invoking the == operator for each.
|
||||
long count = 0;
|
||||
nassertr(wrap->_getitem_func, nullptr);
|
||||
while (index > 0) {
|
||||
--index;
|
||||
PyObject *item = wrap->_getitem_func(wrap->_base._self, index);
|
||||
if (item == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
int cmp = PyObject_RichCompareBool(item, value, Py_EQ);
|
||||
if (cmp > 0) {
|
||||
++count;
|
||||
}
|
||||
if (cmp < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return PyLong_FromLong(count);
|
||||
#else
|
||||
return PyInt_FromLong(count);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of property.clear() which removes all elements in the
|
||||
* sequence, starting with the last.
|
||||
*/
|
||||
static PyObject *Dtool_SequenceWrapper_clear(PyObject *self, PyObject *) {
|
||||
Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self;
|
||||
nassertr(wrap, nullptr);
|
||||
Py_ssize_t index = 0;
|
||||
if (wrap->_len_func != nullptr && wrap->_setitem_func != nullptr) {
|
||||
index = wrap->_len_func(wrap->_base._self);
|
||||
} else {
|
||||
return Dtool_Raise_TypeError("property does not support clear()");
|
||||
}
|
||||
|
||||
// Iterate through the items, invoking the delete function for each. We do
|
||||
// this in reverse order, which may be more efficient.
|
||||
while (index > 0) {
|
||||
--index;
|
||||
if (wrap->_setitem_func(wrap->_base._self, index, nullptr) != 0) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of property.remove(x) which removes the first occurrence of
|
||||
* x in the sequence, or raises a ValueError if it isn't found.
|
||||
*/
|
||||
static PyObject *Dtool_SequenceWrapper_remove(PyObject *self, PyObject *value) {
|
||||
Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self;
|
||||
nassertr(wrap, nullptr);
|
||||
Py_ssize_t length = 0;
|
||||
if (wrap->_len_func != nullptr && wrap->_setitem_func != nullptr) {
|
||||
length = wrap->_len_func(wrap->_base._self);
|
||||
} else {
|
||||
return Dtool_Raise_TypeError("property does not support remove()");
|
||||
}
|
||||
|
||||
// Iterate through the items, invoking the equality function for each, until
|
||||
// we have found the right one.
|
||||
nassertr(wrap->_getitem_func, nullptr);
|
||||
for (Py_ssize_t index = 0; index < length; ++index) {
|
||||
PyObject *item = wrap->_getitem_func(wrap->_base._self, index);
|
||||
if (item != nullptr) {
|
||||
int cmp = PyObject_RichCompareBool(item, value, Py_EQ);
|
||||
if (cmp > 0) {
|
||||
if (wrap->_setitem_func(wrap->_base._self, index, nullptr) == 0) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
if (cmp < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
// Not found, raise ValueError.
|
||||
return PyErr_Format(PyExc_ValueError, "%s.remove() did not find value", wrap->_base._name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of property.pop([i=-1]) which returns and removes the
|
||||
* element at the indicated index in the sequence. If no index is provided,
|
||||
* it removes from the end of the list.
|
||||
*/
|
||||
static PyObject *Dtool_SequenceWrapper_pop(PyObject *self, PyObject *args) {
|
||||
Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self;
|
||||
nassertr(wrap, nullptr);
|
||||
if (wrap->_getitem_func == nullptr || wrap->_setitem_func == nullptr ||
|
||||
wrap->_len_func == nullptr) {
|
||||
return Dtool_Raise_TypeError("property does not support pop()");
|
||||
}
|
||||
|
||||
Py_ssize_t length = wrap->_len_func(wrap->_base._self);
|
||||
Py_ssize_t index;
|
||||
switch (PyTuple_GET_SIZE(args)) {
|
||||
case 0:
|
||||
index = length - 1;
|
||||
break;
|
||||
case 1:
|
||||
index = PyNumber_AsSsize_t(PyTuple_GET_ITEM(args, 0), PyExc_IndexError);
|
||||
if (index == -1 && _PyErr_OCCURRED()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (index < 0) {
|
||||
index += length;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return Dtool_Raise_TypeError("pop([i=-1]) takes 0 or 1 arguments");
|
||||
}
|
||||
|
||||
if (length <= 0) {
|
||||
return PyErr_Format(PyExc_IndexError, "%s.pop() from empty sequence", wrap->_base._name);
|
||||
}
|
||||
|
||||
// Index error will be caught by getitem_func.
|
||||
PyObject *value = wrap->_getitem_func(wrap->_base._self, index);
|
||||
if (value != nullptr) {
|
||||
if (wrap->_setitem_func(wrap->_base._self, index, nullptr) != 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static int Dtool_MappingWrapper_contains(PyObject *self, PyObject *key) {
|
||||
Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self;
|
||||
nassertr(wrap, -1);
|
||||
nassertr(wrap->_getitem_func, -1);
|
||||
PyObject *value = wrap->_getitem_func(wrap->_base._self, key);
|
||||
if (value != nullptr) {
|
||||
Py_DECREF(value);
|
||||
return 1;
|
||||
} else if (_PyErr_OCCURRED() == PyExc_KeyError ||
|
||||
_PyErr_OCCURRED() == PyExc_TypeError) {
|
||||
PyErr_Restore(nullptr, nullptr, nullptr);
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *Dtool_MappingWrapper_getitem(PyObject *self, PyObject *key) {
|
||||
Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self;
|
||||
nassertr(wrap, nullptr);
|
||||
nassertr(wrap->_getitem_func, nullptr);
|
||||
return wrap->_getitem_func(wrap->_base._self, key);
|
||||
}
|
||||
|
||||
static int Dtool_MappingWrapper_setitem(PyObject *self, PyObject *key, PyObject *value) {
|
||||
Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self;
|
||||
nassertr(wrap, -1);
|
||||
if (wrap->_setitem_func != nullptr) {
|
||||
return wrap->_setitem_func(wrap->_base._self, key, value);
|
||||
} else {
|
||||
Dtool_Raise_TypeError("property does not support item assignment");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of property.get(key[,def=None]) which returns the value with
|
||||
* the given key in the mapping, or the given default value (which defaults to
|
||||
* None) if the key isn't found in the mapping.
|
||||
*/
|
||||
static PyObject *Dtool_MappingWrapper_get(PyObject *self, PyObject *args) {
|
||||
Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self;
|
||||
nassertr(wrap, nullptr);
|
||||
nassertr(wrap->_getitem_func, nullptr);
|
||||
Py_ssize_t size = PyTuple_GET_SIZE(args);
|
||||
if (size != 1 && size != 2) {
|
||||
return PyErr_Format(PyExc_TypeError, "%s.get() takes 1 or 2 arguments", wrap->_base._name);
|
||||
}
|
||||
PyObject *defvalue = Py_None;
|
||||
if (size >= 2) {
|
||||
defvalue = PyTuple_GET_ITEM(args, 1);
|
||||
}
|
||||
PyObject *key = PyTuple_GET_ITEM(args, 0);
|
||||
PyObject *value = wrap->_getitem_func(wrap->_base._self, key);
|
||||
if (value != nullptr) {
|
||||
return value;
|
||||
} else if (_PyErr_OCCURRED() == PyExc_KeyError) {
|
||||
PyErr_Restore(nullptr, nullptr, nullptr);
|
||||
Py_INCREF(defvalue);
|
||||
return defvalue;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of property.pop(key[,def=None]) which is the same as get()
|
||||
* except that it also removes the element from the mapping.
|
||||
*/
|
||||
static PyObject *Dtool_MappingWrapper_pop(PyObject *self, PyObject *args) {
|
||||
Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self;
|
||||
nassertr(wrap, nullptr);
|
||||
if (wrap->_getitem_func == nullptr || wrap->_setitem_func == nullptr) {
|
||||
return Dtool_Raise_TypeError("property does not support pop()");
|
||||
}
|
||||
|
||||
Py_ssize_t size = PyTuple_GET_SIZE(args);
|
||||
if (size != 1 && size != 2) {
|
||||
return PyErr_Format(PyExc_TypeError, "%s.pop() takes 1 or 2 arguments", wrap->_base._name);
|
||||
}
|
||||
PyObject *defvalue = Py_None;
|
||||
if (size >= 2) {
|
||||
defvalue = PyTuple_GET_ITEM(args, 1);
|
||||
}
|
||||
|
||||
PyObject *key = PyTuple_GET_ITEM(args, 0);
|
||||
PyObject *value = wrap->_getitem_func(wrap->_base._self, key);
|
||||
if (value != nullptr) {
|
||||
// OK, now set unset this value.
|
||||
if (wrap->_setitem_func(wrap->_base._self, key, nullptr) == 0) {
|
||||
return value;
|
||||
} else {
|
||||
Py_DECREF(value);
|
||||
return nullptr;
|
||||
}
|
||||
} else if (_PyErr_OCCURRED() == PyExc_KeyError) {
|
||||
PyErr_Restore(nullptr, nullptr, nullptr);
|
||||
Py_INCREF(defvalue);
|
||||
return defvalue;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of property.setdefault(key[,def=None]) which is the same as
|
||||
* get() except that it also writes the default value back to the mapping if
|
||||
* the key was not found is missing.
|
||||
*/
|
||||
static PyObject *Dtool_MappingWrapper_setdefault(PyObject *self, PyObject *args) {
|
||||
Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self;
|
||||
nassertr(wrap, nullptr);
|
||||
|
||||
if (wrap->_getitem_func == nullptr || wrap->_setitem_func == nullptr) {
|
||||
return Dtool_Raise_TypeError("property does not support setdefault()");
|
||||
}
|
||||
|
||||
Py_ssize_t size = PyTuple_GET_SIZE(args);
|
||||
if (size != 1 && size != 2) {
|
||||
return PyErr_Format(PyExc_TypeError, "%s.setdefault() takes 1 or 2 arguments", wrap->_base._name);
|
||||
}
|
||||
PyObject *defvalue = Py_None;
|
||||
if (size >= 2) {
|
||||
defvalue = PyTuple_GET_ITEM(args, 1);
|
||||
}
|
||||
PyObject *key = PyTuple_GET_ITEM(args, 0);
|
||||
PyObject *value = wrap->_getitem_func(wrap->_base._self, key);
|
||||
if (value != nullptr) {
|
||||
return value;
|
||||
} else if (_PyErr_OCCURRED() == PyExc_KeyError) {
|
||||
PyErr_Restore(nullptr, nullptr, nullptr);
|
||||
if (wrap->_setitem_func(wrap->_base._self, key, defvalue) == 0) {
|
||||
Py_INCREF(defvalue);
|
||||
return defvalue;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of property.update(...) which sets multiple values in one
|
||||
* go. It accepts either a single dictionary or keyword arguments, not both.
|
||||
*/
|
||||
static PyObject *Dtool_MappingWrapper_update(PyObject *self, PyObject *args, PyObject *kwargs) {
|
||||
Dtool_MappingWrapper *wrap = (Dtool_MappingWrapper *)self;
|
||||
nassertr(wrap, nullptr);
|
||||
|
||||
if (wrap->_getitem_func == nullptr || wrap->_setitem_func == nullptr) {
|
||||
return Dtool_Raise_TypeError("property does not support update()");
|
||||
}
|
||||
|
||||
// We accept either a dict argument or keyword arguments, but not both.
|
||||
PyObject *dict;
|
||||
switch (PyTuple_GET_SIZE(args)) {
|
||||
case 0:
|
||||
if (kwargs == nullptr) {
|
||||
// This is legal.
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
dict = kwargs;
|
||||
break;
|
||||
case 1:
|
||||
if (PyDict_Check(PyTuple_GET_ITEM(args, 0)) && (kwargs == nullptr || Py_SIZE(kwargs) == 0)) {
|
||||
dict = PyTuple_GET_ITEM(args, 0);
|
||||
break;
|
||||
}
|
||||
// Fall through
|
||||
default:
|
||||
return PyErr_Format(PyExc_TypeError, "%s.update() takes either a dict argument or keyword arguments", wrap->_base._name);
|
||||
}
|
||||
|
||||
PyObject *key, *value;
|
||||
Py_ssize_t pos = 0;
|
||||
while (PyDict_Next(dict, &pos, &key, &value)) {
|
||||
if (wrap->_setitem_func(wrap->_base._self, key, value) != 0) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of len(property) for mapping types.
|
||||
*/
|
||||
static Py_ssize_t Dtool_SeqMapWrapper_length(PyObject *self) {
|
||||
Dtool_SeqMapWrapper *wrap = (Dtool_SeqMapWrapper *)self;
|
||||
nassertr(wrap, -1);
|
||||
if (wrap->_len_func != nullptr) {
|
||||
return wrap->_len_func(wrap->_map._base._self);
|
||||
} else {
|
||||
Dtool_Raise_TypeError("property does not support len()");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of property.values() which returns a tuple containing the
|
||||
* dictionary values.
|
||||
*/
|
||||
static PyObject *Dtool_SeqMapWrapper_values(PyObject *self, PyObject *) {
|
||||
Dtool_SeqMapWrapper *wrap = (Dtool_SeqMapWrapper *)self;
|
||||
nassertr(wrap, nullptr);
|
||||
nassertr(wrap->_len_func, nullptr);
|
||||
nassertr(wrap->_seq_getitem_func, nullptr);
|
||||
|
||||
Py_ssize_t length = wrap->_len_func(wrap->_map._base._self);
|
||||
PyObject *values = PyTuple_New(length);
|
||||
if (UNLIKELY(values == nullptr)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (Py_ssize_t i = 0; i < length; ++i) {
|
||||
PyObject *value = wrap->_seq_getitem_func(wrap->_map._base._self, i);
|
||||
if (value != nullptr) {
|
||||
PyTuple_SET_ITEM(values, i, value);
|
||||
} else {
|
||||
Py_DECREF(values);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* This variant defines only a sequence interface.
|
||||
*/
|
||||
static PySequenceMethods Dtool_SequenceWrapper_SequenceMethods = {
|
||||
Dtool_SequenceWrapper_length,
|
||||
0, // sq_concat
|
||||
0, // sq_repeat
|
||||
Dtool_SequenceWrapper_getitem,
|
||||
0, // sq_slice
|
||||
Dtool_SequenceWrapper_setitem,
|
||||
0, // sq_ass_slice
|
||||
0, // sq_contains
|
||||
0, // sq_inplace_concat
|
||||
0, // sq_inplace_repeat
|
||||
};
|
||||
|
||||
static PyMethodDef Dtool_SequenceWrapper_Methods[] = {
|
||||
{"index", &Dtool_SequenceWrapper_index, METH_O, nullptr},
|
||||
{"count", &Dtool_SequenceWrapper_count, METH_O, nullptr},
|
||||
{"clear", &Dtool_SequenceWrapper_clear, METH_NOARGS, nullptr},
|
||||
{"pop", &Dtool_SequenceWrapper_pop, METH_VARARGS, nullptr},
|
||||
{"remove", &Dtool_SequenceWrapper_remove, METH_O, nullptr},
|
||||
{nullptr, nullptr, 0, nullptr}
|
||||
};
|
||||
|
||||
PyTypeObject Dtool_SequenceWrapper_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"sequence wrapper",
|
||||
sizeof(Dtool_SequenceWrapper),
|
||||
0, // tp_itemsize
|
||||
Dtool_WrapperBase_dealloc,
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
0, // tp_reserved
|
||||
#else
|
||||
0, // tp_compare
|
||||
#endif
|
||||
Dtool_SequenceWrapper_repr,
|
||||
0, // tp_as_number
|
||||
&Dtool_SequenceWrapper_SequenceMethods,
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
PyObject_GenericGetAttr,
|
||||
PyObject_GenericSetAttr,
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES,
|
||||
0, // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
0, // tp_iter
|
||||
0, // tp_iternext
|
||||
Dtool_SequenceWrapper_Methods,
|
||||
0, // tp_members
|
||||
0, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
0, // tp_init
|
||||
PyType_GenericAlloc,
|
||||
0, // tp_new
|
||||
PyObject_Del,
|
||||
0, // tp_is_gc
|
||||
0, // tp_bases
|
||||
0, // tp_mro
|
||||
0, // tp_cache
|
||||
0, // tp_subclasses
|
||||
0, // tp_weaklist
|
||||
0, // tp_del
|
||||
#if PY_VERSION_HEX >= 0x02060000
|
||||
0, // tp_version_tag
|
||||
#endif
|
||||
#if PY_VERSION_HEX >= 0x03040000
|
||||
0, // tp_finalize
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* This variant defines only a mapping interface.
|
||||
*/
|
||||
static PySequenceMethods Dtool_MappingWrapper_SequenceMethods = {
|
||||
0, // sq_length
|
||||
0, // sq_concat
|
||||
0, // sq_repeat
|
||||
0, // sq_item
|
||||
0, // sq_slice
|
||||
0, // sq_ass_item
|
||||
0, // sq_ass_slice
|
||||
Dtool_MappingWrapper_contains,
|
||||
0, // sq_inplace_concat
|
||||
0, // sq_inplace_repeat
|
||||
};
|
||||
|
||||
static PyMappingMethods Dtool_MappingWrapper_MappingMethods = {
|
||||
0, // mp_length
|
||||
Dtool_MappingWrapper_getitem,
|
||||
Dtool_MappingWrapper_setitem,
|
||||
};
|
||||
|
||||
static PyMethodDef Dtool_MappingWrapper_Methods[] = {
|
||||
{"get", &Dtool_MappingWrapper_get, METH_VARARGS, nullptr},
|
||||
{"pop", &Dtool_MappingWrapper_pop, METH_VARARGS, nullptr},
|
||||
{"setdefault", &Dtool_MappingWrapper_setdefault, METH_VARARGS, nullptr},
|
||||
{"update", (PyCFunction) &Dtool_MappingWrapper_update, METH_VARARGS | METH_KEYWORDS, nullptr},
|
||||
{nullptr, nullptr, 0, nullptr}
|
||||
};
|
||||
|
||||
PyTypeObject Dtool_MappingWrapper_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"mapping wrapper",
|
||||
sizeof(Dtool_MappingWrapper),
|
||||
0, // tp_itemsize
|
||||
Dtool_WrapperBase_dealloc,
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
0, // tp_reserved
|
||||
#else
|
||||
0, // tp_compare
|
||||
#endif
|
||||
Dtool_WrapperBase_repr,
|
||||
0, // tp_as_number
|
||||
&Dtool_MappingWrapper_SequenceMethods,
|
||||
&Dtool_MappingWrapper_MappingMethods,
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
PyObject_GenericGetAttr,
|
||||
PyObject_GenericSetAttr,
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES,
|
||||
0, // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
0, // tp_iter
|
||||
0, // tp_iternext
|
||||
Dtool_MappingWrapper_Methods,
|
||||
0, // tp_members
|
||||
0, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
0, // tp_init
|
||||
PyType_GenericAlloc,
|
||||
0, // tp_new
|
||||
PyObject_Del,
|
||||
0, // tp_is_gc
|
||||
0, // tp_bases
|
||||
0, // tp_mro
|
||||
0, // tp_cache
|
||||
0, // tp_subclasses
|
||||
0, // tp_weaklist
|
||||
0, // tp_del
|
||||
#if PY_VERSION_HEX >= 0x02060000
|
||||
0, // tp_version_tag
|
||||
#endif
|
||||
#if PY_VERSION_HEX >= 0x03040000
|
||||
0, // tp_finalize
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* This variant defines both a sequence and mapping interface.
|
||||
*/
|
||||
static PyMappingMethods Dtool_SeqMapWrapper_MappingMethods = {
|
||||
Dtool_SeqMapWrapper_length,
|
||||
Dtool_MappingWrapper_getitem,
|
||||
Dtool_MappingWrapper_setitem,
|
||||
};
|
||||
|
||||
static PyMethodDef Dtool_SeqMapWrapper_Methods[] = {
|
||||
{"get", &Dtool_MappingWrapper_get, METH_VARARGS, nullptr},
|
||||
{"pop", &Dtool_MappingWrapper_pop, METH_VARARGS, nullptr},
|
||||
{"setdefault", &Dtool_MappingWrapper_setdefault, METH_VARARGS, nullptr},
|
||||
{"update", (PyCFunction) &Dtool_MappingWrapper_update, METH_VARARGS | METH_KEYWORDS, nullptr},
|
||||
{"values", &Dtool_SeqMapWrapper_values, METH_NOARGS, nullptr},
|
||||
{nullptr, nullptr, 0, nullptr}
|
||||
};
|
||||
|
||||
PyTypeObject Dtool_SeqMapWrapper_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"sequence/mapping wrapper",
|
||||
sizeof(Dtool_SeqMapWrapper),
|
||||
0, // tp_itemsize
|
||||
Dtool_WrapperBase_dealloc,
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
0, // tp_reserved
|
||||
#else
|
||||
0, // tp_compare
|
||||
#endif
|
||||
Dtool_WrapperBase_repr,
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
&Dtool_MappingWrapper_MappingMethods,
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
PyObject_GenericGetAttr,
|
||||
PyObject_GenericSetAttr,
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES,
|
||||
0, // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
0, // tp_iter
|
||||
0, // tp_iternext
|
||||
Dtool_SeqMapWrapper_Methods,
|
||||
0, // tp_members
|
||||
0, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
0, // tp_init
|
||||
PyType_GenericAlloc,
|
||||
0, // tp_new
|
||||
PyObject_Del,
|
||||
0, // tp_is_gc
|
||||
0, // tp_bases
|
||||
0, // tp_mro
|
||||
0, // tp_cache
|
||||
0, // tp_subclasses
|
||||
0, // tp_weaklist
|
||||
0, // tp_del
|
||||
#if PY_VERSION_HEX >= 0x02060000
|
||||
0, // tp_version_tag
|
||||
#endif
|
||||
#if PY_VERSION_HEX >= 0x03040000
|
||||
0, // tp_finalize
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* This variant defines only a generator interface.
|
||||
*/
|
||||
static PyObject *Dtool_GeneratorWrapper_iternext(PyObject *self) {
|
||||
Dtool_GeneratorWrapper *wrap = (Dtool_GeneratorWrapper *)self;
|
||||
nassertr(wrap, nullptr);
|
||||
nassertr(wrap->_iternext_func, nullptr);
|
||||
return wrap->_iternext_func(wrap->_base._self);
|
||||
}
|
||||
|
||||
PyTypeObject Dtool_GeneratorWrapper_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"generator wrapper",
|
||||
sizeof(Dtool_GeneratorWrapper),
|
||||
0, // tp_itemsize
|
||||
Dtool_WrapperBase_dealloc,
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
0, // tp_reserved
|
||||
#else
|
||||
0, // tp_compare
|
||||
#endif
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
PyObject_GenericGetAttr,
|
||||
PyObject_GenericSetAttr,
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES,
|
||||
0, // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
PyObject_SelfIter,
|
||||
Dtool_GeneratorWrapper_iternext,
|
||||
0, // tp_methods
|
||||
0, // tp_members
|
||||
0, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
0, // tp_init
|
||||
PyType_GenericAlloc,
|
||||
0, // tp_new
|
||||
PyObject_Del,
|
||||
0, // tp_is_gc
|
||||
0, // tp_bases
|
||||
0, // tp_mro
|
||||
0, // tp_cache
|
||||
0, // tp_subclasses
|
||||
0, // tp_weaklist
|
||||
0, // tp_del
|
||||
#if PY_VERSION_HEX >= 0x02060000
|
||||
0, // tp_version_tag
|
||||
#endif
|
||||
#if PY_VERSION_HEX >= 0x03040000
|
||||
0, // tp_finalize
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a variant of the Python getset mechanism that permits static
|
||||
* properties.
|
||||
*/
|
||||
PyObject *
|
||||
Dtool_NewStaticProperty(PyTypeObject *type, const PyGetSetDef *getset) {
|
||||
PyGetSetDescrObject *descr;
|
||||
descr = (PyGetSetDescrObject *)PyType_GenericAlloc(&Dtool_StaticProperty_Type, 0);
|
||||
if (descr != nullptr) {
|
||||
Py_XINCREF(type);
|
||||
descr->d_getset = (PyGetSetDef *)getset;
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
descr->d_common.d_type = type;
|
||||
descr->d_common.d_name = PyUnicode_InternFromString(getset->name);
|
||||
#if PY_VERSION_HEX >= 0x03030000
|
||||
descr->d_common.d_qualname = nullptr;
|
||||
#endif
|
||||
#else
|
||||
descr->d_type = type;
|
||||
descr->d_name = PyString_InternFromString(getset->name);
|
||||
#endif
|
||||
}
|
||||
return (PyObject *)descr;
|
||||
}
|
||||
|
||||
static void
|
||||
Dtool_StaticProperty_dealloc(PyDescrObject *descr) {
|
||||
_PyObject_GC_UNTRACK(descr);
|
||||
Py_XDECREF(descr->d_type);
|
||||
Py_XDECREF(descr->d_name);
|
||||
//#if PY_MAJOR_VERSION >= 3
|
||||
// Py_XDECREF(descr->d_qualname);
|
||||
//#endif
|
||||
PyObject_GC_Del(descr);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
Dtool_StaticProperty_repr(PyDescrObject *descr, const char *format) {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return PyUnicode_FromFormat("<attribute '%s' of '%s'>",
|
||||
PyUnicode_AsUTF8(descr->d_name),
|
||||
descr->d_type->tp_name);
|
||||
#else
|
||||
return PyString_FromFormat("<attribute '%s' of '%s'>",
|
||||
PyString_AS_STRING(descr->d_name),
|
||||
descr->d_type->tp_name);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
Dtool_StaticProperty_traverse(PyObject *self, visitproc visit, void *arg) {
|
||||
PyDescrObject *descr = (PyDescrObject *)self;
|
||||
Py_VISIT(descr->d_type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
Dtool_StaticProperty_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type) {
|
||||
if (descr->d_getset->get != nullptr) {
|
||||
return descr->d_getset->get(obj, descr->d_getset->closure);
|
||||
} else {
|
||||
return PyErr_Format(PyExc_AttributeError,
|
||||
"attribute '%s' of type '%.100s' is not readable",
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyUnicode_AsUTF8(((PyDescrObject *)descr)->d_name),
|
||||
#else
|
||||
PyString_AS_STRING(((PyDescrObject *)descr)->d_name),
|
||||
#endif
|
||||
((PyDescrObject *)descr)->d_type->tp_name);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
Dtool_StaticProperty_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value) {
|
||||
if (descr->d_getset->set != nullptr) {
|
||||
return descr->d_getset->set(obj, value, descr->d_getset->closure);
|
||||
} else {
|
||||
PyErr_Format(PyExc_AttributeError,
|
||||
"attribute '%s' of type '%.100s' is not writable",
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyUnicode_AsUTF8(((PyDescrObject *)descr)->d_name),
|
||||
#else
|
||||
PyString_AS_STRING(((PyDescrObject *)descr)->d_name),
|
||||
#endif
|
||||
((PyDescrObject *)descr)->d_type->tp_name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
PyTypeObject Dtool_StaticProperty_Type = {
|
||||
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
||||
"getset_descriptor",
|
||||
sizeof(PyGetSetDescrObject),
|
||||
0, // tp_itemsize
|
||||
(destructor)Dtool_StaticProperty_dealloc,
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_reserved
|
||||
(reprfunc)Dtool_StaticProperty_repr,
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
PyObject_GenericGetAttr,
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT,
|
||||
0, // tp_doc
|
||||
Dtool_StaticProperty_traverse,
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
0, // tp_iter
|
||||
0, // tp_iternext
|
||||
0, // tp_methods
|
||||
0, // tp_members
|
||||
0, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
(descrgetfunc)Dtool_StaticProperty_get,
|
||||
(descrsetfunc)Dtool_StaticProperty_set,
|
||||
0, // tp_dictoffset
|
||||
0, // tp_init
|
||||
0, // tp_alloc
|
||||
0, // tp_new
|
||||
0, // tp_del
|
||||
0, // tp_is_gc
|
||||
0, // tp_bases
|
||||
0, // tp_mro
|
||||
0, // tp_cache
|
||||
0, // tp_subclasses
|
||||
0, // tp_weaklist
|
||||
0, // tp_del
|
||||
#if PY_VERSION_HEX >= 0x02060000
|
||||
0, // tp_version_tag
|
||||
#endif
|
||||
#if PY_VERSION_HEX >= 0x03040000
|
||||
0, // tp_finalize
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // HAVE_PYTHON
|
||||
|
|
|
|||
|
|
@ -468,49 +468,6 @@ copy_from_copy_constructor(PyObject *self, PyObject *noargs);
|
|||
EXPCL_INTERROGATEDB PyObject *
|
||||
map_deepcopy_to_copy(PyObject *self, PyObject *args);
|
||||
|
||||
/**
|
||||
* These classes are returned from properties that require a subscript
|
||||
* interface, ie. something.children[i] = 3.
|
||||
*/
|
||||
struct Dtool_WrapperBase {
|
||||
PyObject_HEAD;
|
||||
PyObject *_self;
|
||||
const char *_name;
|
||||
};
|
||||
|
||||
struct Dtool_SequenceWrapper {
|
||||
Dtool_WrapperBase _base;
|
||||
lenfunc _len_func;
|
||||
ssizeargfunc _getitem_func;
|
||||
ssizeobjargproc _setitem_func;
|
||||
};
|
||||
|
||||
struct Dtool_MappingWrapper {
|
||||
Dtool_WrapperBase _base;
|
||||
binaryfunc _getitem_func;
|
||||
objobjargproc _setitem_func;
|
||||
};
|
||||
|
||||
struct Dtool_SeqMapWrapper {
|
||||
Dtool_MappingWrapper _map;
|
||||
lenfunc _len_func;
|
||||
ssizeargfunc _seq_getitem_func;
|
||||
ssizeobjargproc _seq_setitem_func;
|
||||
};
|
||||
|
||||
struct Dtool_GeneratorWrapper {
|
||||
Dtool_WrapperBase _base;
|
||||
iternextfunc _iternext_func;
|
||||
};
|
||||
|
||||
EXPCL_INTERROGATEDB extern PyTypeObject Dtool_SequenceWrapper_Type;
|
||||
EXPCL_INTERROGATEDB extern PyTypeObject Dtool_MappingWrapper_Type;
|
||||
EXPCL_INTERROGATEDB extern PyTypeObject Dtool_SeqMapWrapper_Type;
|
||||
EXPCL_INTERROGATEDB extern PyTypeObject Dtool_GeneratorWrapper_Type;
|
||||
EXPCL_INTERROGATEDB extern PyTypeObject Dtool_StaticProperty_Type;
|
||||
|
||||
EXPCL_INTERROGATEDB PyObject *Dtool_NewStaticProperty(PyTypeObject *obj, const PyGetSetDef *getset);
|
||||
|
||||
/**
|
||||
* These functions check whether the arguments passed to a function conform to
|
||||
* certain expectations.
|
||||
|
|
@ -566,6 +523,8 @@ EXPCL_INTERROGATEDB extern void Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(PyObjec
|
|||
|
||||
#include "py_panda.I"
|
||||
|
||||
#include "py_wrappers.h"
|
||||
|
||||
#endif // HAVE_PYTHON && !CPPPARSER
|
||||
|
||||
#endif // PY_PANDA_H_
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* 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 py_wrappers.h
|
||||
* @author rdb
|
||||
* @date 2017-11-26
|
||||
*/
|
||||
|
||||
#ifndef PY_WRAPPERS_H
|
||||
#define PY_WRAPPERS_H
|
||||
|
||||
#include "py_panda.h"
|
||||
|
||||
/**
|
||||
* These classes are returned from properties that require a subscript
|
||||
* interface, ie. something.children[i] = 3.
|
||||
*/
|
||||
struct Dtool_WrapperBase {
|
||||
PyObject_HEAD;
|
||||
PyObject *_self;
|
||||
const char *_name;
|
||||
};
|
||||
|
||||
struct Dtool_SequenceWrapper {
|
||||
Dtool_WrapperBase _base;
|
||||
lenfunc _len_func;
|
||||
ssizeargfunc _getitem_func;
|
||||
};
|
||||
|
||||
struct Dtool_MutableSequenceWrapper {
|
||||
Dtool_WrapperBase _base;
|
||||
lenfunc _len_func;
|
||||
ssizeargfunc _getitem_func;
|
||||
ssizeobjargproc _setitem_func;
|
||||
PyObject *(*_insert_func)(PyObject *, size_t, PyObject *);
|
||||
};
|
||||
|
||||
struct Dtool_MappingWrapper {
|
||||
union {
|
||||
Dtool_WrapperBase _base;
|
||||
Dtool_SequenceWrapper _keys;
|
||||
};
|
||||
binaryfunc _getitem_func;
|
||||
objobjargproc _setitem_func;
|
||||
};
|
||||
|
||||
struct Dtool_GeneratorWrapper {
|
||||
Dtool_WrapperBase _base;
|
||||
iternextfunc _iternext_func;
|
||||
};
|
||||
|
||||
EXPCL_INTERROGATEDB extern PyTypeObject Dtool_SequenceWrapper_Type;
|
||||
EXPCL_INTERROGATEDB extern PyTypeObject Dtool_MutableSequenceWrapper_Type;
|
||||
EXPCL_INTERROGATEDB extern PyTypeObject Dtool_MappingWrapper_Type;
|
||||
EXPCL_INTERROGATEDB extern PyTypeObject Dtool_MutableMappingWrapper_Type;
|
||||
EXPCL_INTERROGATEDB extern PyTypeObject Dtool_MappingWrapper_Items_Type;
|
||||
EXPCL_INTERROGATEDB extern PyTypeObject Dtool_MappingWrapper_Keys_Type;
|
||||
EXPCL_INTERROGATEDB extern PyTypeObject Dtool_MappingWrapper_Values_Type;
|
||||
EXPCL_INTERROGATEDB extern PyTypeObject Dtool_GeneratorWrapper_Type;
|
||||
EXPCL_INTERROGATEDB extern PyTypeObject Dtool_StaticProperty_Type;
|
||||
|
||||
EXPCL_INTERROGATEDB Dtool_SequenceWrapper *Dtool_NewSequenceWrapper(PyObject *self, const char *name);
|
||||
EXPCL_INTERROGATEDB Dtool_MutableSequenceWrapper *Dtool_NewMutableSequenceWrapper(PyObject *self, const char *name);
|
||||
EXPCL_INTERROGATEDB Dtool_MappingWrapper *Dtool_NewMappingWrapper(PyObject *self, const char *name);
|
||||
EXPCL_INTERROGATEDB Dtool_MappingWrapper *Dtool_NewMutableMappingWrapper(PyObject *self, const char *name);
|
||||
EXPCL_INTERROGATEDB PyObject *Dtool_NewGenerator(PyObject *self, const char *name, iternextfunc func);
|
||||
EXPCL_INTERROGATEDB PyObject *Dtool_NewStaticProperty(PyTypeObject *obj, const PyGetSetDef *getset);
|
||||
|
||||
#endif
|
||||
|
|
@ -66,6 +66,7 @@ extern "C" {
|
|||
EXPCL_PYSTUB int PyInt_FromLong(...);
|
||||
EXPCL_PYSTUB int PyInt_FromSize_t(...);
|
||||
EXPCL_PYSTUB int PyInt_Type(...);
|
||||
EXPCL_PYSTUB int PyIter_Next(...);
|
||||
EXPCL_PYSTUB int PyList_Append(...);
|
||||
EXPCL_PYSTUB int PyList_AsTuple(...);
|
||||
EXPCL_PYSTUB int PyList_GetItem(...);
|
||||
|
|
@ -91,6 +92,7 @@ extern "C" {
|
|||
EXPCL_PYSTUB int PyModule_AddStringConstant(...);
|
||||
EXPCL_PYSTUB int PyModule_Create2(...);
|
||||
EXPCL_PYSTUB int PyModule_Create2TraceRefs(...);
|
||||
EXPCL_PYSTUB int PyModule_GetDict(...);
|
||||
EXPCL_PYSTUB int PyNumber_AsSsize_t(...);
|
||||
EXPCL_PYSTUB int PyNumber_Check(...);
|
||||
EXPCL_PYSTUB int PyNumber_Float(...);
|
||||
|
|
@ -111,15 +113,18 @@ extern "C" {
|
|||
EXPCL_PYSTUB int PyObject_GenericSetAttr(...);
|
||||
EXPCL_PYSTUB int PyObject_GetAttrString(...);
|
||||
EXPCL_PYSTUB int PyObject_GetBuffer(...);
|
||||
EXPCL_PYSTUB int PyObject_GetIter(...);
|
||||
EXPCL_PYSTUB int PyObject_HasAttrString(...);
|
||||
EXPCL_PYSTUB int PyObject_IsInstance(...);
|
||||
EXPCL_PYSTUB int PyObject_IsTrue(...);
|
||||
EXPCL_PYSTUB int PyObject_Malloc(...);
|
||||
EXPCL_PYSTUB int PyObject_Repr(...);
|
||||
EXPCL_PYSTUB int PyObject_RichCompareBool(...);
|
||||
EXPCL_PYSTUB int PyObject_SelfIter(...);
|
||||
EXPCL_PYSTUB int PyObject_SetAttrString(...);
|
||||
EXPCL_PYSTUB int PyObject_Str(...);
|
||||
EXPCL_PYSTUB int PyObject_Type(...);
|
||||
EXPCL_PYSTUB int PySeqIter_New(...);
|
||||
EXPCL_PYSTUB int PySequence_Check(...);
|
||||
EXPCL_PYSTUB int PySequence_Fast(...);
|
||||
EXPCL_PYSTUB int PySequence_GetItem(...);
|
||||
|
|
@ -290,6 +295,7 @@ int PyInt_AsSsize_t(...) { return 0; }
|
|||
int PyInt_FromLong(...) { return 0; }
|
||||
int PyInt_FromSize_t(...) { return 0; }
|
||||
int PyInt_Type(...) { return 0; }
|
||||
int PyIter_Next(...) { return 0; }
|
||||
int PyList_Append(...) { return 0; }
|
||||
int PyList_AsTuple(...) { return 0; }
|
||||
int PyList_GetItem(...) { return 0; }
|
||||
|
|
@ -315,6 +321,7 @@ int PyModule_AddObject(...) { return 0; };
|
|||
int PyModule_AddStringConstant(...) { return 0; };
|
||||
int PyModule_Create2(...) { return 0; };
|
||||
int PyModule_Create2TraceRefs(...) { return 0; };
|
||||
int PyModule_GetDict(...) { return 0; };
|
||||
int PyNumber_AsSsize_t(...) { return 0; }
|
||||
int PyNumber_Check(...) { return 0; }
|
||||
int PyNumber_Float(...) { return 0; }
|
||||
|
|
@ -335,15 +342,18 @@ int PyObject_GenericGetAttr(...) { return 0; };
|
|||
int PyObject_GenericSetAttr(...) { return 0; };
|
||||
int PyObject_GetAttrString(...) { return 0; }
|
||||
int PyObject_GetBuffer(...) { return 0; }
|
||||
int PyObject_GetIter(...) { return 0; }
|
||||
int PyObject_HasAttrString(...) { return 0; }
|
||||
int PyObject_IsInstance(...) { return 0; }
|
||||
int PyObject_IsTrue(...) { return 0; }
|
||||
int PyObject_Malloc(...) { return 0; }
|
||||
int PyObject_Repr(...) { return 0; }
|
||||
int PyObject_RichCompareBool(...) { return 0; }
|
||||
int PyObject_SelfIter(...) { return 0; }
|
||||
int PyObject_SetAttrString(...) { return 0; }
|
||||
int PyObject_Str(...) { return 0; }
|
||||
int PyObject_Type(...) { return 0; }
|
||||
int PySeqIter_New(...) { return 0; }
|
||||
int PySequence_Check(...) { return 0; }
|
||||
int PySequence_Fast(...) { return 0; }
|
||||
int PySequence_GetItem(...) { return 0; }
|
||||
|
|
|
|||
|
|
@ -768,9 +768,11 @@ if (COMPILER == "MSVC"):
|
|||
DefSymbol("WX", "_UNICODE", "")
|
||||
DefSymbol("WX", "UNICODE", "")
|
||||
if (PkgSkip("VORBIS")==0):
|
||||
LibName("VORBIS", GetThirdpartyDir() + "vorbis/lib/libogg_static.lib")
|
||||
LibName("VORBIS", GetThirdpartyDir() + "vorbis/lib/libvorbis_static.lib")
|
||||
LibName("VORBIS", GetThirdpartyDir() + "vorbis/lib/libvorbisfile_static.lib")
|
||||
for lib in ('ogg', 'vorbis', 'vorbisfile'):
|
||||
path = GetThirdpartyDir() + "vorbis/lib/lib{0}_static.lib".format(lib)
|
||||
if not os.path.isfile(path):
|
||||
path = GetThirdpartyDir() + "vorbis/lib/{0}.lib".format(lib)
|
||||
LibName("VORBIS", path)
|
||||
if (PkgSkip("OPUS")==0):
|
||||
LibName("OPUS", GetThirdpartyDir() + "opus/lib/libogg_static.lib")
|
||||
LibName("OPUS", GetThirdpartyDir() + "opus/lib/libopus_static.lib")
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ PUBLISHED:
|
|||
void sort_descendants();
|
||||
|
||||
MAKE_SEQ_PROPERTY(children, get_num_children, get_child);
|
||||
MAKE_MAP_PROPERTY(children, get_child_named, get_child_named);
|
||||
|
||||
public:
|
||||
virtual TypeHandle get_value_type() const;
|
||||
|
|
|
|||
|
|
@ -76,7 +76,6 @@ PUBLISHED:
|
|||
void sort_descendants();
|
||||
|
||||
MAKE_SEQ_PROPERTY(children, get_num_children, get_child);
|
||||
MAKE_MAP_PROPERTY(children, get_child_named, get_child_named);
|
||||
|
||||
bool apply_freeze(const TransformState *transform);
|
||||
virtual bool apply_freeze_matrix(const LVecBase3 &pos, const LVecBase3 &hpr, const LVecBase3 &scale);
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ clear_solids() {
|
|||
/**
|
||||
*
|
||||
*/
|
||||
INLINE int CollisionNode::
|
||||
INLINE size_t CollisionNode::
|
||||
get_num_solids() const {
|
||||
return _solids.size();
|
||||
}
|
||||
|
|
@ -74,8 +74,8 @@ get_num_solids() const {
|
|||
*
|
||||
*/
|
||||
INLINE CPT(CollisionSolid) CollisionNode::
|
||||
get_solid(int n) const {
|
||||
nassertr(n >= 0 && n < get_num_solids(), NULL);
|
||||
get_solid(size_t n) const {
|
||||
nassertr(n < get_num_solids(), nullptr);
|
||||
return _solids[n].get_read_pointer();
|
||||
}
|
||||
|
||||
|
|
@ -83,8 +83,8 @@ get_solid(int n) const {
|
|||
*
|
||||
*/
|
||||
INLINE PT(CollisionSolid) CollisionNode::
|
||||
modify_solid(int n) {
|
||||
nassertr(n >= 0 && n < get_num_solids(), NULL);
|
||||
modify_solid(size_t n) {
|
||||
nassertr(n < get_num_solids(), nullptr);
|
||||
mark_internal_bounds_stale();
|
||||
return _solids[n].get_write_pointer();
|
||||
}
|
||||
|
|
@ -93,19 +93,31 @@ modify_solid(int n) {
|
|||
* Replaces the solid with the indicated index.
|
||||
*/
|
||||
INLINE void CollisionNode::
|
||||
set_solid(int n, CollisionSolid *solid) {
|
||||
nassertv(n >= 0 && n < get_num_solids());
|
||||
set_solid(size_t n, CollisionSolid *solid) {
|
||||
nassertv(n < get_num_solids());
|
||||
_solids[n] = solid;
|
||||
mark_internal_bounds_stale();
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the indicated solid to the node at the indicated position.
|
||||
*/
|
||||
INLINE void CollisionNode::
|
||||
insert_solid(size_t n, const CollisionSolid *solid) {
|
||||
if (n > _solids.size()) {
|
||||
n = _solids.size();
|
||||
}
|
||||
_solids.insert(_solids.begin() + n, (CollisionSolid *)solid);
|
||||
mark_internal_bounds_stale();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the solid with the indicated index. This will shift all subsequent
|
||||
* indices down by one.
|
||||
*/
|
||||
INLINE void CollisionNode::
|
||||
remove_solid(int n) {
|
||||
nassertv(n >= 0 && n < get_num_solids());
|
||||
remove_solid(size_t n) {
|
||||
nassertv(n < get_num_solids());
|
||||
_solids.erase(_solids.begin() + n);
|
||||
mark_internal_bounds_stale();
|
||||
}
|
||||
|
|
@ -114,7 +126,7 @@ remove_solid(int n) {
|
|||
* Adds the indicated solid to the node. Returns the index of the new solid
|
||||
* within the node's list of solids.
|
||||
*/
|
||||
INLINE int CollisionNode::
|
||||
INLINE size_t CollisionNode::
|
||||
add_solid(const CollisionSolid *solid) {
|
||||
_solids.push_back((CollisionSolid *)solid);
|
||||
mark_internal_bounds_stale();
|
||||
|
|
|
|||
|
|
@ -61,14 +61,15 @@ PUBLISHED:
|
|||
set_into_collide_mask);
|
||||
|
||||
INLINE void clear_solids();
|
||||
INLINE int get_num_solids() const;
|
||||
INLINE CPT(CollisionSolid) get_solid(int n) const;
|
||||
INLINE size_t get_num_solids() const;
|
||||
INLINE CPT(CollisionSolid) get_solid(size_t n) const;
|
||||
MAKE_SEQ(get_solids, get_num_solids, get_solid);
|
||||
INLINE PT(CollisionSolid) modify_solid(int n);
|
||||
INLINE void set_solid(int n, CollisionSolid *solid);
|
||||
INLINE void remove_solid(int n);
|
||||
INLINE int add_solid(const CollisionSolid *solid);
|
||||
MAKE_SEQ_PROPERTY(solids, get_num_solids, get_solid, set_solid, remove_solid);
|
||||
INLINE PT(CollisionSolid) modify_solid(size_t n);
|
||||
INLINE void set_solid(size_t n, CollisionSolid *solid);
|
||||
INLINE void insert_solid(size_t n, const CollisionSolid *solid);
|
||||
INLINE void remove_solid(size_t n);
|
||||
INLINE size_t add_solid(const CollisionSolid *solid);
|
||||
MAKE_SEQ_PROPERTY(solids, get_num_solids, get_solid, set_solid, remove_solid, insert_solid);
|
||||
|
||||
INLINE int get_collider_sort() const;
|
||||
INLINE void set_collider_sort(int sort);
|
||||
|
|
|
|||
|
|
@ -584,8 +584,7 @@ get_quality(const FrameBufferProperties &reqs) const {
|
|||
// However, deduct for color bits above 24, if we are requesting only 1.
|
||||
// This is to prevent choosing a 64-bit color mode in NVIDIA cards that
|
||||
// is linear and therefore causes the gamma to be off in non-sRGB pipelines.
|
||||
if ((reqs._property[FBP_color_bits] == 1 || reqs._property[FBP_color_bits] == 3) &&
|
||||
_property[FBP_color_bits] > 24) {
|
||||
if (reqs._property[FBP_color_bits] <= 3 && _property[FBP_color_bits] > 24) {
|
||||
quality -= 100;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ operator = (const EggCompositePrimitive ©) {
|
|||
* Returns the number of individual component triangles within the composite.
|
||||
* Each one of these might have a different set of attributes.
|
||||
*/
|
||||
INLINE int EggCompositePrimitive::
|
||||
INLINE size_t EggCompositePrimitive::
|
||||
get_num_components() const {
|
||||
return _components.size();
|
||||
}
|
||||
|
|
@ -47,8 +47,8 @@ get_num_components() const {
|
|||
* Returns the attributes for the nth component triangle.
|
||||
*/
|
||||
INLINE const EggAttributes *EggCompositePrimitive::
|
||||
get_component(int i) const {
|
||||
nassertr(i >= 0 && i < (int)_components.size(), NULL);
|
||||
get_component(size_t i) const {
|
||||
nassertr(i < _components.size(), nullptr);
|
||||
return _components[i];
|
||||
}
|
||||
|
||||
|
|
@ -56,8 +56,8 @@ get_component(int i) const {
|
|||
* Returns the attributes for the nth component triangle.
|
||||
*/
|
||||
INLINE EggAttributes *EggCompositePrimitive::
|
||||
get_component(int i) {
|
||||
nassertr(i >= 0 && i < (int)_components.size(), NULL);
|
||||
get_component(size_t i) {
|
||||
nassertr(i < _components.size(), nullptr);
|
||||
return _components[i];
|
||||
}
|
||||
|
||||
|
|
@ -65,8 +65,8 @@ get_component(int i) {
|
|||
* Changes the attributes for the nth component triangle.
|
||||
*/
|
||||
INLINE void EggCompositePrimitive::
|
||||
set_component(int i, const EggAttributes *attrib) {
|
||||
nassertv(i >= 0 && i < (int)_components.size());
|
||||
set_component(size_t i, const EggAttributes *attrib) {
|
||||
nassertv(i < _components.size());
|
||||
_components[i] = new EggAttributes(*attrib);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,11 +32,11 @@ PUBLISHED:
|
|||
|
||||
virtual Shading get_shading() const;
|
||||
|
||||
INLINE int get_num_components() const;
|
||||
INLINE const EggAttributes *get_component(int i) const;
|
||||
INLINE EggAttributes *get_component(int i);
|
||||
INLINE size_t get_num_components() const;
|
||||
INLINE const EggAttributes *get_component(size_t i) const;
|
||||
INLINE EggAttributes *get_component(size_t i);
|
||||
MAKE_SEQ(get_components, get_num_components, get_component);
|
||||
INLINE void set_component(int i, const EggAttributes *attrib);
|
||||
INLINE void set_component(size_t i, const EggAttributes *attrib);
|
||||
|
||||
MAKE_SEQ_PROPERTY(components, get_num_components, get_component, set_component);
|
||||
|
||||
|
|
|
|||
|
|
@ -372,6 +372,17 @@ set_vertex(size_t index, EggVertex *vertex) {
|
|||
replace(begin() + index, vertex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a vertex at the given position.
|
||||
*/
|
||||
INLINE void EggPrimitive::
|
||||
insert_vertex(size_t index, EggVertex *vertex) {
|
||||
if (index > _vertices.size()) {
|
||||
index = _vertices.size();
|
||||
}
|
||||
_vertices.insert(_vertices.begin() + index, vertex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a particular index based on its index number.
|
||||
*/
|
||||
|
|
@ -381,7 +392,6 @@ get_vertex(size_t index) const {
|
|||
return *(begin() + index);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the vertex pool associated with the vertices of the primitive, or
|
||||
* NULL if the primitive has no vertices.
|
||||
|
|
|
|||
|
|
@ -181,13 +181,14 @@ PUBLISHED:
|
|||
|
||||
// These are shorthands if you don't want to use the iterators.
|
||||
INLINE size_t get_num_vertices() const;
|
||||
INLINE void set_vertex(size_t index, EggVertex *vertex);
|
||||
INLINE EggVertex *get_vertex(size_t index) const;
|
||||
INLINE void set_vertex(size_t index, EggVertex *vertex);
|
||||
INLINE void insert_vertex(size_t index, EggVertex *vertex);
|
||||
MAKE_SEQ(get_vertices, get_num_vertices, get_vertex);
|
||||
|
||||
INLINE EggVertexPool *get_pool() const;
|
||||
|
||||
MAKE_SEQ_PROPERTY(vertices, get_num_vertices, get_vertex, set_vertex, remove_vertex);
|
||||
MAKE_SEQ_PROPERTY(vertices, get_num_vertices, get_vertex, set_vertex, remove_vertex, insert_vertex);
|
||||
MAKE_PROPERTY(pool, get_pool);
|
||||
|
||||
virtual void write(ostream &out, int indent_level) const=0;
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ is_empty() const {
|
|||
* Returns the number of GeomPrimitive objects stored within the Geom, each of
|
||||
* which represents a number of primitives of a particular type.
|
||||
*/
|
||||
INLINE int Geom::
|
||||
INLINE size_t Geom::
|
||||
get_num_primitives() const {
|
||||
CDReader cdata(_cycler);
|
||||
return cdata->_primitives.size();
|
||||
|
|
@ -80,9 +80,9 @@ get_num_primitives() const {
|
|||
* or set_primitive() if you want to modify it.
|
||||
*/
|
||||
INLINE CPT(GeomPrimitive) Geom::
|
||||
get_primitive(int i) const {
|
||||
get_primitive(size_t i) const {
|
||||
CDReader cdata(_cycler);
|
||||
nassertr(i >= 0 && i < (int)cdata->_primitives.size(), NULL);
|
||||
nassertr(i < cdata->_primitives.size(), nullptr);
|
||||
return cdata->_primitives[i].get_read_pointer();
|
||||
}
|
||||
|
||||
|
|
@ -95,15 +95,28 @@ get_primitive(int i) const {
|
|||
* away other changes you might have recently made in an upstream thread.
|
||||
*/
|
||||
INLINE PT(GeomPrimitive) Geom::
|
||||
modify_primitive(int i) {
|
||||
modify_primitive(size_t i) {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
CDWriter cdata(_cycler, true, current_thread);
|
||||
nassertr(i >= 0 && i < (int)cdata->_primitives.size(), NULL);
|
||||
nassertr(i < cdata->_primitives.size(), NULL);
|
||||
cdata->_modified = Geom::get_next_modified();
|
||||
clear_cache_stage(current_thread);
|
||||
return cdata->_primitives[i].get_write_pointer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a new GeomPrimitive structure to the Geom object. This specifies a
|
||||
* particular subset of vertices that are used to define geometric primitives
|
||||
* of the indicated type.
|
||||
*
|
||||
* Don't call this in a downstream thread unless you don't mind it blowing
|
||||
* away other changes you might have recently made in an upstream thread.
|
||||
*/
|
||||
INLINE void Geom::
|
||||
add_primitive(const GeomPrimitive *primitive) {
|
||||
insert_primitive((size_t)-1, primitive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decomposes all of the primitives within this Geom, returning the result.
|
||||
* See GeomPrimitive::decompose().
|
||||
|
|
|
|||
|
|
@ -294,10 +294,10 @@ make_nonindexed(bool composite_only) {
|
|||
* away other changes you might have recently made in an upstream thread.
|
||||
*/
|
||||
void Geom::
|
||||
set_primitive(int i, const GeomPrimitive *primitive) {
|
||||
set_primitive(size_t i, const GeomPrimitive *primitive) {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
CDWriter cdata(_cycler, true, current_thread);
|
||||
nassertv(i >= 0 && i < (int)cdata->_primitives.size());
|
||||
nassertv(i < cdata->_primitives.size());
|
||||
nassertv(primitive->check_valid(cdata->_data.get_read_pointer(current_thread)));
|
||||
|
||||
// All primitives within a particular Geom must have the same fundamental
|
||||
|
|
@ -327,7 +327,7 @@ set_primitive(int i, const GeomPrimitive *primitive) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Adds a new GeomPrimitive structure to the Geom object. This specifies a
|
||||
* Inserts a new GeomPrimitive structure to the Geom object. This specifies a
|
||||
* particular subset of vertices that are used to define geometric primitives
|
||||
* of the indicated type.
|
||||
*
|
||||
|
|
@ -335,7 +335,7 @@ set_primitive(int i, const GeomPrimitive *primitive) {
|
|||
* away other changes you might have recently made in an upstream thread.
|
||||
*/
|
||||
void Geom::
|
||||
add_primitive(const GeomPrimitive *primitive) {
|
||||
insert_primitive(size_t i, const GeomPrimitive *primitive) {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
CDWriter cdata(_cycler, true, current_thread);
|
||||
|
||||
|
|
@ -348,9 +348,13 @@ add_primitive(const GeomPrimitive *primitive) {
|
|||
|
||||
// They also should have a compatible shade model.
|
||||
CPT(GeomPrimitive) compat = primitive->match_shade_model(cdata->_shade_model);
|
||||
nassertv_always(compat != (GeomPrimitive *)NULL);
|
||||
nassertv_always(compat != nullptr);
|
||||
|
||||
cdata->_primitives.push_back((GeomPrimitive *)compat.p());
|
||||
if (i >= cdata->_primitives.size()) {
|
||||
cdata->_primitives.push_back((GeomPrimitive *)compat.p());
|
||||
} else {
|
||||
cdata->_primitives.insert(cdata->_primitives.begin() + i, (GeomPrimitive *)compat.p());
|
||||
}
|
||||
PrimitiveType new_primitive_type = compat->get_primitive_type();
|
||||
if (new_primitive_type != cdata->_primitive_type) {
|
||||
cdata->_primitive_type = new_primitive_type;
|
||||
|
|
@ -374,10 +378,10 @@ add_primitive(const GeomPrimitive *primitive) {
|
|||
* away other changes you might have recently made in an upstream thread.
|
||||
*/
|
||||
void Geom::
|
||||
remove_primitive(int i) {
|
||||
remove_primitive(size_t i) {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
CDWriter cdata(_cycler, true, current_thread);
|
||||
nassertv(i >= 0 && i < (int)cdata->_primitives.size());
|
||||
nassertv(i < cdata->_primitives.size());
|
||||
cdata->_primitives.erase(cdata->_primitives.begin() + i);
|
||||
if (cdata->_primitives.empty()) {
|
||||
cdata->_primitive_type = PT_none;
|
||||
|
|
|
|||
|
|
@ -87,15 +87,16 @@ PUBLISHED:
|
|||
|
||||
INLINE bool is_empty() const;
|
||||
|
||||
INLINE int get_num_primitives() const;
|
||||
INLINE CPT(GeomPrimitive) get_primitive(int i) const;
|
||||
INLINE size_t get_num_primitives() const;
|
||||
INLINE CPT(GeomPrimitive) get_primitive(size_t i) const;
|
||||
MAKE_SEQ(get_primitives, get_num_primitives, get_primitive);
|
||||
INLINE PT(GeomPrimitive) modify_primitive(int i);
|
||||
void set_primitive(int i, const GeomPrimitive *primitive);
|
||||
void add_primitive(const GeomPrimitive *primitive);
|
||||
void remove_primitive(int i);
|
||||
INLINE PT(GeomPrimitive) modify_primitive(size_t i);
|
||||
void set_primitive(size_t i, const GeomPrimitive *primitive);
|
||||
void insert_primitive(size_t i, const GeomPrimitive *primitive);
|
||||
INLINE void add_primitive(const GeomPrimitive *primitive);
|
||||
void remove_primitive(size_t i);
|
||||
void clear_primitives();
|
||||
MAKE_SEQ_PROPERTY(primitives, get_num_primitives, get_primitive, set_primitive, remove_primitive);
|
||||
MAKE_SEQ_PROPERTY(primitives, get_num_primitives, get_primitive, set_primitive, remove_primitive, insert_primitive);
|
||||
|
||||
INLINE PT(Geom) decompose() const;
|
||||
INLINE PT(Geom) doubleside() const;
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ reserve_num_rows(int n) {
|
|||
* Returns the number of individual arrays stored within the data. This must
|
||||
* match get_format()->get_num_arrays().
|
||||
*/
|
||||
INLINE int GeomVertexData::
|
||||
INLINE size_t GeomVertexData::
|
||||
get_num_arrays() const {
|
||||
CDReader cdata(_cycler);
|
||||
return cdata->_arrays.size();
|
||||
|
|
@ -141,9 +141,9 @@ get_num_arrays() const {
|
|||
* data.
|
||||
*/
|
||||
INLINE CPT(GeomVertexArrayData) GeomVertexData::
|
||||
get_array(int i) const {
|
||||
get_array(size_t i) const {
|
||||
CDReader cdata(_cycler);
|
||||
nassertr(i >= 0 && i < (int)cdata->_arrays.size(), NULL);
|
||||
nassertr(i < cdata->_arrays.size(), nullptr);
|
||||
return cdata->_arrays[i].get_read_pointer();
|
||||
}
|
||||
|
||||
|
|
@ -151,10 +151,10 @@ get_array(int i) const {
|
|||
* Equivalent to get_array(i).get_handle().
|
||||
*/
|
||||
INLINE CPT(GeomVertexArrayDataHandle) GeomVertexData::
|
||||
get_array_handle(int i) const {
|
||||
get_array_handle(size_t i) const {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
CDReader cdata(_cycler, current_thread);
|
||||
nassertr(i >= 0 && i < (int)cdata->_arrays.size(), NULL);
|
||||
nassertr(i < cdata->_arrays.size(), nullptr);
|
||||
return new GeomVertexArrayDataHandle(cdata->_arrays[i].get_read_pointer(), current_thread);
|
||||
}
|
||||
|
||||
|
|
@ -168,7 +168,7 @@ get_array_handle(int i) const {
|
|||
* away other changes you might have recently made in an upstream thread.
|
||||
*/
|
||||
INLINE PT(GeomVertexArrayData) GeomVertexData::
|
||||
modify_array(int i) {
|
||||
modify_array(size_t i) {
|
||||
GeomVertexDataPipelineWriter writer(this, true, Thread::get_current_thread());
|
||||
return writer.modify_array(i);
|
||||
}
|
||||
|
|
@ -177,7 +177,7 @@ modify_array(int i) {
|
|||
* Equivalent to modify_array(i).modify_handle().
|
||||
*/
|
||||
INLINE PT(GeomVertexArrayDataHandle) GeomVertexData::
|
||||
modify_array_handle(int i) {
|
||||
modify_array_handle(size_t i) {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
GeomVertexDataPipelineWriter writer(this, true, current_thread);
|
||||
return new GeomVertexArrayDataHandle(writer.modify_array(i), current_thread);
|
||||
|
|
@ -192,7 +192,7 @@ modify_array_handle(int i) {
|
|||
* away other changes you might have recently made in an upstream thread.
|
||||
*/
|
||||
INLINE void GeomVertexData::
|
||||
set_array(int i, const GeomVertexArrayData *array) {
|
||||
set_array(size_t i, const GeomVertexArrayData *array) {
|
||||
GeomVertexDataPipelineWriter writer(this, true, Thread::get_current_thread());
|
||||
writer.set_array(i, array);
|
||||
}
|
||||
|
|
@ -888,9 +888,9 @@ check_array_writers() const {
|
|||
*
|
||||
*/
|
||||
INLINE GeomVertexArrayDataHandle *GeomVertexDataPipelineWriter::
|
||||
get_array_writer(int i) const {
|
||||
get_array_writer(size_t i) const {
|
||||
nassertr(_got_array_writers, NULL);
|
||||
nassertr(i >= 0 && i < (int)_array_writers.size(), NULL);
|
||||
nassertr(i < _array_writers.size(), nullptr);
|
||||
return _array_writers[i];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2565,8 +2565,8 @@ reserve_num_rows(int n) {
|
|||
*
|
||||
*/
|
||||
PT(GeomVertexArrayData) GeomVertexDataPipelineWriter::
|
||||
modify_array(int i) {
|
||||
nassertr(i >= 0 && i < (int)_cdata->_arrays.size(), NULL);
|
||||
modify_array(size_t i) {
|
||||
nassertr(i < _cdata->_arrays.size(), nullptr);
|
||||
|
||||
PT(GeomVertexArrayData) new_data;
|
||||
if (_got_array_writers) {
|
||||
|
|
@ -2586,8 +2586,8 @@ modify_array(int i) {
|
|||
*
|
||||
*/
|
||||
void GeomVertexDataPipelineWriter::
|
||||
set_array(int i, const GeomVertexArrayData *array) {
|
||||
nassertv(i >= 0 && i < (int)_cdata->_arrays.size());
|
||||
set_array(size_t i, const GeomVertexArrayData *array) {
|
||||
nassertv(i < _cdata->_arrays.size());
|
||||
_cdata->_arrays[i] = (GeomVertexArrayData *)array;
|
||||
_object->clear_cache_stage();
|
||||
_cdata->_modified = Geom::get_next_modified();
|
||||
|
|
|
|||
|
|
@ -105,13 +105,13 @@ PUBLISHED:
|
|||
INLINE bool reserve_num_rows(int n);
|
||||
void clear_rows();
|
||||
|
||||
INLINE int get_num_arrays() const;
|
||||
INLINE CPT(GeomVertexArrayData) get_array(int i) const;
|
||||
INLINE CPT(GeomVertexArrayDataHandle) get_array_handle(int i) const;
|
||||
INLINE size_t get_num_arrays() const;
|
||||
INLINE CPT(GeomVertexArrayData) get_array(size_t i) const;
|
||||
INLINE CPT(GeomVertexArrayDataHandle) get_array_handle(size_t i) const;
|
||||
MAKE_SEQ(get_arrays, get_num_arrays, get_array);
|
||||
INLINE PT(GeomVertexArrayData) modify_array(int i);
|
||||
INLINE PT(GeomVertexArrayDataHandle) modify_array_handle(int i);
|
||||
INLINE void set_array(int i, const GeomVertexArrayData *array);
|
||||
INLINE PT(GeomVertexArrayData) modify_array(size_t i);
|
||||
INLINE PT(GeomVertexArrayDataHandle) modify_array_handle(size_t i);
|
||||
INLINE void set_array(size_t i, const GeomVertexArrayData *array);
|
||||
MAKE_SEQ_PROPERTY(arrays, get_num_arrays, get_array, set_array);
|
||||
|
||||
INLINE const TransformTable *get_transform_table() const;
|
||||
|
|
@ -520,10 +520,10 @@ public:
|
|||
INLINE GeomVertexData *get_object() const;
|
||||
|
||||
INLINE void check_array_writers() const;
|
||||
INLINE GeomVertexArrayDataHandle *get_array_writer(int i) const;
|
||||
INLINE GeomVertexArrayDataHandle *get_array_writer(size_t i) const;
|
||||
|
||||
PT(GeomVertexArrayData) modify_array(int i);
|
||||
void set_array(int i, const GeomVertexArrayData *array);
|
||||
PT(GeomVertexArrayData) modify_array(size_t i);
|
||||
void set_array(size_t i, const GeomVertexArrayData *array);
|
||||
|
||||
int get_num_rows() const;
|
||||
bool set_num_rows(int n);
|
||||
|
|
|
|||
|
|
@ -310,7 +310,9 @@ add_array(const GeomVertexArrayFormat *array_format) {
|
|||
void GeomVertexFormat::
|
||||
insert_array(size_t array, const GeomVertexArrayFormat *array_format) {
|
||||
nassertv(!is_registered());
|
||||
nassertv(array <= _arrays.size());
|
||||
if (array > _arrays.size()) {
|
||||
array = _arrays.size();
|
||||
}
|
||||
|
||||
_arrays.insert(_arrays.begin() + array, (GeomVertexArrayFormat *)array_format);
|
||||
}
|
||||
|
|
@ -377,6 +379,22 @@ get_column(size_t i) const {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the ith column, across all arrays.
|
||||
*/
|
||||
const InternalName *GeomVertexFormat::
|
||||
get_column_name(size_t i) const {
|
||||
Arrays::const_iterator ai;
|
||||
for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
|
||||
if (i < (size_t)(*ai)->get_num_columns()) {
|
||||
return (*ai)->get_column(i)->get_name();
|
||||
}
|
||||
i -= (*ai)->get_num_columns();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index number of the array with the ith column.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ PUBLISHED:
|
|||
int get_array_with(const InternalName *name) const;
|
||||
const GeomVertexColumn *get_column(const InternalName *name) const;
|
||||
INLINE bool has_column(const InternalName *name) const;
|
||||
const InternalName *get_column_name(size_t i) const;
|
||||
|
||||
MAKE_SEQ(get_columns, get_num_columns, get_column);
|
||||
|
||||
|
|
@ -120,13 +121,13 @@ PUBLISHED:
|
|||
MAKE_SEQ(get_morph_bases, get_num_morphs, get_morph_base);
|
||||
MAKE_SEQ(get_morph_deltas, get_num_morphs, get_morph_delta);
|
||||
|
||||
MAKE_SEQ_PROPERTY(arrays, get_num_arrays, get_array, set_array, remove_array);
|
||||
MAKE_SEQ_PROPERTY(columns, get_num_columns, get_column);
|
||||
MAKE_SEQ_PROPERTY(arrays, get_num_arrays, get_array, set_array, remove_array, insert_array);
|
||||
MAKE_SEQ_PROPERTY(points, get_num_points, get_point);
|
||||
MAKE_SEQ_PROPERTY(vectors, get_num_vectors, get_vector);
|
||||
|
||||
// We also define this as a mapping interface, for lookups by name.
|
||||
MAKE_MAP_PROPERTY(columns, has_column, get_column);
|
||||
MAKE_MAP_KEYS_SEQ(columns, get_num_columns, get_column_name);
|
||||
|
||||
void output(ostream &out) const;
|
||||
void write(ostream &out, int indent_level = 0) const;
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@ PUBLISHED:
|
|||
|
||||
MAKE_SEQ_PROPERTY(transforms, get_num_transforms, get_transform,
|
||||
set_transform, remove_transform);
|
||||
MAKE_SEQ_PROPERTY(weights, get_num_transforms, get_weight, set_weight);
|
||||
MAKE_MAP_PROPERTY(weights, has_transform, get_weight);
|
||||
MAKE_MAP_KEYS_SEQ(weights, get_num_transforms, get_transform);
|
||||
|
||||
INLINE void update_blend(Thread *current_thread) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -65,6 +65,23 @@ set_transform(size_t n, const VertexTransform *transform) {
|
|||
_transforms[n] = transform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a new transform to the table at the given index position. If the
|
||||
* index is beyond the end of the table, appends it to the end. Only valid
|
||||
* for unregistered tables.
|
||||
*
|
||||
* This does not automatically uniquify the pointer; if the transform is
|
||||
* already present in the table, it will be added twice.
|
||||
*/
|
||||
void TransformTable::
|
||||
insert_transform(size_t n, const VertexTransform *transform) {
|
||||
nassertv(!_is_registered);
|
||||
if (n > _transforms.size()) {
|
||||
n = _transforms.size();
|
||||
}
|
||||
_transforms.insert(_transforms.begin() + n, transform);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the nth transform. Only valid for unregistered tables.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ PUBLISHED:
|
|||
INLINE UpdateSeq get_modified(Thread *current_thread = Thread::get_current_thread()) const;
|
||||
|
||||
void set_transform(size_t n, const VertexTransform *transform);
|
||||
void insert_transform(size_t n, const VertexTransform *transform);
|
||||
void remove_transform(size_t n);
|
||||
size_t add_transform(const VertexTransform *transform);
|
||||
|
||||
|
|
@ -58,7 +59,8 @@ PUBLISHED:
|
|||
|
||||
MAKE_PROPERTY(registered, is_registered);
|
||||
MAKE_PROPERTY(modified, get_modified);
|
||||
MAKE_SEQ_PROPERTY(transforms, get_num_transforms, get_transform, set_transform, remove_transform);
|
||||
MAKE_SEQ_PROPERTY(transforms, get_num_transforms, get_transform, set_transform,
|
||||
remove_transform, insert_transform);
|
||||
|
||||
private:
|
||||
void do_register();
|
||||
|
|
|
|||
|
|
@ -36,6 +36,15 @@ get_curve(int index) const {
|
|||
return _curves[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new ParametricCurve to the collection at the indicated index.
|
||||
* @deprecated Use insert_curve(index, curve) instead.
|
||||
*/
|
||||
INLINE void ParametricCurveCollection::
|
||||
add_curve(ParametricCurve *curve, int index) {
|
||||
insert_curve(max(index, 0), curve);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum T value associated with the *last* curve in the
|
||||
* collection. Normally, this will be either the XYZ or HPR curve, or a
|
||||
|
|
|
|||
|
|
@ -42,9 +42,9 @@ add_curve(ParametricCurve *curve) {
|
|||
* Adds a new ParametricCurve to the collection at the indicated index.
|
||||
*/
|
||||
void ParametricCurveCollection::
|
||||
add_curve(ParametricCurve *curve, int index) {
|
||||
insert_curve(size_t index, ParametricCurve *curve) {
|
||||
prepare_add_curve(curve);
|
||||
index = max(min(index, (int)_curves.size()), 0);
|
||||
index = min(index, _curves.size());
|
||||
_curves.insert(_curves.begin() + index, curve);
|
||||
redraw();
|
||||
}
|
||||
|
|
@ -93,8 +93,8 @@ remove_curve(ParametricCurve *curve) {
|
|||
* number.
|
||||
*/
|
||||
void ParametricCurveCollection::
|
||||
remove_curve(int index) {
|
||||
nassertv(index >= 0 && index < (int)_curves.size());
|
||||
remove_curve(size_t index) {
|
||||
nassertv(index < _curves.size());
|
||||
PT(ParametricCurve) curve = _curves[index];
|
||||
prepare_remove_curve(curve);
|
||||
_curves.erase(_curves.begin() + index);
|
||||
|
|
@ -107,8 +107,8 @@ remove_curve(int index) {
|
|||
* number.
|
||||
*/
|
||||
void ParametricCurveCollection::
|
||||
set_curve(int index, ParametricCurve *curve) {
|
||||
nassertv(index >= 0 && index < (int)_curves.size());
|
||||
set_curve(size_t index, ParametricCurve *curve) {
|
||||
nassertv(index < _curves.size());
|
||||
prepare_remove_curve(_curves[index]);
|
||||
prepare_add_curve(curve);
|
||||
_curves[index] = curve;
|
||||
|
|
|
|||
|
|
@ -41,10 +41,11 @@ PUBLISHED:
|
|||
|
||||
void add_curve(ParametricCurve *curve);
|
||||
void add_curve(ParametricCurve *curve, int index);
|
||||
void insert_curve(size_t index, ParametricCurve *curve);
|
||||
int add_curves(PandaNode *node);
|
||||
bool remove_curve(ParametricCurve *curve);
|
||||
void remove_curve(int index);
|
||||
void set_curve(int index, ParametricCurve *curve);
|
||||
void remove_curve(size_t index);
|
||||
void set_curve(size_t index, ParametricCurve *curve);
|
||||
bool has_curve(ParametricCurve *curve) const;
|
||||
void clear();
|
||||
void clear_timewarps();
|
||||
|
|
|
|||
|
|
@ -913,10 +913,11 @@ PUBLISHED:
|
|||
INLINE bool has_net_tag(const string &key) const;
|
||||
NodePath find_net_tag(const string &key) const;
|
||||
|
||||
MAKE_MAP_PROPERTY(tags, has_tag, get_tag, set_tag, clear_tag);
|
||||
MAKE_MAP_PROPERTY(net_tags, has_net_tag, get_net_tag);
|
||||
|
||||
EXTENSION(INLINE PyObject *get_tags() const);
|
||||
EXTENSION(INLINE PyObject *get_tag_keys() const);
|
||||
MAKE_PROPERTY(tags, get_tags);
|
||||
|
||||
EXTENSION(PyObject *get_python_tags());
|
||||
EXTENSION(INLINE void set_python_tag(PyObject *keys, PyObject *value));
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ get_python_tags() {
|
|||
/**
|
||||
* This variant on get_tag_keys returns a Python list of strings. Returns
|
||||
* None if the NodePath is empty.
|
||||
* @deprecated use `np.tags.keys()` instead.
|
||||
*/
|
||||
INLINE PyObject *Extension<NodePath>::
|
||||
get_tag_keys() const {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ extern struct Dtool_PyTypedObject Dtool_LPoint3d;
|
|||
extern struct Dtool_PyTypedObject Dtool_LPoint3f;
|
||||
#endif
|
||||
extern struct Dtool_PyTypedObject Dtool_NodePath;
|
||||
extern struct Dtool_PyTypedObject Dtool_PandaNode;
|
||||
#endif // CPPPARSER
|
||||
|
||||
/**
|
||||
|
|
@ -130,7 +131,7 @@ __reduce_persist__(PyObject *self, PyObject *pickler) const {
|
|||
}
|
||||
|
||||
// Start by getting this class object.
|
||||
PyObject *this_class = PyObject_Type(self);
|
||||
PyObject *this_class = (PyObject *)Py_TYPE(self);
|
||||
if (this_class == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -143,7 +144,6 @@ __reduce_persist__(PyObject *self, PyObject *pickler) const {
|
|||
func = Extension<TypedWritable>::find_global_decode(this_class, "py_decode_NodePath_from_bam_stream_persist");
|
||||
if (func == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError, "Couldn't find py_decode_NodePath_from_bam_stream_persist()");
|
||||
Py_DECREF(this_class);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -153,15 +153,13 @@ __reduce_persist__(PyObject *self, PyObject *pickler) const {
|
|||
func = Extension<TypedWritable>::find_global_decode(this_class, "py_decode_NodePath_from_bam_stream");
|
||||
if (func == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError, "Couldn't find py_decode_NodePath_from_bam_stream()");
|
||||
Py_DECREF(this_class);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// PyTuple_SET_ITEM conveniently borrows the reference it is passed.
|
||||
PyObject *args = PyTuple_New(2);
|
||||
PyTuple_SET_ITEM(args, 0, this_class);
|
||||
PyTuple_SET_ITEM(args, 1, Dtool_WrapValue(bam_stream));
|
||||
PyObject *args = PyTuple_New(1);
|
||||
PyTuple_SET_ITEM(args, 0, Dtool_WrapValue(bam_stream));
|
||||
|
||||
PyObject *tuple = PyTuple_New(2);
|
||||
PyTuple_SET_ITEM(tuple, 0, func);
|
||||
|
|
@ -169,6 +167,30 @@ __reduce_persist__(PyObject *self, PyObject *pickler) const {
|
|||
return tuple;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the associated node's tags.
|
||||
*/
|
||||
PyObject *Extension<NodePath>::
|
||||
get_tags() const {
|
||||
// An empty NodePath returns None
|
||||
if (_this->is_empty()) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
// Just call PandaNode.tags rather than defining a whole new interface.
|
||||
PT(PandaNode) node = _this->node();
|
||||
PyObject *py_node = DTool_CreatePyInstanceTyped
|
||||
((void *)node.p(), Dtool_PandaNode, true, false, node->get_type_index());
|
||||
|
||||
// DTool_CreatePyInstanceTyped() steals a C++ reference.
|
||||
node.cheat() = nullptr;
|
||||
|
||||
PyObject *result = PyObject_GetAttrString(py_node, "tags");
|
||||
Py_DECREF(py_node);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the lowest ancestor of this node that contains a tag definition
|
||||
* with the indicated key, if any, or an empty NodePath if no ancestor of this
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ public:
|
|||
PyObject *__reduce__(PyObject *self) const;
|
||||
PyObject *__reduce_persist__(PyObject *self, PyObject *pickler) const;
|
||||
|
||||
PyObject *get_tags() const;
|
||||
INLINE PyObject *get_tag_keys() const;
|
||||
|
||||
INLINE PyObject *get_python_tags();
|
||||
|
|
|
|||
|
|
@ -348,12 +348,12 @@ has_dirty_prev_transform() const {
|
|||
INLINE string PandaNode::
|
||||
get_tag(const string &key, Thread *current_thread) const {
|
||||
CDReader cdata(_cycler, current_thread);
|
||||
TagData::const_iterator ti;
|
||||
ti = cdata->_tag_data.find(key);
|
||||
if (ti != cdata->_tag_data.end()) {
|
||||
return (*ti).second;
|
||||
int index = cdata->_tag_data.find(key);
|
||||
if (index >= 0) {
|
||||
return cdata->_tag_data.get_data((size_t)index);
|
||||
} else {
|
||||
return string();
|
||||
}
|
||||
return string();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -364,9 +364,25 @@ get_tag(const string &key, Thread *current_thread) const {
|
|||
INLINE bool PandaNode::
|
||||
has_tag(const string &key, Thread *current_thread) const {
|
||||
CDReader cdata(_cycler, current_thread);
|
||||
TagData::const_iterator ti;
|
||||
ti = cdata->_tag_data.find(key);
|
||||
return (ti != cdata->_tag_data.end());
|
||||
return cdata->_tag_data.find(key) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of tags applied to this node.
|
||||
*/
|
||||
INLINE size_t PandaNode::
|
||||
get_num_tags() const {
|
||||
CDReader cdata(_cycler);
|
||||
return cdata->_tag_data.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key of the nth tag applied to this node.
|
||||
*/
|
||||
INLINE string PandaNode::
|
||||
get_tag_key(size_t i) const {
|
||||
CDReader cdata(_cycler);
|
||||
return cdata->_tag_data.get_key(i);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -376,7 +392,7 @@ has_tag(const string &key, Thread *current_thread) const {
|
|||
INLINE bool PandaNode::
|
||||
has_tags() const {
|
||||
CDReader cdata(_cycler);
|
||||
if (!cdata->_tag_data.empty()) {
|
||||
if (!cdata->_tag_data.is_empty()) {
|
||||
return true;
|
||||
}
|
||||
#ifdef HAVE_PYTHON
|
||||
|
|
@ -1448,12 +1464,12 @@ get_prev_transform() const {
|
|||
*/
|
||||
INLINE string PandaNodePipelineReader::
|
||||
get_tag(const string &key) const {
|
||||
PandaNode::TagData::const_iterator ti;
|
||||
ti = _cdata->_tag_data.find(key);
|
||||
if (ti != _cdata->_tag_data.end()) {
|
||||
return (*ti).second;
|
||||
int index = _cdata->_tag_data.find(key);
|
||||
if (index >= 0) {
|
||||
return _cdata->_tag_data.get_data((size_t)index);
|
||||
} else {
|
||||
return string();
|
||||
}
|
||||
return string();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1463,9 +1479,7 @@ get_tag(const string &key) const {
|
|||
*/
|
||||
INLINE bool PandaNodePipelineReader::
|
||||
has_tag(const string &key) const {
|
||||
PandaNode::TagData::const_iterator ti;
|
||||
ti = _cdata->_tag_data.find(key);
|
||||
return (ti != _cdata->_tag_data.end());
|
||||
return _cdata->_tag_data.find(key) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1216,7 +1216,7 @@ set_tag(const string &key, const string &value, Thread *current_thread) {
|
|||
// stages.
|
||||
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
|
||||
CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
|
||||
cdata->_tag_data[key] = value;
|
||||
cdata->_tag_data.store(key, value);
|
||||
cdata->set_fancy_bit(FB_tag, true);
|
||||
}
|
||||
CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
|
||||
|
|
@ -1231,8 +1231,8 @@ void PandaNode::
|
|||
clear_tag(const string &key, Thread *current_thread) {
|
||||
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
|
||||
CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
|
||||
cdata->_tag_data.erase(key);
|
||||
cdata->set_fancy_bit(FB_tag, !cdata->_tag_data.empty());
|
||||
cdata->_tag_data.remove(key);
|
||||
cdata->set_fancy_bit(FB_tag, !cdata->_tag_data.is_empty());
|
||||
}
|
||||
CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
|
||||
mark_bam_modified();
|
||||
|
|
@ -1257,13 +1257,10 @@ copy_tags(PandaNode *other) {
|
|||
CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
|
||||
CDStageReader cdatar(other->_cycler, pipeline_stage, current_thread);
|
||||
|
||||
TagData::const_iterator ti;
|
||||
for (ti = cdatar->_tag_data.begin();
|
||||
ti != cdatar->_tag_data.end();
|
||||
++ti) {
|
||||
cdataw->_tag_data[(*ti).first] = (*ti).second;
|
||||
for (size_t n = 0; n < cdatar->_tag_data.size(); ++n) {
|
||||
cdataw->_tag_data.store(cdatar->_tag_data.get_key(n), cdatar->_tag_data.get_data(n));
|
||||
}
|
||||
cdataw->set_fancy_bit(FB_tag, !cdataw->_tag_data.empty());
|
||||
cdataw->set_fancy_bit(FB_tag, !cdataw->_tag_data.is_empty());
|
||||
}
|
||||
CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
|
||||
|
||||
|
|
@ -1286,14 +1283,11 @@ copy_tags(PandaNode *other) {
|
|||
void PandaNode::
|
||||
list_tags(ostream &out, const string &separator) const {
|
||||
CDReader cdata(_cycler);
|
||||
if (!cdata->_tag_data.empty()) {
|
||||
TagData::const_iterator ti = cdata->_tag_data.begin();
|
||||
out << (*ti).first;
|
||||
++ti;
|
||||
while (ti != cdata->_tag_data.end()) {
|
||||
out << separator << (*ti).first;
|
||||
++ti;
|
||||
for (size_t n = 0; n < cdata->_tag_data.size(); ++n) {
|
||||
if (n > 0) {
|
||||
out << separator;
|
||||
}
|
||||
out << cdata->_tag_data.get_key(n);
|
||||
}
|
||||
|
||||
// We used to list the Python tags here. That's a bit awkward, though,
|
||||
|
|
@ -1310,12 +1304,8 @@ list_tags(ostream &out, const string &separator) const {
|
|||
void PandaNode::
|
||||
get_tag_keys(vector_string &keys) const {
|
||||
CDReader cdata(_cycler);
|
||||
if (!cdata->_tag_data.empty()) {
|
||||
TagData::const_iterator ti = cdata->_tag_data.begin();
|
||||
while (ti != cdata->_tag_data.end()) {
|
||||
keys.push_back((*ti).first);
|
||||
++ti;
|
||||
}
|
||||
for (size_t n = 0; n < cdata->_tag_data.size(); ++n) {
|
||||
keys.push_back(cdata->_tag_data.get_key(n));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1331,28 +1321,30 @@ compare_tags(const PandaNode *other) const {
|
|||
CDReader cdata(_cycler);
|
||||
CDReader cdata_other(other->_cycler);
|
||||
|
||||
TagData::const_iterator ati = cdata->_tag_data.begin();
|
||||
TagData::const_iterator bti = cdata_other->_tag_data.begin();
|
||||
while (ati != cdata->_tag_data.end() &&
|
||||
bti != cdata_other->_tag_data.end()) {
|
||||
int cmp = strcmp((*ati).first.c_str(), (*bti).first.c_str());
|
||||
const TagData &a_data = cdata->_tag_data;
|
||||
const TagData &b_data = cdata_other->_tag_data;
|
||||
|
||||
size_t ai = 0;
|
||||
size_t bi = 0;
|
||||
while (ai < a_data.size() && bi < b_data.size()) {
|
||||
int cmp = strcmp(a_data.get_key(ai).c_str(), b_data.get_key(bi).c_str());
|
||||
if (cmp != 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
cmp = strcmp((*ati).second.c_str(), (*bti).second.c_str());
|
||||
cmp = strcmp(a_data.get_key(ai).c_str(), b_data.get_key(bi).c_str());
|
||||
if (cmp != 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
++ati;
|
||||
++bti;
|
||||
++ai;
|
||||
++bi;
|
||||
}
|
||||
if (ati != cdata->_tag_data.end()) {
|
||||
if (ai < a_data.size()) {
|
||||
// list A is longer.
|
||||
return 1;
|
||||
}
|
||||
if (bti != cdata_other->_tag_data.end()) {
|
||||
if (bi < b_data.size()) {
|
||||
// list B is longer.
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1412,11 +1404,8 @@ copy_all_properties(PandaNode *other) {
|
|||
// to preserve properties such as the default GeomNode bitmask.
|
||||
cdataw->_into_collide_mask |= cdatar->_into_collide_mask;
|
||||
|
||||
TagData::const_iterator ti;
|
||||
for (ti = cdatar->_tag_data.begin();
|
||||
ti != cdatar->_tag_data.end();
|
||||
++ti) {
|
||||
cdataw->_tag_data[(*ti).first] = (*ti).second;
|
||||
for (size_t n = 0; n < cdatar->_tag_data.size(); ++n) {
|
||||
cdataw->_tag_data.store(cdatar->_tag_data.get_key(n), cdatar->_tag_data.get_data(n));
|
||||
}
|
||||
|
||||
static const int change_bits = (FB_transform | FB_state | FB_effects |
|
||||
|
|
@ -3775,13 +3764,11 @@ write_datagram(BamWriter *manager, Datagram &dg) const {
|
|||
dg.add_uint8(_bounds_type);
|
||||
|
||||
dg.add_uint32(_tag_data.size());
|
||||
TagData::const_iterator ti;
|
||||
for (ti = _tag_data.begin(); ti != _tag_data.end(); ++ti) {
|
||||
dg.add_string((*ti).first);
|
||||
dg.add_string((*ti).second);
|
||||
for (size_t n = 0; n < _tag_data.size(); ++n) {
|
||||
dg.add_string(_tag_data.get_key(n));
|
||||
dg.add_string(_tag_data.get_data(n));
|
||||
}
|
||||
|
||||
|
||||
write_up_list(*get_up(), manager, dg);
|
||||
write_down_list(*get_down(), manager, dg);
|
||||
write_down_list(*get_stashed(), manager, dg);
|
||||
|
|
@ -3855,7 +3842,7 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
|
|||
set_fancy_bit(FB_transform, !_transform->is_identity());
|
||||
set_fancy_bit(FB_state, !_state->is_empty());
|
||||
set_fancy_bit(FB_effects, !_effects->is_empty());
|
||||
set_fancy_bit(FB_tag, !_tag_data.empty());
|
||||
set_fancy_bit(FB_tag, !_tag_data.is_empty());
|
||||
|
||||
// Mark the bounds stale.
|
||||
++_next_update;
|
||||
|
|
@ -3914,7 +3901,7 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|||
for (int i = 0; i < num_tags; i++) {
|
||||
string key = scan.get_string();
|
||||
string value = scan.get_string();
|
||||
_tag_data[key] = value;
|
||||
_tag_data.store(key, value);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#include "copyOnWritePointer.h"
|
||||
#include "lightReMutex.h"
|
||||
#include "extension.h"
|
||||
#include "simpleHashMap.h"
|
||||
|
||||
class NodePathComponent;
|
||||
class CullTraverser;
|
||||
|
|
@ -196,7 +197,15 @@ PUBLISHED:
|
|||
Thread *current_thread = Thread::get_current_thread()) const;
|
||||
void clear_tag(const string &key,
|
||||
Thread *current_thread = Thread::get_current_thread());
|
||||
|
||||
public:
|
||||
void get_tag_keys(vector_string &keys) const;
|
||||
INLINE size_t get_num_tags() const;
|
||||
INLINE string get_tag_key(size_t i) const;
|
||||
|
||||
PUBLISHED:
|
||||
MAKE_MAP_PROPERTY(tags, has_tag, get_tag, set_tag, clear_tag);
|
||||
MAKE_MAP_KEYS_SEQ(tags, get_num_tags, get_tag_key);
|
||||
|
||||
EXTENSION(PyObject *get_tag_keys() const);
|
||||
|
||||
|
|
@ -511,7 +520,7 @@ private:
|
|||
|
||||
// This is used to maintain a table of keyed data on each node, for the
|
||||
// user's purposes.
|
||||
typedef phash_map<string, string, string_hash> TagData;
|
||||
typedef SimpleHashMap<string, string, string_hash> TagData;
|
||||
|
||||
// This is actually implemented in pandaNode_ext.h, but defined here so
|
||||
// that we can destruct it from the C++ side. Note that it isn't cycled,
|
||||
|
|
|
|||
|
|
@ -97,8 +97,9 @@ is_empty() const {
|
|||
|
||||
/**
|
||||
* Returns the number of separate effects indicated in the state.
|
||||
* @deprecated in Python, use len(effects) instead, or effects.size() in C++.
|
||||
*/
|
||||
INLINE int RenderEffects::
|
||||
INLINE size_t RenderEffects::
|
||||
get_num_effects() const {
|
||||
return _effects.size();
|
||||
}
|
||||
|
|
@ -107,11 +108,36 @@ get_num_effects() const {
|
|||
* Returns the nth effect in the state.
|
||||
*/
|
||||
INLINE const RenderEffect *RenderEffects::
|
||||
get_effect(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_effects.size(), NULL);
|
||||
get_effect(size_t n) const {
|
||||
nassertr(n < _effects.size(), nullptr);
|
||||
return _effects[n]._effect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of separate effects indicated in the state.
|
||||
*/
|
||||
INLINE size_t RenderEffects::
|
||||
size() const {
|
||||
return _effects.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the nth effect in the state.
|
||||
*/
|
||||
INLINE const RenderEffect *RenderEffects::
|
||||
operator [](size_t n) const {
|
||||
nassertr(n < _effects.size(), nullptr);
|
||||
return _effects[n]._effect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the effect in the state with the given type.
|
||||
*/
|
||||
INLINE const RenderEffect *RenderEffects::
|
||||
operator [](TypeHandle type) const {
|
||||
return get_effect(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is provided as an optimization, to speed up the render-time
|
||||
* checking for the existance of a DecalEffect on this state. It returns true
|
||||
|
|
|
|||
|
|
@ -58,8 +58,12 @@ PUBLISHED:
|
|||
bool operator < (const RenderEffects &other) const;
|
||||
|
||||
INLINE bool is_empty() const;
|
||||
INLINE int get_num_effects() const;
|
||||
INLINE const RenderEffect *get_effect(int n) const;
|
||||
INLINE size_t get_num_effects() const;
|
||||
INLINE const RenderEffect *get_effect(size_t n) const;
|
||||
|
||||
INLINE size_t size() const;
|
||||
INLINE const RenderEffect *operator [] (size_t n) const;
|
||||
INLINE const RenderEffect *operator [] (TypeHandle type) const;
|
||||
|
||||
int find_effect(TypeHandle type) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,12 @@ PUBLISHED:
|
|||
int find_on_stage(const TextureStage *stage) const;
|
||||
|
||||
MAKE_SEQ_PROPERTY(on_stages, get_num_on_stages, get_on_stage);
|
||||
MAKE_MAP_PROPERTY(on_stages, find_on_stage, get_on_stage);
|
||||
|
||||
MAKE_MAP_PROPERTY(textures, has_on_stage, get_on_texture);
|
||||
MAKE_MAP_KEYS_SEQ(textures, get_num_on_stages, get_on_stage);
|
||||
|
||||
MAKE_MAP_PROPERTY(samplers, has_on_stage, get_on_sampler);
|
||||
MAKE_MAP_KEYS_SEQ(samplers, get_num_on_stages, get_on_stage);
|
||||
|
||||
INLINE int get_num_off_stages() const;
|
||||
INLINE TextureStage *get_off_stage(int n) const;
|
||||
|
|
@ -74,7 +79,6 @@ PUBLISHED:
|
|||
INLINE bool has_all_off() const;
|
||||
|
||||
MAKE_SEQ_PROPERTY(off_stages, get_num_off_stages, get_off_stage);
|
||||
MAKE_MAP_PROPERTY(off_stages, has_off_stage, get_off_stage);
|
||||
|
||||
INLINE bool is_identity() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -71,6 +71,21 @@ set_dispatch(size_t n, const LVecBase3i &dispatch) {
|
|||
cdata->_dispatches[n] = dispatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a dispatch command with the given number of work groups in the X,
|
||||
* Y, and Z dimensions at the given position in the list of dispatch commands.
|
||||
* Any of these values may be set to 1 if the respective dimension should not
|
||||
* be used.
|
||||
*/
|
||||
INLINE void ComputeNode::
|
||||
insert_dispatch(size_t n, const LVecBase3i &dispatch) {
|
||||
Dispatcher::CDWriter cdata(_dispatcher->_cycler);
|
||||
if (n > cdata->_dispatches.size()) {
|
||||
n = cdata->_dispatches.size();
|
||||
}
|
||||
cdata->_dispatches.insert(cdata->_dispatches.begin(), dispatch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Erases the given dispatch index from the list.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -34,11 +34,12 @@ PUBLISHED:
|
|||
INLINE size_t get_num_dispatches() const;
|
||||
INLINE const LVecBase3i &get_dispatch(size_t i) const;
|
||||
INLINE void set_dispatch(size_t i, const LVecBase3i &num_groups);
|
||||
INLINE void insert_dispatch(size_t i, const LVecBase3i &num_groups);
|
||||
INLINE void remove_dispatch(size_t i);
|
||||
INLINE void clear_dispatches();
|
||||
|
||||
MAKE_SEQ(get_dispatches, get_num_dispatches, get_dispatch);
|
||||
MAKE_SEQ_PROPERTY(dispatches, get_num_dispatches, get_dispatch, set_dispatch, remove_dispatch);
|
||||
MAKE_SEQ_PROPERTY(dispatches, get_num_dispatches, get_dispatch, set_dispatch, remove_dispatch, insert_dispatch);
|
||||
|
||||
public:
|
||||
ComputeNode(const ComputeNode ©);
|
||||
|
|
|
|||
|
|
@ -69,15 +69,29 @@ add_forces_from(const ForceNode &other) {
|
|||
*/
|
||||
void ForceNode::
|
||||
set_force(size_t index, BaseForce *force) {
|
||||
nassertv(index <= _forces.size());
|
||||
nassertv(index < _forces.size());
|
||||
|
||||
_forces[index]->_force_node = (ForceNode *)NULL;
|
||||
_forces[index]->_force_node = nullptr;
|
||||
_forces[index]->_force_node_path.clear();
|
||||
_forces[index] = force;
|
||||
force->_force_node = this;
|
||||
force->_force_node_path = NodePath(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* insert operation
|
||||
*/
|
||||
void ForceNode::
|
||||
insert_force(size_t index, BaseForce *force) {
|
||||
if (index > _forces.size()) {
|
||||
index = _forces.size();
|
||||
}
|
||||
|
||||
_forces.insert(_forces.begin() + index, force);
|
||||
force->_force_node = this;
|
||||
force->_force_node_path = NodePath(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* remove operation
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -35,10 +35,11 @@ PUBLISHED:
|
|||
|
||||
void add_forces_from(const ForceNode &other);
|
||||
void set_force(size_t index, BaseForce *force);
|
||||
void insert_force(size_t index, BaseForce *force);
|
||||
void remove_force(BaseForce *force);
|
||||
void remove_force(size_t index);
|
||||
|
||||
MAKE_SEQ_PROPERTY(forces, get_num_forces, get_force, set_force, remove_force);
|
||||
MAKE_SEQ_PROPERTY(forces, get_num_forces, get_force, set_force, remove_force, insert_force);
|
||||
|
||||
virtual void output(ostream &out) const;
|
||||
virtual void write_forces(ostream &out, unsigned int indent=0) const;
|
||||
|
|
|
|||
|
|
@ -77,13 +77,26 @@ add_physicals_from(const PhysicalNode &other) {
|
|||
*/
|
||||
void PhysicalNode::
|
||||
set_physical(size_t index, Physical *physical) {
|
||||
nassertv(index <= _physicals.size());
|
||||
nassertv(index < _physicals.size());
|
||||
|
||||
_physicals[index]->_physical_node = (PhysicalNode *) NULL;
|
||||
_physicals[index]->_physical_node = nullptr;
|
||||
_physicals[index] = physical;
|
||||
physical->_physical_node = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* insert operation
|
||||
*/
|
||||
void PhysicalNode::
|
||||
insert_physical(size_t index, Physical *physical) {
|
||||
if (index > _physicals.size()) {
|
||||
index = _physicals.size();
|
||||
}
|
||||
|
||||
_physicals.insert(_physicals.begin() + index, physical);
|
||||
physical->_physical_node = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* remove operation
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -36,10 +36,12 @@ PUBLISHED:
|
|||
|
||||
void add_physicals_from(const PhysicalNode &other);
|
||||
void set_physical(size_t index, Physical *physical);
|
||||
void insert_physical(size_t index, Physical *physical);
|
||||
void remove_physical(Physical *physical);
|
||||
void remove_physical(size_t index);
|
||||
|
||||
MAKE_SEQ_PROPERTY(physicals, get_num_physicals, get_physical, set_physical, remove_physical);
|
||||
MAKE_SEQ_PROPERTY(physicals, get_num_physicals, get_physical, set_physical,
|
||||
remove_physical, insert_physical);
|
||||
|
||||
virtual void write(ostream &out, unsigned int indent=0) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,25 @@ SimpleHashMap(const Compare &comp) :
|
|||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template<class Key, class Value, class Compare>
|
||||
INLINE SimpleHashMap<Key, Value, Compare>::
|
||||
SimpleHashMap(const SimpleHashMap ©) :
|
||||
_table_size(copy._table_size),
|
||||
_num_entries(copy._num_entries),
|
||||
_comp(copy._comp) {
|
||||
|
||||
// We allocate enough bytes for _table_size elements of TableEntry, plus
|
||||
// _table_size * 4 more ints at the end (for the index array).
|
||||
size_t alloc_size = _table_size * (sizeof(TableEntry) + sizeof(int) * sparsity);
|
||||
|
||||
_deleted_chain = memory_hook->get_deleted_chain(alloc_size);
|
||||
_table = (TableEntry *)_deleted_chain->allocate(alloc_size, TypeHandle::none());
|
||||
memcpy(_table, copy._table, alloc_size);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -37,7 +56,10 @@ SimpleHashMap(SimpleHashMap &&from) NOEXCEPT :
|
|||
_num_entries(from._num_entries),
|
||||
_comp(move(from._comp))
|
||||
{
|
||||
from._table = nullptr;
|
||||
from._deleted_chain = nullptr;
|
||||
from._table_size = 0;
|
||||
from._num_entries = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -49,6 +71,48 @@ INLINE SimpleHashMap<Key, Value, Compare>::
|
|||
clear();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template<class Key, class Value, class Compare>
|
||||
INLINE SimpleHashMap<Key, Value, Compare> &SimpleHashMap<Key, Value, Compare>::
|
||||
operator = (const SimpleHashMap<Key, Value, Compare> ©) {
|
||||
if (this != ©) {
|
||||
_table_size = copy._table_size;
|
||||
_num_entries = copy._num_entries;
|
||||
_comp = copy._comp;
|
||||
|
||||
// We allocate enough bytes for _table_size elements of TableEntry, plus
|
||||
// _table_size * 4 more ints at the end (for the index array).
|
||||
size_t alloc_size = _table_size * (sizeof(TableEntry) + sizeof(int) * sparsity);
|
||||
|
||||
_deleted_chain = memory_hook->get_deleted_chain(alloc_size);
|
||||
_table = (TableEntry *)_deleted_chain->allocate(alloc_size, TypeHandle::none());
|
||||
memcpy(_table, copy._table, alloc_size);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template<class Key, class Value, class Compare>
|
||||
INLINE SimpleHashMap<Key, Value, Compare> &SimpleHashMap<Key, Value, Compare>::
|
||||
operator = (SimpleHashMap<Key, Value, Compare> &&from) NOEXCEPT {
|
||||
if (this != &from) {
|
||||
_table = from._table;
|
||||
_deleted_chain = from._deleted_chain;
|
||||
_table_size = from._table_size;
|
||||
_num_entries = from._num_entries;
|
||||
_comp = move(from._comp);
|
||||
|
||||
from._table = nullptr;
|
||||
from._deleted_chain = nullptr;
|
||||
from._table_size = 0;
|
||||
from._num_entries = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Quickly exchanges the contents of this map and the other map.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -86,9 +86,13 @@ class SimpleHashMap {
|
|||
public:
|
||||
#ifndef CPPPARSER
|
||||
CONSTEXPR SimpleHashMap(const Compare &comp = Compare());
|
||||
INLINE SimpleHashMap(const SimpleHashMap ©);
|
||||
INLINE SimpleHashMap(SimpleHashMap &&from) NOEXCEPT;
|
||||
INLINE ~SimpleHashMap();
|
||||
|
||||
INLINE SimpleHashMap &operator = (const SimpleHashMap ©);
|
||||
INLINE SimpleHashMap &operator = (SimpleHashMap &&from) NOEXCEPT;
|
||||
|
||||
INLINE void swap(SimpleHashMap &other);
|
||||
|
||||
int find(const Key &key) const;
|
||||
|
|
|
|||
|
|
@ -53,18 +53,31 @@ def test_fbquality_rgba64():
|
|||
# This issue occurs if we are requesting 1 bit, not if we are requesting
|
||||
# a specific amount. There are several ways to do that, so we want to
|
||||
# assert that none of them will yield a 64-bit color buffer.
|
||||
req_color = FrameBufferProperties()
|
||||
req_color.color_bits = 1
|
||||
req_color0 = FrameBufferProperties()
|
||||
req_color0.color_bits = 0
|
||||
|
||||
req_color_alpha = FrameBufferProperties()
|
||||
req_color_alpha.color_bits = 1
|
||||
req_color_alpha.alpha_bits = 1
|
||||
req_color1 = FrameBufferProperties()
|
||||
req_color1.color_bits = 1
|
||||
|
||||
req_rgb = FrameBufferProperties()
|
||||
req_rgb.set_rgba_bits(1, 1, 1, 0)
|
||||
req_color0_alpha0 = FrameBufferProperties()
|
||||
req_color0_alpha0.color_bits = 0
|
||||
req_color0_alpha0.alpha_bits = 0
|
||||
|
||||
req_rgb_alpha = FrameBufferProperties()
|
||||
req_rgb_alpha.set_rgba_bits(1, 1, 1, 1)
|
||||
req_color1_alpha1 = FrameBufferProperties()
|
||||
req_color1_alpha1.color_bits = 1
|
||||
req_color1_alpha1.alpha_bits = 1
|
||||
|
||||
req_rgb0 = FrameBufferProperties()
|
||||
req_rgb0.set_rgba_bits(0, 0, 0, 0)
|
||||
|
||||
req_rgb1 = FrameBufferProperties()
|
||||
req_rgb1.set_rgba_bits(1, 1, 1, 0)
|
||||
|
||||
req_rgb0_alpha0 = FrameBufferProperties()
|
||||
req_rgb0_alpha0.set_rgba_bits(0, 0, 0, 0)
|
||||
|
||||
req_rgb1_alpha1 = FrameBufferProperties()
|
||||
req_rgb1_alpha1.set_rgba_bits(1, 1, 1, 1)
|
||||
|
||||
fb_rgba8 = FrameBufferProperties()
|
||||
fb_rgba8.rgb_color = True
|
||||
|
|
@ -74,7 +87,11 @@ def test_fbquality_rgba64():
|
|||
fb_rgba16.rgb_color = True
|
||||
fb_rgba16.set_rgba_bits(16, 16, 16, 16)
|
||||
|
||||
assert fb_rgba8.get_quality(req_color) > fb_rgba16.get_quality(req_color)
|
||||
assert fb_rgba8.get_quality(req_color_alpha) > fb_rgba16.get_quality(req_color_alpha)
|
||||
assert fb_rgba8.get_quality(req_rgb) > fb_rgba16.get_quality(req_rgb)
|
||||
assert fb_rgba8.get_quality(req_rgb_alpha) > fb_rgba16.get_quality(req_rgb_alpha)
|
||||
assert fb_rgba8.get_quality(req_color0) > fb_rgba16.get_quality(req_color0)
|
||||
assert fb_rgba8.get_quality(req_color1) > fb_rgba16.get_quality(req_color1)
|
||||
assert fb_rgba8.get_quality(req_color0_alpha0) > fb_rgba16.get_quality(req_color0_alpha0)
|
||||
assert fb_rgba8.get_quality(req_color1_alpha1) > fb_rgba16.get_quality(req_color1_alpha1)
|
||||
assert fb_rgba8.get_quality(req_rgb0) > fb_rgba16.get_quality(req_rgb0)
|
||||
assert fb_rgba8.get_quality(req_rgb1) > fb_rgba16.get_quality(req_rgb1)
|
||||
assert fb_rgba8.get_quality(req_rgb0_alpha0) > fb_rgba16.get_quality(req_rgb0_alpha0)
|
||||
assert fb_rgba8.get_quality(req_rgb1_alpha1) > fb_rgba16.get_quality(req_rgb1_alpha1)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import sys
|
|||
import pytest
|
||||
from panda3d import core
|
||||
from contextlib import contextmanager
|
||||
import collections
|
||||
|
||||
|
||||
@contextmanager
|
||||
|
|
@ -70,6 +71,15 @@ item_b = core.CollisionSphere((0, 0, 0), 2)
|
|||
item_c = core.CollisionSphere((0, 0, 0), 3)
|
||||
|
||||
|
||||
def test_seq_property_abc():
|
||||
prop = seq_property()
|
||||
assert isinstance(prop, collections.Container)
|
||||
assert isinstance(prop, collections.Sized)
|
||||
assert isinstance(prop, collections.Iterable)
|
||||
assert isinstance(prop, collections.MutableSequence)
|
||||
assert isinstance(prop, collections.Sequence)
|
||||
|
||||
|
||||
def test_seq_property_empty():
|
||||
prop = seq_property()
|
||||
assert not prop
|
||||
|
|
@ -92,6 +102,11 @@ def test_seq_property_iter():
|
|||
assert None not in prop
|
||||
|
||||
|
||||
def test_seq_property_reversed():
|
||||
prop = seq_property(item_a, item_b, item_b)
|
||||
assert tuple(reversed(prop)) == tuple(reversed(tuple(prop)))
|
||||
|
||||
|
||||
def test_seq_property_getitem():
|
||||
prop = seq_property(item_a, item_b, item_b)
|
||||
|
||||
|
|
@ -313,6 +328,88 @@ def test_seq_property_remove():
|
|||
prop.remove("nonsense")
|
||||
|
||||
|
||||
def test_seq_property_append():
|
||||
prop = seq_property(item_a, item_b)
|
||||
|
||||
with constant_refcount(item_c):
|
||||
prop.append(item_c)
|
||||
|
||||
assert tuple(prop) == (item_a, item_b, item_c)
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
prop.append(None)
|
||||
with pytest.raises(TypeError):
|
||||
prop.append("nonsense")
|
||||
|
||||
|
||||
def test_seq_property_insert():
|
||||
# Adding at the beginning
|
||||
prop = seq_property(item_a, item_a, item_a)
|
||||
with constant_refcount(item_b):
|
||||
prop.insert(0, item_b)
|
||||
|
||||
assert tuple(prop) == (item_b, item_a, item_a, item_a)
|
||||
|
||||
# Adding in the middle
|
||||
prop = seq_property(item_a, item_a, item_a)
|
||||
with constant_refcount(item_b):
|
||||
prop.insert(2, item_b)
|
||||
|
||||
assert tuple(prop) == (item_a, item_a, item_b, item_a)
|
||||
|
||||
# Adding at the end
|
||||
prop = seq_property(item_a, item_a, item_a)
|
||||
with constant_refcount(item_b):
|
||||
prop.insert(len(prop), item_b)
|
||||
|
||||
assert tuple(prop) == (item_a, item_a, item_a, item_b)
|
||||
|
||||
# Adding with negative index
|
||||
prop = seq_property(item_a, item_a, item_a)
|
||||
with constant_refcount(item_b):
|
||||
prop.insert(-2, item_b)
|
||||
|
||||
assert tuple(prop) == (item_a, item_b, item_a, item_a)
|
||||
|
||||
# Adding at the end with overflowing index
|
||||
prop = seq_property(item_a, item_a, item_a)
|
||||
with constant_refcount(item_b):
|
||||
prop.insert(2345, item_b)
|
||||
|
||||
assert tuple(prop) == (item_a, item_a, item_a, item_b)
|
||||
|
||||
# Adding at the beginning with negative overflowing index
|
||||
prop = seq_property(item_a, item_a, item_a)
|
||||
with constant_refcount(item_b):
|
||||
prop.insert(-2345, item_b)
|
||||
|
||||
assert tuple(prop) == (item_b, item_a, item_a, item_a)
|
||||
|
||||
|
||||
def test_seq_property_extend():
|
||||
prop = seq_property(item_a)
|
||||
|
||||
with constant_refcount(item_b):
|
||||
prop.extend((item_b, item_c))
|
||||
|
||||
assert tuple(prop) == (item_a, item_b, item_c)
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
prop.extend(None)
|
||||
with pytest.raises(TypeError):
|
||||
prop.extend("nonsense")
|
||||
with pytest.raises(TypeError):
|
||||
prop.extend(item_a)
|
||||
with pytest.raises(TypeError):
|
||||
prop.extend(item_a, item_b)
|
||||
with pytest.raises(TypeError):
|
||||
prop.extend()
|
||||
with pytest.raises(TypeError):
|
||||
prop.extend((item_a, None))
|
||||
with pytest.raises(TypeError):
|
||||
prop.extend(["nonsense"])
|
||||
|
||||
|
||||
# The next tests are for MAKE_MAP_PROPERTY.
|
||||
@pytest.fixture
|
||||
def map_property(**items):
|
||||
|
|
@ -326,6 +423,27 @@ def map_property(**items):
|
|||
return np.tags
|
||||
|
||||
|
||||
def test_map_property_abc():
|
||||
prop = map_property()
|
||||
assert isinstance(prop, collections.Container)
|
||||
assert isinstance(prop, collections.Sized)
|
||||
assert isinstance(prop, collections.Iterable)
|
||||
assert isinstance(prop, collections.MutableMapping)
|
||||
assert isinstance(prop, collections.Mapping)
|
||||
|
||||
|
||||
def test_map_property_empty():
|
||||
prop = map_property()
|
||||
assert not prop
|
||||
assert len(prop) == 0
|
||||
|
||||
with pytest.raises(KeyError):
|
||||
prop.popitem()
|
||||
|
||||
with pytest.raises(KeyError):
|
||||
prop['nonsense']
|
||||
|
||||
|
||||
def test_map_property_getitem():
|
||||
key = 'key'
|
||||
value = 'value'
|
||||
|
|
@ -430,6 +548,24 @@ def test_map_property_pop():
|
|||
assert 'key' not in prop
|
||||
|
||||
|
||||
def test_map_property_popitem():
|
||||
key = 'key'
|
||||
value = 'value'
|
||||
prop = map_property(**{key: value})
|
||||
|
||||
assert prop.popitem() == (key, value)
|
||||
|
||||
with pytest.raises(KeyError):
|
||||
assert prop.popitem()
|
||||
|
||||
|
||||
def test_map_property_clear():
|
||||
prop = map_property(key='value', key2='value2')
|
||||
|
||||
prop.clear()
|
||||
assert len(prop) == 0
|
||||
|
||||
|
||||
def test_map_property_setdefault():
|
||||
prop = map_property(key='value')
|
||||
|
||||
|
|
@ -466,3 +602,24 @@ def test_map_property_update():
|
|||
|
||||
assert prop['key'] == 'value'
|
||||
assert prop['key2'] == 'value2'
|
||||
|
||||
|
||||
def test_map_property_keys():
|
||||
prop = map_property(key='value', key2='value2')
|
||||
|
||||
assert isinstance(prop.keys(), collections.MappingView)
|
||||
assert frozenset(prop.keys()) == frozenset(('key', 'key2'))
|
||||
|
||||
|
||||
def test_map_property_values():
|
||||
prop = map_property(key='value', key2='value2')
|
||||
|
||||
assert isinstance(prop.values(), collections.ValuesView)
|
||||
assert frozenset(prop.values()) == frozenset(('value', 'value2'))
|
||||
|
||||
|
||||
def test_map_property_items():
|
||||
prop = map_property(key='value', key2='value2')
|
||||
|
||||
assert isinstance(prop.items(), collections.MappingView)
|
||||
assert frozenset(prop.items()) == frozenset((('key', 'value'), ('key2', 'value2')))
|
||||
|
|
|
|||
Loading…
Reference in New Issue