37 bool Loader::_file_types_loaded =
false;
45 Loader(
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);
82 filename, options,
this);
93 filename, options, node,
this);
101 load_bam_stream(std::istream &in) {
107 return bam_file.read_node();
114 output(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)";
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);
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 = node->copy_subgraph();
301 bool report_errors = ((options.get_flags() & LoaderOptions::LF_report_errors) != 0 || loader_cat.is_debug());
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";
318 sgr.
premunge(result, RenderState::make_empty());
321 if (result->is_of_type(ModelRoot::get_class_type())) {
326 if (allow_ram_cache) {
331 if ((options.get_flags() & LoaderOptions::LF_allow_instance) == 0) {
332 return model_root->copy_subgraph();
340 if (loader_cat.is_debug()) {
342 <<
"Model " << pathname <<
" not found in cache.\n";
346 if (options.get_flags() & LoaderOptions::LF_cache_only) {
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);
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);
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 = result->copy_subgraph();
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";
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");
The principle public interface to reading and writing Bam disk files.
A node of this type is created automatically at the root of each model file that is loaded.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A basic node of the scene graph or data graph.
get_cache_models
Returns whether model files (e.g.
static void add_model(const Filename &filename, ModelRoot *model)
Adds the indicated already-loaded model to the pool.
set_data
Stores a new data object on the record.
bool open_read(const Filename &bam_filename, bool report_errors=true)
Attempts to open the indicated filename for reading.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A class object that manages a single asynchronous model save request.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
size_t get_num_unique_values() const
Returns the number of unique values in the variable.
Specifies parameters that may be passed to the loader.
This class maintains a cache of Bam and/or Txo objects generated from model files and texture images ...
A hierarchy of directories and files that appears to be one continuous file system,...
static LoaderFileTypeRegistry * get_global_ptr()
Returns a pointer to the global LoaderFileTypeRegistry object.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
An interface for simplifying ("flattening") scene graphs by eliminating unneeded nodes and collapsing...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A convenient class for loading models from disk, in bam or egg format (or any of a number of other fo...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PT(AsyncTask) Loader
Returns a new AsyncTask object suitable for adding to load_async() to start an asynchronous model loa...
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.
void output(std::ostream &out) const
Outputs the Namable.
bool store(BamCacheRecord *record)
Flushes a cache entry to disk.
A base class for all things which can have a name.
bool exists(const Filename &filename) const
Convenience function; returns true if the named file exists.
int extract_words(const string &str, vector_string &words)
Divides the string into a number of words according to whitespace.
The name of a file, such as a texture file or an Egg file.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
An instance of this class is written to the front of a Bam or Txo file to make the file a cached inst...
virtual bool supports_load() const
Returns true if the file type can be used to load files, and load_file() is supported.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_data
Returns a pointer to the data stored in the record, or NULL if there is no data.
virtual bool supports_compressed() const
Returns true if this file type can transparently load compressed files (with a .pz or ....
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...
The AsyncTaskChain is a subset of the AsyncTaskManager.
This class specializes ConfigVariable as an enumerated type.
This class maintains the set of all known LoaderFileTypes in the universe.
std::string get_unique_value(size_t n) const
Returns the nth unique value of the variable.
get_value
Returns the variable's value.
bool is_local() const
Returns true if the filename is local, e.g.
std::string get_extension() const
Returns the file extension.
std::string get_basename() const
Returns the basename part of the filename.
virtual bool supports_save() const
Returns true if the file type can be used to save files, and save_file() is supported.
get_reader
Returns the BamReader in charge of performing the read operations.
This class represents a concrete task performed by an AsyncManager.
LoaderFileType * get_type_from_extension(const std::string &extension)
Determines the type of the file based on the indicated extension (without a leading dot).
set_timestamp
Sets the timestamp of the file on disk that was read for this model.
This is the base class for a family of scene-graph file types that the Loader supports.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is a convenience class to specialize ConfigVariable as an integer type.
This class stores a list of directories that can be searched, in order, to locate a particular file.
A class object that manages a single asynchronous model load request.
TypeHandle is the identifier used to differentiate C++ class types.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
static AsyncTaskManager * get_global_ptr()
Returns a pointer to the global AsyncTaskManager.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::string get_fullpath_wo_extension() const
Returns the full filename–directory and basename parts–except for the extension.
static BamCache * get_global_ptr()
Returns a pointer to the global BamCache object, which is used automatically by the ModelPool and Tex...
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.