diff --git a/panda/src/pgraph/loaderFileTypeRegistry.cxx b/panda/src/pgraph/loaderFileTypeRegistry.cxx index c7df6731eb..2a8d321323 100644 --- a/panda/src/pgraph/loaderFileTypeRegistry.cxx +++ b/panda/src/pgraph/loaderFileTypeRegistry.cxx @@ -113,6 +113,41 @@ register_deferred_type(const string &extension, const string &library) { _deferred_types[dcextension] = library; } +/** + * Removes a type previously registered using register_type. + */ +void LoaderFileTypeRegistry:: +unregister_type(LoaderFileType *type) { + Types::iterator it = find(_types.begin(), _types.end(), type); + if (it == _types.end()) { + if (loader_cat.is_debug()) { + loader_cat.debug() + << "Attempt to unregister LoaderFileType " << type->get_name() + << " (" << type->get_type() << "), which was not registered.\n"; + } + return; + } + + _types.erase(it); + + { + std::string dcextension = downcase(type->get_extension()); + Extensions::iterator ei = _extensions.find(dcextension); + if (ei != _extensions.end() && ei->second == type) { + _extensions.erase(ei); + } + } + + vector_string words; + extract_words(type->get_additional_extensions(), words); + for (const std::string &word : words) { + Extensions::iterator ei = _extensions.find(downcase(word)); + if (ei != _extensions.end() && ei->second == type) { + _extensions.erase(ei); + } + } +} + /** * Returns the total number of types registered. */ diff --git a/panda/src/pgraph/loaderFileTypeRegistry.h b/panda/src/pgraph/loaderFileTypeRegistry.h index 2a4c569329..cccb3af333 100644 --- a/panda/src/pgraph/loaderFileTypeRegistry.h +++ b/panda/src/pgraph/loaderFileTypeRegistry.h @@ -35,10 +35,14 @@ public: void register_type(LoaderFileType *type); void register_deferred_type(const std::string &extension, const std::string &library); + void unregister_type(LoaderFileType *type); + PUBLISHED: EXTENSION(void register_type(PyObject *type)); EXTENSION(void register_deferred_type(PyObject *entry_point)); + EXTENSION(void unregister_type(PyObject *type)); + int get_num_types() const; LoaderFileType *get_type(int n) const; MAKE_SEQ(get_types, get_num_types, get_type); diff --git a/panda/src/pgraph/loaderFileTypeRegistry_ext.cxx b/panda/src/pgraph/loaderFileTypeRegistry_ext.cxx index 0e1df98d02..20450e9195 100644 --- a/panda/src/pgraph/loaderFileTypeRegistry_ext.cxx +++ b/panda/src/pgraph/loaderFileTypeRegistry_ext.cxx @@ -17,6 +17,8 @@ #include "pythonLoaderFileType.h" +extern struct Dtool_PyTypedObject Dtool_LoaderFileType; + /** * Registers a loader file type that is implemented in Python. */ @@ -64,4 +66,50 @@ register_deferred_type(PyObject *entry_point) { _this->register_type(loader); } +/** + * If the given loader type is registered, unregisters it. + */ +void Extension:: +unregister_type(PyObject *type) { + // Are we passing in a C++ file type object? + LoaderFileType *extracted_type; + if (DtoolInstance_GetPointer(type, extracted_type, Dtool_LoaderFileType)) { + _this->unregister_type(extracted_type); + return; + } + + // If not, we may be passing in a Python file type. + PyObject *load_func = PyObject_GetAttrString(type, "load_file"); + PyObject *save_func = PyObject_GetAttrString(type, "save_file"); + PyErr_Clear(); + + if (load_func == nullptr && save_func == nullptr) { + Dtool_Raise_TypeError("expected loader type"); + return; + } + + // Keep looping until we've removed all instances of it. + bool found_any; + do { + found_any = false; + size_t num_types = _this->get_num_types(); + for (size_t i = 0; i < num_types; ++i) { + LoaderFileType *type = _this->get_type(i); + if (type->is_of_type(PythonLoaderFileType::get_class_type())) { + PythonLoaderFileType *python_type = (PythonLoaderFileType *)type; + if (python_type->_load_func == load_func && + python_type->_save_func == save_func) { + _this->unregister_type(python_type); + delete python_type; + found_any = true; + break; + } + } + } + } while (found_any); + + Py_XDECREF(load_func); + Py_XDECREF(save_func); +} + #endif diff --git a/panda/src/pgraph/loaderFileTypeRegistry_ext.h b/panda/src/pgraph/loaderFileTypeRegistry_ext.h index 63eee84f72..9c9815c20d 100644 --- a/panda/src/pgraph/loaderFileTypeRegistry_ext.h +++ b/panda/src/pgraph/loaderFileTypeRegistry_ext.h @@ -31,6 +31,8 @@ class Extension : public ExtensionBase; + public: static TypeHandle get_class_type() { return _type_handle;