37bool Loader::_file_types_loaded =
false;
38PT(
Loader) Loader::_global_ptr;
45Loader(
const string &name) :
51 if (_task_manager->find_task_chain(_task_chain) ==
nullptr) {
52 PT(
AsyncTaskChain) chain = _task_manager->make_task_chain(_task_chain);
55 (
"loader-num-threads", 1,
56 PRC_DESC(
"The number of threads that will be started by the Loader class "
57 "to load models asynchronously. These threads will only be "
58 "started if the asynchronous interface is used, and if threading "
59 "support is compiled into Panda. The default is one thread, "
60 "which allows models to be loaded one at a time in a single "
61 "asychronous thread. You can set this higher, particularly if "
62 "you have many CPU's available, to allow loading multiple models "
64 chain->set_num_threads(loader_num_threads);
67 (
"loader-thread-priority", TP_low,
68 PRC_DESC(
"The default thread priority to assign to the threads created "
69 "for asynchronous loading. The default is 'low'; you may "
70 "also specify 'normal', 'high', or 'urgent'."));
71 chain->set_thread_priority(loader_thread_priority);
81 return new ModelLoadRequest(
string(
"model:")+filename.
get_basename(),
82 filename, options,
this);
93 filename, options, node,
this);
114output(std::ostream &out)
const {
115 out << get_type() <<
" " << get_name();
117 int num_tasks = _task_manager->make_task_chain(_task_chain)->get_num_tasks();
118 if (num_tasks != 0) {
119 out <<
" (" << num_tasks <<
" models pending)";
132 Filename this_filename(filename);
133 LoaderOptions this_options(options);
135 bool report_errors = (this_options.get_flags() & LoaderOptions::LF_report_errors) != 0;
137 string extension = this_filename.get_extension();
138 if (extension.empty()) {
141 this_filename = this_filename.get_fullpath() + default_model_extension.
get_value();
142 extension = this_filename.get_extension();
145 bool compressed =
false;
147 if (extension ==
"pz" || extension ==
"gz") {
149 extension = Filename(this_filename.get_basename_wo_extension()).get_extension();
153 if (extension.empty()) {
156 <<
"Cannot load " << this_filename
157 <<
" without filename extension. Loading of model filenames with an "
158 "implicit extension is deprecated in Panda3D. Please "
159 "correct the filename reference. If necessary, you may put the "
160 "line \"default-model-extension .bam\" or \"default-model-extension .egg\" "
161 "in your Config.prc to globally assume a particular model "
162 "filename extension.\n";
171 if (requested_type !=
nullptr) {
175 << requested_type->get_name() <<
" file type (."
176 << extension <<
") does not support loading.\n";
182 << requested_type->get_name() <<
" file type (."
183 << extension <<
") does not support in-line compression.\n";
189 bool search = (this_options.get_flags() & LoaderOptions::LF_search) != 0;
197 this_options.set_flags(this_options.get_flags() & ~LoaderOptions::LF_search);
203 DSearchPath model_path(get_model_path());
204 int num_dirs = model_path.get_num_directories();
205 for (
int i = 0; i < num_dirs; ++i) {
206 Filename pathname(model_path.get_directory(i), this_filename);
207 PT(PandaNode) result = try_load_file(pathname, this_options,
209 if (result !=
nullptr) {
215 bool any_exist =
false;
216 for (
int i = 0; i < num_dirs; ++i) {
217 Filename pathname(model_path.get_directory(i), this_filename);
218 if (vfs->
exists(pathname)) {
225 if (requested_type ==
nullptr) {
227 <<
"Extension of file " << this_filename
228 <<
" is unrecognized; cannot load.\n";
229 loader_cat.error(
false)
230 <<
"Currently known scene file types are:\n";
231 reg->
write(loader_cat.error(
false), 2);
234 <<
"Couldn't load file " << this_filename
235 <<
": all matching files on model path invalid "
236 <<
"(the model path is currently: \"" << get_model_path() <<
"\")\n";
239 <<
"Couldn't load file " << this_filename
240 <<
": not found on model path "
241 <<
"(currently: \"" << get_model_path() <<
"\")\n";
248 PT(PandaNode) result = try_load_file(this_filename, this_options, requested_type);
249 if (result !=
nullptr) {
253 if (vfs->
exists(this_filename)) {
254 if (requested_type ==
nullptr) {
256 <<
"Extension of file " << this_filename
257 <<
" is unrecognized; cannot load.\n";
258 loader_cat.error(
false)
259 <<
"Currently known scene file types are:\n";
260 reg->
write(loader_cat.error(
false), 2);
263 <<
"Couldn't load file " << this_filename <<
": invalid.\n";
266 <<
"Couldn't load file " << this_filename <<
": does not exist.\n";
282 bool allow_ram_cache =
283 ((options.get_flags() & LoaderOptions::LF_no_ram_cache) == 0);
285 if (allow_ram_cache) {
288 if (node !=
nullptr) {
289 if ((options.get_flags() & LoaderOptions::LF_allow_instance) == 0) {
290 if (loader_cat.is_debug()) {
292 <<
"Model " << pathname <<
" found in ModelPool.\n";
295 node = NodePath(node).copy_to(NodePath()).node();
301 bool report_errors = ((options.get_flags() & LoaderOptions::LF_report_errors) != 0 || loader_cat.is_debug());
303 PT(BamCacheRecord) record;
305 (options.get_flags() & LoaderOptions::LF_no_disk_cache) == 0) {
307 record = cache->lookup(pathname,
"bam");
308 if (record !=
nullptr) {
309 if (record->has_data()) {
312 <<
"Model " << pathname <<
" found in disk cache.\n";
314 PT(PandaNode) result = DCAST(PandaNode, record->
get_data());
317 SceneGraphReducer sgr;
318 sgr.
premunge(result, RenderState::make_empty());
321 if (result->is_of_type(ModelRoot::get_class_type())) {
322 ModelRoot *model_root = DCAST(ModelRoot, result.p());
326 if (allow_ram_cache) {
331 if ((options.get_flags() & LoaderOptions::LF_allow_instance) == 0) {
332 return NodePath(model_root).copy_to(NodePath()).node();
340 if (loader_cat.is_debug()) {
342 <<
"Model " << pathname <<
" not found in cache.\n";
346 if (options.get_flags() & LoaderOptions::LF_cache_only) {
352 PT(PandaNode) result;
353 if (requested_type !=
nullptr) {
354 result = requested_type->load_file(pathname, options, record);
356 if (result !=
nullptr) {
357 if (record !=
nullptr) {
360 cache->
store(record);
365 Filename pathname_bam = pathname;
366 if (extension ==
"pz" || extension ==
"gz") {
371 if (extension ==
"bam") {
375 pathname_bam +=
".bam";
378 if (!bam_file.
open_read(pathname_bam, report_errors)) {
382 bam_file.
get_reader()->set_loader_options(options);
383 result = bam_file.
read_node(report_errors);
385 nassertr_always(result !=
nullptr && result->is_of_type(ModelRoot::get_class_type()),
nullptr);
391 SceneGraphReducer sgr;
392 sgr.
premunge(result, RenderState::make_empty());
395 if (allow_ram_cache && result->is_of_type(ModelRoot::get_class_type())) {
400 if ((options.get_flags() & LoaderOptions::LF_allow_instance) == 0) {
401 result = NodePath(result).copy_to(NodePath()).node();
415 Filename this_filename(filename);
416 LoaderOptions this_options(options);
418 bool report_errors = (this_options.get_flags() & LoaderOptions::LF_report_errors) != 0;
420 string extension = this_filename.get_extension();
421 if (extension.empty()) {
424 this_filename = this_filename.get_fullpath() + default_model_extension.
get_value();
425 extension = this_filename.get_extension();
428 bool compressed =
false;
430 if (extension ==
"pz" || extension ==
"gz") {
432 extension = Filename(this_filename.get_basename_wo_extension()).get_extension();
436 if (extension.empty()) {
439 <<
"Cannot save " << this_filename
440 <<
" without filename extension.\n";
446 LoaderFileType *requested_type =
449 if (requested_type ==
nullptr) {
452 <<
"Extension of file " << this_filename
453 <<
" is unrecognized; cannot save.\n";
454 loader_cat.error(
false)
455 <<
"Currently known scene file types are:\n";
456 reg->
write(loader_cat.error(
false), 2);
463 << requested_type->get_name() <<
" file type (."
464 << extension <<
") does not support saving.\n";
471 << requested_type->get_name() <<
" file type (."
472 << extension <<
") does not support in-line compression.\n";
477 bool result = try_save_file(this_filename, this_options, node, requested_type);
481 <<
"Couldn't save file " << this_filename <<
".\n";
495 return requested_type->save_file(pathname, options, node);
505 if (!_file_types_loaded) {
508 for (
int i = 0; i < num_unique_values; i++) {
514 if (words.size() == 1) {
516 string name = words[0];
517 Filename dlname = Filename::dso_filename(
"lib" + name +
".so");
519 <<
"loading file type module: " << name << std::endl;
520 void *tmp = load_dso(get_plugin_path().get_value(), dlname);
521 if (tmp ==
nullptr) {
524 <<
": " << load_dso_error() << std::endl;
525 }
else if (loader_cat.is_debug()) {
527 <<
"done loading file type module: " << name << std::endl;
530 }
else if (words.size() > 1) {
535 size_t num_extensions = words.size() - 1;
536 string library_name = words[num_extensions];
538 for (
size_t i = 0; i < num_extensions; i++) {
539 string extension = words[i];
540 if (extension[0] ==
'.') {
541 extension = extension.substr(1);
549 _file_types_loaded =
true;
558 nassertv(_global_ptr ==
nullptr);
560 _global_ptr =
new Loader(
"loader");
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The AsyncTaskChain is a subset of the AsyncTaskManager.
static AsyncTaskManager * get_global_ptr()
Returns a pointer to the global AsyncTaskManager.
This class represents a concrete task performed by an AsyncManager.
get_data
Returns a pointer to the data stored in the record, or NULL if there is no data.
set_data
Stores a new data object on the record.
get_cache_models
Returns whether model files (e.g.
bool store(BamCacheRecord *record)
Flushes a cache entry to disk.
static BamCache * get_global_ptr()
Returns a pointer to the global BamCache object, which is used automatically by the ModelPool and Tex...
The principle public interface to reading and writing Bam disk files.
PointerTo< PandaNode > read_node(bool report_errors=true)
Although the bam file format is general enough to store a list of objects of arbitrary type,...
bool open_read(const Filename &bam_filename, bool report_errors=true)
Attempts to open the indicated filename for reading.
get_reader
Returns the BamReader in charge of performing the read operations.
This class specializes ConfigVariable as an enumerated type.
This is a convenience class to specialize ConfigVariable as an integer type.
std::string get_unique_value(size_t n) const
Returns the nth unique value of the variable.
size_t get_num_unique_values() const
Returns the number of unique values in the variable.
get_value
Returns the variable's value.
The name of a file, such as a texture file or an Egg file.
std::string get_basename() const
Returns the basename part of the filename.
std::string get_fullpath_wo_extension() const
Returns the full filename–directory and basename parts–except for the extension.
std::string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
std::string get_extension() const
Returns the file extension.
bool is_local() const
Returns true if the filename is local, e.g.
void write(std::ostream &out, int indent_level=0) const
Writes a list of supported file types to the indicated output stream, one per line.
static LoaderFileTypeRegistry * get_global_ptr()
Returns a pointer to the global LoaderFileTypeRegistry object.
LoaderFileType * get_type_from_extension(const std::string &extension)
Determines the type of the file based on the indicated extension (without a leading dot).
void register_deferred_type(const std::string &extension, const std::string &library)
Records a type associated with a particular extension to be loaded in the future.
This is the base class for a family of scene-graph file types that the Loader supports.
virtual bool supports_compressed() const
Returns true if this file type can transparently load compressed files (with a .pz or ....
virtual bool supports_save() const
Returns true if the file type can be used to save files, and save_file() is supported.
virtual bool supports_load() const
Returns true if the file type can be used to load files, and load_file() is supported.
Specifies parameters that may be passed to the loader.
A convenient class for loading models from disk, in bam or egg format (or any of a number of other fo...
PointerTo< AsyncTask > make_async_save_request(const Filename &filename, const LoaderOptions &options, PandaNode *node)
Returns a new AsyncTask object suitable for adding to save_async() to start an asynchronous model sav...
PointerTo< AsyncTask > make_async_request(const Filename &filename, const LoaderOptions &options=LoaderOptions())
Returns a new AsyncTask object suitable for adding to load_async() to start an asynchronous model loa...
PointerTo< PandaNode > load_bam_stream(std::istream &in)
Attempts to read a bam file from the indicated stream and return the scene graph defined there.
static void add_model(const Filename &filename, ModelRoot *model)
Adds the indicated already-loaded model to the pool.
static ModelRoot * get_model(const Filename &filename, bool verify)
Returns the model that has already been previously loaded, or NULL otherwise.
set_fullpath
Sets the full pathname of the model represented by this node, as found on disk.
set_timestamp
Sets the timestamp of the file on disk that was read for this model.
A class object that manages a single asynchronous model save request.
A base class for all things which can have a name.
A basic node of the scene graph or data graph.
void premunge(PandaNode *root, const RenderState *initial_state)
Walks the scene graph rooted at this node and below, and uses the indicated GSG to premunge every Geo...
TypeHandle is the identifier used to differentiate C++ class types.
bool exists(const Filename &filename) const
Convenience function; returns true if the named file exists in the virtual file system hierarchy.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int extract_words(const string &str, vector_string &words)
Divides the string into a number of words according to whitespace.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.