mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
support deferred loading of loader file types
This commit is contained in:
parent
e435834ec8
commit
25a599e3c9
@ -31,9 +31,10 @@
|
||||
#include "circBuffer.h"
|
||||
#include "filename.h"
|
||||
#include "load_dso.h"
|
||||
|
||||
#include "string_utils.h"
|
||||
#include "plist.h"
|
||||
#include "pvector.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
@ -310,17 +311,49 @@ load_file_types() {
|
||||
nassertv(load_file_type != (Config::ConfigTable::Symbol *)NULL);
|
||||
|
||||
if (!_file_types_loaded) {
|
||||
|
||||
// When we use GetAll(), we might inadvertently read duplicate
|
||||
// lines. Filter them out with a set.
|
||||
pset<string> already_read;
|
||||
|
||||
Config::ConfigTable::Symbol::iterator ti;
|
||||
for (ti = load_file_type->begin(); ti != load_file_type->end(); ++ti) {
|
||||
Filename dlname = Filename::dso_filename("lib" + (*ti).Val() + ".so");
|
||||
loader_cat.info()
|
||||
<< "loading file type module: " << dlname.to_os_specific() << endl;
|
||||
void *tmp = load_dso(dlname);
|
||||
if (tmp == (void *)NULL) {
|
||||
loader_cat.info()
|
||||
<< "Unable to load: " << load_dso_error() << endl;
|
||||
string param = (*ti).Val();
|
||||
if (already_read.insert(param).second) {
|
||||
vector_string words;
|
||||
extract_words(param, words);
|
||||
|
||||
if (words.size() == 1) {
|
||||
// Exactly one word: load the named library immediately.
|
||||
Filename dlname = Filename::dso_filename("lib" + words[0] + ".so");
|
||||
loader_cat.info()
|
||||
<< "loading file type module: " << dlname.to_os_specific() << endl;
|
||||
void *tmp = load_dso(dlname);
|
||||
if (tmp == (void *)NULL) {
|
||||
loader_cat.info()
|
||||
<< "Unable to load: " << load_dso_error() << endl;
|
||||
}
|
||||
|
||||
} else if (words.size() > 1) {
|
||||
// Multiple words: the first n words are filename extensions,
|
||||
// and the last word is the name of the library to load should
|
||||
// any of those filename extensions be encountered.
|
||||
LoaderFileTypeRegistry *registry = LoaderFileTypeRegistry::get_ptr();
|
||||
size_t num_extensions = words.size() - 1;
|
||||
string library_name = words[num_extensions];
|
||||
|
||||
for (size_t i = 0; i < num_extensions; i++) {
|
||||
string extension = words[i];
|
||||
if (extension[0] == '.') {
|
||||
extension = extension.substr(1);
|
||||
}
|
||||
|
||||
registry->register_deferred_type(extension, library_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_file_types_loaded = true;
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,18 @@ LoaderFileType::
|
||||
~LoaderFileType() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LoaderFileType::get_additional_extensions
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns a space-separated list of extension, in
|
||||
// addition to the one returned by get_extension(), that
|
||||
// are recognized by this loader.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string LoaderFileType::
|
||||
get_additional_extensions() const {
|
||||
return string();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LoaderFileType::load_file
|
||||
// Access: Public, Virtual
|
||||
|
@ -43,6 +43,7 @@ public:
|
||||
|
||||
virtual string get_name() const=0;
|
||||
virtual string get_extension() const=0;
|
||||
virtual string get_additional_extensions() const;
|
||||
|
||||
virtual PT(PandaNode) load_file(const Filename &path, bool report_errors) const;
|
||||
|
||||
|
@ -20,8 +20,8 @@
|
||||
#include "loaderFileType.h"
|
||||
#include "config_pgraph.h"
|
||||
|
||||
#include <string_utils.h>
|
||||
#include <indent.h>
|
||||
#include "string_utils.h"
|
||||
#include "indent.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@ -88,11 +88,41 @@ get_type(int n) const {
|
||||
// the extension matches no known file types.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LoaderFileType *LoaderFileTypeRegistry::
|
||||
get_type_from_extension(const string &extension) const {
|
||||
get_type_from_extension(const string &extension) {
|
||||
string dcextension = downcase(extension);
|
||||
|
||||
Extensions::const_iterator ei;
|
||||
ei = _extensions.find(downcase(extension));
|
||||
ei = _extensions.find(dcextension);
|
||||
if (ei == _extensions.end()) {
|
||||
// Nothing matches that extension.
|
||||
// Nothing matches that extension. Do we have a deferred type?
|
||||
|
||||
DeferredTypes::iterator di;
|
||||
di = _deferred_types.find(dcextension);
|
||||
if (di != _deferred_types.end()) {
|
||||
// We do! Try to load the deferred library on-the-fly. Note
|
||||
// that this is a race condition if we support threaded loading;
|
||||
// this whole function needs to be protected from multiple
|
||||
// entry.
|
||||
Filename dlname = Filename::dso_filename("lib" + (*di).second + ".so");
|
||||
_deferred_types.erase(di);
|
||||
|
||||
loader_cat->info()
|
||||
<< "loading file type module: " << dlname.to_os_specific() << endl;
|
||||
void *tmp = load_dso(dlname);
|
||||
if (tmp == (void *)NULL) {
|
||||
loader_cat->info()
|
||||
<< "Unable to load: " << load_dso_error() << endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Now try again to find the LoaderFileType.
|
||||
ei = _extensions.find(dcextension);
|
||||
}
|
||||
}
|
||||
|
||||
if (ei == _extensions.end()) {
|
||||
// Nothing matches that extension, even after we've checked for a
|
||||
// deferred type description.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -119,6 +149,16 @@ write_types(ostream &out, int indent_level) const {
|
||||
<< " ." << type->get_extension() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (!_deferred_types.empty()) {
|
||||
indent(out, indent_level) << "Also available:";
|
||||
DeferredTypes::const_iterator di;
|
||||
for (di = _deferred_types.begin(); di != _deferred_types.end(); ++di) {
|
||||
const string &extension = (*di).first;
|
||||
out << " ." << extension;
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -130,7 +170,7 @@ void LoaderFileTypeRegistry::
|
||||
register_type(LoaderFileType *type) {
|
||||
// Make sure we haven't already registered this type.
|
||||
if (find(_types.begin(), _types.end(), type) != _types.end()) {
|
||||
loader_cat.warning()
|
||||
loader_cat->info()
|
||||
<< "Attempt to register LoaderFileType " << type->get_name()
|
||||
<< " (" << type->get_type() << ") more than once.\n";
|
||||
return;
|
||||
@ -138,14 +178,77 @@ register_type(LoaderFileType *type) {
|
||||
|
||||
_types.push_back(type);
|
||||
|
||||
string extension = downcase(type->get_extension());
|
||||
Extensions::const_iterator ei;
|
||||
ei = _extensions.find(extension);
|
||||
if (ei != _extensions.end()) {
|
||||
loader_cat.warning()
|
||||
<< "Multiple LoaderFileTypes registered that use the extension "
|
||||
<< extension << "\n";
|
||||
} else {
|
||||
_extensions.insert(Extensions::value_type(extension, type));
|
||||
record_extension(type->get_extension(), type);
|
||||
|
||||
vector_string words;
|
||||
extract_words(type->get_additional_extensions(), words);
|
||||
vector_string::const_iterator wi;
|
||||
for (wi = words.begin(); wi != words.end(); ++wi) {
|
||||
record_extension(*wi, type);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LoaderFileTypeRegistry::register_deferred_type
|
||||
// Access: Public
|
||||
// Description: Records a type associated with a particular extension
|
||||
// to be loaded in the future. The named library will
|
||||
// be dynamically loaded the first time files of this
|
||||
// extension are loaded; presumably this library will
|
||||
// call register_type() when it initializes, thus making
|
||||
// the extension loadable.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void LoaderFileTypeRegistry::
|
||||
register_deferred_type(const string &extension, const string &library) {
|
||||
string dcextension = downcase(extension);
|
||||
|
||||
Extensions::const_iterator ei;
|
||||
ei = _extensions.find(dcextension);
|
||||
if (ei != _extensions.end()) {
|
||||
// We already have a loader for this type; no need to register
|
||||
// another one.
|
||||
loader_cat->info()
|
||||
<< "Attempt to register loader library " << library
|
||||
<< " (" << dcextension << ") when extension is already known.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
DeferredTypes::const_iterator di;
|
||||
di = _deferred_types.find(dcextension);
|
||||
if (di != _deferred_types.end()) {
|
||||
if ((*di).second == library) {
|
||||
loader_cat->info()
|
||||
<< "Attempt to register loader library " << library
|
||||
<< " (" << dcextension << ") more than once.\n";
|
||||
return;
|
||||
} else {
|
||||
loader_cat->info()
|
||||
<< "Multiple libraries registered that use the extension "
|
||||
<< dcextension << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
_deferred_types[dcextension] = library;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LoaderFileTypeRegistry::record_extension
|
||||
// Access: Private
|
||||
// Description: Records a filename extension recognized by a loader
|
||||
// file type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void LoaderFileTypeRegistry::
|
||||
record_extension(const string &extension, LoaderFileType *type) {
|
||||
string dcextension = downcase(extension);
|
||||
Extensions::const_iterator ei;
|
||||
ei = _extensions.find(dcextension);
|
||||
if (ei != _extensions.end()) {
|
||||
loader_cat->info()
|
||||
<< "Multiple LoaderFileTypes registered that use the extension "
|
||||
<< dcextension << "\n";
|
||||
} else {
|
||||
_extensions.insert(Extensions::value_type(dcextension, type));
|
||||
}
|
||||
|
||||
_deferred_types.erase(dcextension);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
#ifndef LOADERFILETYPEREGISTRY_H
|
||||
#define LOADERFILETYPEREGISTRY_H
|
||||
|
||||
#include <pandabase.h>
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "pvector.h"
|
||||
#include "pmap.h"
|
||||
@ -44,11 +44,15 @@ public:
|
||||
int get_num_types() const;
|
||||
LoaderFileType *get_type(int n) const;
|
||||
|
||||
LoaderFileType *get_type_from_extension(const string &extension) const;
|
||||
LoaderFileType *get_type_from_extension(const string &extension);
|
||||
|
||||
void write_types(ostream &out, int indent_level = 0) const;
|
||||
|
||||
void register_type(LoaderFileType *type);
|
||||
void register_deferred_type(const string &extension, const string &library);
|
||||
|
||||
private:
|
||||
void record_extension(const string &extension, LoaderFileType *type);
|
||||
|
||||
private:
|
||||
typedef pvector<LoaderFileType *> Types;
|
||||
@ -57,6 +61,9 @@ private:
|
||||
typedef pmap<string, LoaderFileType *> Extensions;
|
||||
Extensions _extensions;
|
||||
|
||||
typedef pmap<string, string> DeferredTypes;
|
||||
DeferredTypes _deferred_types;
|
||||
|
||||
static LoaderFileTypeRegistry *_global_ptr;
|
||||
};
|
||||
|
||||
|
@ -90,6 +90,18 @@ set_egg_data(EggData *egg_data, bool owns_egg_data) {
|
||||
_owns_egg_data = owns_egg_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SomethingToEggConverter::get_additional_extensions
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns a space-separated list of extension, in
|
||||
// addition to the one returned by get_extension(), that
|
||||
// are recognized by this converter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string SomethingToEggConverter::
|
||||
get_additional_extensions() const {
|
||||
return string();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SomethingToEggConverter::handle_external_reference
|
||||
// Access: Public
|
||||
|
@ -101,6 +101,7 @@ public:
|
||||
|
||||
virtual string get_name() const=0;
|
||||
virtual string get_extension() const=0;
|
||||
virtual string get_additional_extensions() const;
|
||||
|
||||
virtual bool convert_file(const Filename &filename)=0;
|
||||
|
||||
|
@ -151,6 +151,18 @@ get_extension() const {
|
||||
return "mb";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MayaToEggConverter::get_additional_extensions
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns a space-separated list of extension, in
|
||||
// addition to the one returned by get_extension(), that
|
||||
// are recognized by this converter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string MayaToEggConverter::
|
||||
get_additional_extensions() const {
|
||||
return "ma";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MayaToEggConverter::convert_file
|
||||
// Access: Public, Virtual
|
||||
|
@ -70,6 +70,7 @@ public:
|
||||
|
||||
virtual string get_name() const;
|
||||
virtual string get_extension() const;
|
||||
virtual string get_additional_extensions() const;
|
||||
|
||||
virtual bool convert_file(const Filename &filename);
|
||||
bool convert_maya(bool from_selection);
|
||||
|
@ -94,4 +94,21 @@
|
||||
mayaPview.cxx mayaPview.h
|
||||
|
||||
#end lib_target
|
||||
|
||||
|
||||
#begin lib_target
|
||||
#define USE_PACKAGES maya
|
||||
#define TARGET mayaloader
|
||||
#define BUILDING_DLL BUILDING_MISC
|
||||
#define LOCAL_LIBS \
|
||||
mayaegg ptloader converter pandatoolbase
|
||||
#define OTHER_LIBS \
|
||||
egg2pg:c builder:c egg:c pandaegg:m \
|
||||
mathutil:c linmath:c putil:c panda:m \
|
||||
express:c pandaexpress:m \
|
||||
dtoolconfig dtool \
|
||||
$[if $[UNIX_PLATFORM],OpenMayalib]
|
||||
|
||||
#define SOURCES \
|
||||
config_mayaloader.cxx
|
||||
|
||||
#end lib_target
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define TARGET ptloader
|
||||
#define BUILDING_DLL BUILDING_PTLOADER
|
||||
#define LOCAL_LIBS \
|
||||
fltegg flt lwoegg lwo mayaegg converter pandatoolbase
|
||||
fltegg flt lwoegg lwo converter pandatoolbase
|
||||
#define OTHER_LIBS \
|
||||
egg2pg:c builder:c egg:c pandaegg:m \
|
||||
mathutil:c linmath:c putil:c panda:m \
|
||||
@ -11,10 +11,6 @@
|
||||
#define UNIX_SYS_LIBS \
|
||||
m
|
||||
|
||||
// If we've got Maya, link in the Maya libraries.
|
||||
// On second thought, don't. It takes forever to load.
|
||||
//#define USE_PACKAGES maya
|
||||
|
||||
#define SOURCES \
|
||||
config_ptloader.cxx config_ptloader.h \
|
||||
loaderFileTypePandatool.cxx loaderFileTypePandatool.h
|
||||
|
@ -19,9 +19,9 @@
|
||||
#ifndef CONFIG_PTLOADER_H
|
||||
#define CONFIG_PTLOADER_H
|
||||
|
||||
#include <pandatoolbase.h>
|
||||
#include "pandatoolbase.h"
|
||||
|
||||
#include <dconfig.h>
|
||||
#include "dconfig.h"
|
||||
|
||||
ConfigureDecl(config_ptloader, EXPCL_PTLOADER, EXPTP_PTLOADER);
|
||||
|
||||
|
@ -66,6 +66,18 @@ get_extension() const {
|
||||
return _converter->get_extension();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LoaderFileTypePandatool::get_additional_extensions
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns a space-separated list of extension, in
|
||||
// addition to the one returned by get_extension(), that
|
||||
// are recognized by this converter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string LoaderFileTypePandatool::
|
||||
get_additional_extensions() const {
|
||||
return _converter->get_additional_extensions();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LoaderFileTypePandatool::resolve_filename
|
||||
// Access: Public, Virtual
|
||||
|
@ -39,6 +39,7 @@ public:
|
||||
|
||||
virtual string get_name() const;
|
||||
virtual string get_extension() const;
|
||||
virtual string get_additional_extensions() const;
|
||||
|
||||
virtual void resolve_filename(Filename &path) const;
|
||||
virtual PT(PandaNode) load_file(const Filename &path, bool report_errors) const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user