Panda3D
loader.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file loader.cxx
10  * @author mike
11  * @date 1997-01-09
12  */
13 
14 #include "loader.h"
15 #include "loaderFileType.h"
16 #include "loaderFileTypeRegistry.h"
17 #include "config_pgraph.h"
18 #include "modelPool.h"
19 #include "modelLoadRequest.h"
20 #include "modelSaveRequest.h"
21 #include "config_express.h"
22 #include "config_putil.h"
23 #include "virtualFileSystem.h"
24 #include "filename.h"
25 #include "load_dso.h"
26 #include "string_utils.h"
27 #include "bamCache.h"
28 #include "bamCacheRecord.h"
29 #include "sceneGraphReducer.h"
30 #include "renderState.h"
31 #include "bamFile.h"
32 #include "configVariableInt.h"
33 #include "configVariableEnum.h"
34 
35 using std::string;
36 
37 bool Loader::_file_types_loaded = false;
38 PT(Loader) Loader::_global_ptr;
39 TypeHandle Loader::_type_handle;
40 
41 /**
42  *
43  */
44 Loader::
45 Loader(const string &name) :
46  Namable(name)
47 {
48  _task_manager = AsyncTaskManager::get_global_ptr();
49  _task_chain = name;
50 
51  if (_task_manager->find_task_chain(_task_chain) == nullptr) {
52  PT(AsyncTaskChain) chain = _task_manager->make_task_chain(_task_chain);
53 
54  ConfigVariableInt loader_num_threads
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 "
63  "simultaneously."));
64  chain->set_num_threads(loader_num_threads);
65 
66  ConfigVariableEnum<ThreadPriority> loader_thread_priority
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);
72  }
73 }
74 
75 /**
76  * Returns a new AsyncTask object suitable for adding to load_async() to start
77  * an asynchronous model load.
78  */
79 PT(AsyncTask) Loader::
80 make_async_request(const Filename &filename, const LoaderOptions &options) {
81  return new ModelLoadRequest(string("model:")+filename.get_basename(),
82  filename, options, this);
83 }
84 
85 /**
86  * Returns a new AsyncTask object suitable for adding to save_async() to start
87  * an asynchronous model save.
88  */
89 PT(AsyncTask) Loader::
90 make_async_save_request(const Filename &filename, const LoaderOptions &options,
91  PandaNode *node) {
92  return new ModelSaveRequest(string("model_save:")+filename.get_basename(),
93  filename, options, node, this);
94 }
95 
96 /**
97  * Attempts to read a bam file from the indicated stream and return the scene
98  * graph defined there.
99  */
100 PT(PandaNode) Loader::
101 load_bam_stream(std::istream &in) {
102  BamFile bam_file;
103  if (!bam_file.open_read(in)) {
104  return nullptr;
105  }
106 
107  return bam_file.read_node();
108 }
109 
110 /**
111  *
112  */
113 void Loader::
114 output(std::ostream &out) const {
115  out << get_type() << " " << get_name();
116 
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)";
120  }
121 }
122 
123 /**
124  * Loads a single scene graph file, if possible. Returns the Node that is the
125  * root of the file, or NULL if the file cannot be loaded.
126  *
127  * If search is true, the file is searched for along the model path;
128  * otherwise, only the exact filename is loaded.
129  */
130 PT(PandaNode) Loader::
131 load_file(const Filename &filename, const LoaderOptions &options) const {
132  Filename this_filename(filename);
133  LoaderOptions this_options(options);
134 
135  bool report_errors = (this_options.get_flags() & LoaderOptions::LF_report_errors) != 0;
136 
137  string extension = this_filename.get_extension();
138  if (extension.empty()) {
139  // If the filename has no filename extension, append the default extension
140  // specified in the Config file.
141  this_filename = this_filename.get_fullpath() + default_model_extension.get_value();
142  extension = this_filename.get_extension();
143  }
144 
145  bool compressed = false;
146 #ifdef HAVE_ZLIB
147  if (extension == "pz" || extension == "gz") {
148  compressed = true;
149  extension = Filename(this_filename.get_basename_wo_extension()).get_extension();
150  }
151 #endif // HAVE_ZLIB
152 
153  if (extension.empty()) {
154  if (report_errors) {
155  loader_cat.error()
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";
163  }
164  return nullptr;
165  }
166 
168  LoaderFileType *requested_type = reg->get_type_from_extension(extension);
169  // requested_type may be nullptr at this point, because there's still a
170  // chance we can load it via the model-cache or by adding .bam to the end.
171  if (requested_type != nullptr) {
172  if (!requested_type->supports_load()) {
173  if (report_errors) {
174  loader_cat.error()
175  << requested_type->get_name() << " file type (."
176  << extension << ") does not support loading.\n";
177  }
178  return nullptr;
179  } else if (compressed && !requested_type->supports_compressed()) {
180  if (report_errors) {
181  loader_cat.error()
182  << requested_type->get_name() << " file type (."
183  << extension << ") does not support in-line compression.\n";
184  }
185  return nullptr;
186  }
187  }
188 
189  bool search = (this_options.get_flags() & LoaderOptions::LF_search) != 0;
190  if (!filename.is_local()) {
191  // If we have a global filename, we don't search the model path.
192  search = false;
193  }
194 
195  // Now that we've decided whether to search for the file, don't try to
196  // search again.
197  this_options.set_flags(this_options.get_flags() & ~LoaderOptions::LF_search);
198 
200 
201  if (search) {
202  // Look for the file along the model path.
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,
208  requested_type);
209  if (result != nullptr) {
210  return result;
211  }
212  }
213 
214  if (report_errors) {
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)) {
219  any_exist = true;
220  break;
221  }
222  }
223 
224  if (any_exist) {
225  if (requested_type == nullptr) {
226  loader_cat.error()
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);
232  }
233  loader_cat.error()
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";
237  } else {
238  loader_cat.error()
239  << "Couldn't load file " << this_filename
240  << ": not found on model path "
241  << "(currently: \"" << get_model_path() << "\")\n";
242  }
243  }
244 
245  } else {
246  // Look for the file only where it is.
248  PT(PandaNode) result = try_load_file(this_filename, this_options, requested_type);
249  if (result != nullptr) {
250  return result;
251  }
252  if (report_errors) {
253  if (vfs->exists(this_filename)) {
254  if (requested_type == nullptr) {
255  loader_cat.error()
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);
261  }
262  loader_cat.error()
263  << "Couldn't load file " << this_filename << ": invalid.\n";
264  } else {
265  loader_cat.error()
266  << "Couldn't load file " << this_filename << ": does not exist.\n";
267  }
268  }
269  }
270  return nullptr;
271 }
272 
273 /**
274  * The implementatin of load_file(), this tries a single possible file without
275  * searching further along the path.
276  */
277 PT(PandaNode) Loader::
278 try_load_file(const Filename &pathname, const LoaderOptions &options,
279  LoaderFileType *requested_type) const {
281 
282  bool allow_ram_cache =
283  ((options.get_flags() & LoaderOptions::LF_no_ram_cache) == 0);
284 
285  if (allow_ram_cache) {
286  // If we're allowing a RAM cache, use the ModelPool to load the file.
287  PT(PandaNode) node = ModelPool::get_model(pathname, true);
288  if (node != nullptr) {
289  if ((options.get_flags() & LoaderOptions::LF_allow_instance) == 0) {
290  if (loader_cat.is_debug()) {
291  loader_cat.debug()
292  << "Model " << pathname << " found in ModelPool.\n";
293  }
294  // But return a deep copy of the shared model.
295  node = node->copy_subgraph();
296  }
297  return node;
298  }
299  }
300 
301  bool report_errors = ((options.get_flags() & LoaderOptions::LF_report_errors) != 0 || loader_cat.is_debug());
302 
303  PT(BamCacheRecord) record;
304  if (cache->get_cache_models() &&
305  (options.get_flags() & LoaderOptions::LF_no_disk_cache) == 0) {
306  // See if the model can be found in the on-disk cache, if it is active.
307  record = cache->lookup(pathname, "bam");
308  if (record != nullptr) {
309  if (record->has_data()) {
310  if (report_errors) {
311  loader_cat.info()
312  << "Model " << pathname << " found in disk cache.\n";
313  }
314  PT(PandaNode) result = DCAST(PandaNode, record->get_data());
315 
316  if (premunge_data) {
317  SceneGraphReducer sgr;
318  sgr.premunge(result, RenderState::make_empty());
319  }
320 
321  if (result->is_of_type(ModelRoot::get_class_type())) {
322  ModelRoot *model_root = DCAST(ModelRoot, result.p());
323  model_root->set_fullpath(pathname);
324  model_root->set_timestamp(record->get_source_timestamp());
325 
326  if (allow_ram_cache) {
327  // Store the loaded model in the RAM cache, and make sure we
328  // return a copy so that this node can be modified independently
329  // from the RAM cached version.
330  ModelPool::add_model(pathname, model_root);
331  if ((options.get_flags() & LoaderOptions::LF_allow_instance) == 0) {
332  return model_root->copy_subgraph();
333  }
334  }
335  }
336  return result;
337  }
338  }
339 
340  if (loader_cat.is_debug()) {
341  loader_cat.debug()
342  << "Model " << pathname << " not found in cache.\n";
343  }
344  }
345 
346  if (options.get_flags() & LoaderOptions::LF_cache_only) {
347  // We're not allowed to read from disk.
348  return nullptr;
349  }
350 
351  // Load the model from disk.
352  PT(PandaNode) result;
353  if (requested_type != nullptr) {
354  result = requested_type->load_file(pathname, options, record);
355  }
356  if (result != nullptr) {
357  if (record != nullptr) {
358  // Store the loaded model in the model cache.
359  record->set_data(result);
360  cache->store(record);
361  }
362  } else {
363  // Do we have the same filename, but with .bam appended to the end?
364  string extension = pathname.get_extension();
365  Filename pathname_bam = pathname;
366  if (extension == "pz" || extension == "gz") {
367  // Strip .pz/.gz, so that model.egg.pz -> model.egg.bam
368  extension = pathname_bam.get_extension();
369  pathname_bam = pathname_bam.get_fullpath_wo_extension();
370  }
371  if (extension == "bam") {
372  // Don't try to load .bam.bam files, that is just silly.
373  return nullptr;
374  }
375  pathname_bam += ".bam";
376 
377  BamFile bam_file;
378  if (!bam_file.open_read(pathname_bam, report_errors)) {
379  return nullptr;
380  }
381 
382  bam_file.get_reader()->set_loader_options(options);
383  result = bam_file.read_node(report_errors);
384 
385  nassertr_always(result != nullptr && result->is_of_type(ModelRoot::get_class_type()), nullptr);
386  // We don't bother with the model-cache here, since this .bam file is
387  // already effectively a cached version of the original model.
388  }
389 
390  if (premunge_data) {
391  SceneGraphReducer sgr;
392  sgr.premunge(result, RenderState::make_empty());
393  }
394 
395  if (allow_ram_cache && result->is_of_type(ModelRoot::get_class_type())) {
396  // Store the loaded model in the RAM cache, and make sure we return a
397  // copy so that this node can be modified independently from the RAM
398  // cached version.
399  ModelPool::add_model(pathname, DCAST(ModelRoot, result.p()));
400  if ((options.get_flags() & LoaderOptions::LF_allow_instance) == 0) {
401  result = result->copy_subgraph();
402  }
403  }
404 
405  return result;
406 }
407 
408 /**
409  * Saves a scene graph to a single file, if possible. The file type written
410  * is implicit in the filename extension.
411  */
412 bool Loader::
413 save_file(const Filename &filename, const LoaderOptions &options,
414  PandaNode *node) const {
415  Filename this_filename(filename);
416  LoaderOptions this_options(options);
417 
418  bool report_errors = (this_options.get_flags() & LoaderOptions::LF_report_errors) != 0;
419 
420  string extension = this_filename.get_extension();
421  if (extension.empty()) {
422  // If the filename has no filename extension, append the default extension
423  // specified in the Config file.
424  this_filename = this_filename.get_fullpath() + default_model_extension.get_value();
425  extension = this_filename.get_extension();
426  }
427 
428  bool compressed = false;
429 #ifdef HAVE_ZLIB
430  if (extension == "pz" || extension == "gz") {
431  compressed = true;
432  extension = Filename(this_filename.get_basename_wo_extension()).get_extension();
433  }
434 #endif // HAVE_ZLIB
435 
436  if (extension.empty()) {
437  if (report_errors) {
438  loader_cat.error()
439  << "Cannot save " << this_filename
440  << " without filename extension.\n";
441  }
442  return false;
443  }
444 
446  LoaderFileType *requested_type =
447  reg->get_type_from_extension(extension);
448 
449  if (requested_type == nullptr) {
450  if (report_errors) {
451  loader_cat.error()
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);
457  }
458  return false;
459 
460  } else if (!requested_type->supports_save()) {
461  if (report_errors) {
462  loader_cat.error()
463  << requested_type->get_name() << " file type (."
464  << extension << ") does not support saving.\n";
465  }
466  return false;
467 
468  } else if (compressed && !requested_type->supports_compressed()) {
469  if (report_errors) {
470  loader_cat.error()
471  << requested_type->get_name() << " file type (."
472  << extension << ") does not support in-line compression.\n";
473  }
474  return false;
475  }
476 
477  bool result = try_save_file(this_filename, this_options, node, requested_type);
478  if (!result) {
479  if (report_errors) {
480  loader_cat.error()
481  << "Couldn't save file " << this_filename << ".\n";
482  }
483  }
484 
485  return result;
486 }
487 
488 /**
489  * The implementation of save_file(), this tries to write a specific file
490  * type.
491  */
492 bool Loader::
493 try_save_file(const Filename &pathname, const LoaderOptions &options,
494  PandaNode *node, LoaderFileType *requested_type) const {
495  return requested_type->save_file(pathname, options, node);
496 }
497 
498 /**
499  * Loads up all of the dynamic libraries named in a load-file-type Configure
500  * variable. Presumably this will make the various file types available for
501  * runtime loading.
502  */
503 void Loader::
504 load_file_types() {
505  if (!_file_types_loaded) {
506  int num_unique_values = load_file_type.get_num_unique_values();
507 
508  for (int i = 0; i < num_unique_values; i++) {
509  string param = load_file_type.get_unique_value(i);
510 
511  vector_string words;
512  extract_words(param, words);
513 
514  if (words.size() == 1) {
515  // Exactly one word: load the named library immediately.
516  string name = words[0];
517  Filename dlname = Filename::dso_filename("lib" + name + ".so");
518  loader_cat.info()
519  << "loading file type module: " << name << std::endl;
520  void *tmp = load_dso(get_plugin_path().get_value(), dlname);
521  if (tmp == nullptr) {
522  loader_cat.warning()
523  << "Unable to load " << dlname.to_os_specific()
524  << ": " << load_dso_error() << std::endl;
525  } else if (loader_cat.is_debug()) {
526  loader_cat.debug()
527  << "done loading file type module: " << name << std::endl;
528  }
529 
530  } else if (words.size() > 1) {
531  // Multiple words: the first n words are filename extensions, and the
532  // last word is the name of the library to load should any of those
533  // filename extensions be encountered.
535  size_t num_extensions = words.size() - 1;
536  string library_name = words[num_extensions];
537 
538  for (size_t i = 0; i < num_extensions; i++) {
539  string extension = words[i];
540  if (extension[0] == '.') {
541  extension = extension.substr(1);
542  }
543 
544  registry->register_deferred_type(extension, library_name);
545  }
546  }
547  }
548 
549  _file_types_loaded = true;
550  }
551 }
552 
553 /**
554  * Called once per application to create the global loader object.
555  */
556 void Loader::
557 make_global_ptr() {
558  nassertv(_global_ptr == nullptr);
559 
560  _global_ptr = new Loader("loader");
561 }
bamCache.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Filename::get_fullpath_wo_extension
std::string get_fullpath_wo_extension() const
Returns the full filename–directory and basename parts–except for the extension.
Definition: filename.I:377
modelLoadRequest.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
AsyncTaskChain
The AsyncTaskChain is a subset of the AsyncTaskManager.
Definition: asyncTaskChain.h:50
Loader
A convenient class for loading models from disk, in bam or egg format (or any of a number of other fo...
Definition: loader.h:42
config_putil.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
modelPool.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
AsyncTaskManager::get_global_ptr
static AsyncTaskManager * get_global_ptr()
Returns a pointer to the global AsyncTaskManager.
Definition: asyncTaskManager.I:50
BamCacheRecord::set_data
set_data
Stores a new data object on the record.
Definition: bamCacheRecord.h:77
BamCacheRecord
An instance of this class is written to the front of a Bam or Txo file to make the file a cached inst...
Definition: bamCacheRecord.h:35
LoaderFileType
This is the base class for a family of scene-graph file types that the Loader supports.
Definition: loaderFileType.h:33
SceneGraphReducer
An interface for simplifying ("flattening") scene graphs by eliminating unneeded nodes and collapsing...
Definition: sceneGraphReducer.h:39
string_utils.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ConfigVariableList::get_unique_value
std::string get_unique_value(size_t n) const
Returns the nth unique value of the variable.
Definition: configVariableList.I:77
Filename::to_os_specific
std::string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
Definition: filename.cxx:1123
BamCache::get_global_ptr
static BamCache * get_global_ptr()
Returns a pointer to the global BamCache object, which is used automatically by the ModelPool and Tex...
Definition: bamCache.I:223
BamFile::open_read
bool open_read(const Filename &bam_filename, bool report_errors=true)
Attempts to open the indicated filename for reading.
Definition: bamFile.cxx:51
sceneGraphReducer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bamCacheRecord.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LoaderFileTypeRegistry::write
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.
Definition: loaderFileTypeRegistry.cxx:223
load_dso.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LoaderFileTypeRegistry::register_deferred_type
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.
Definition: loaderFileTypeRegistry.cxx:78
filename.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ConfigVariableEnum
This class specializes ConfigVariable as an enumerated type.
Definition: configVariableEnum.h:31
PT
PT(AsyncTask) Loader
Returns a new AsyncTask object suitable for adding to load_async() to start an asynchronous model loa...
Definition: loader.cxx:79
VirtualFileSystem::exists
bool exists(const Filename &filename) const
Convenience function; returns true if the named file exists.
Definition: virtualFileSystem.I:18
LoaderOptions
Specifies parameters that may be passed to the loader.
Definition: loaderOptions.h:23
configVariableEnum.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ModelLoadRequest
A class object that manages a single asynchronous model load request.
Definition: modelLoadRequest.h:32
bamFile.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
renderState.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
configVariableInt.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ConfigVariableString::get_value
get_value
Returns the variable's value.
Definition: configVariableString.h:46
ModelSaveRequest
A class object that manages a single asynchronous model save request.
Definition: modelSaveRequest.h:31
DSearchPath
This class stores a list of directories that can be searched, in order, to locate a particular file.
Definition: dSearchPath.h:28
VirtualFileSystem
A hierarchy of directories and files that appears to be one continuous file system,...
Definition: virtualFileSystem.h:40
BamCache::store
bool store(BamCacheRecord *record)
Flushes a cache entry to disk.
Definition: bamCache.cxx:188
Namable::output
void output(std::ostream &out) const
Outputs the Namable.
Definition: namable.I:61
SceneGraphReducer::premunge
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...
Definition: sceneGraphReducer.I:173
AsyncTask
This class represents a concrete task performed by an AsyncManager.
Definition: asyncTask.h:32
BamFile::get_reader
get_reader
Returns the BamReader in charge of performing the read operations.
Definition: bamFile.h:81
Filename::is_local
bool is_local() const
Returns true if the filename is local, e.g.
Definition: filename.I:549
modelSaveRequest.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LoaderFileTypeRegistry
This class maintains the set of all known LoaderFileTypes in the universe.
Definition: loaderFileTypeRegistry.h:28
LoaderFileType::supports_load
virtual bool supports_load() const
Returns true if the file type can be used to load files, and load_file() is supported.
Definition: loaderFileType.cxx:82
ConfigVariableList::get_num_unique_values
size_t get_num_unique_values() const
Returns the number of unique values in the variable.
Definition: configVariableList.I:68
ModelRoot::set_timestamp
set_timestamp
Sets the timestamp of the file on disk that was read for this model.
Definition: modelRoot.h:41
BamFile
The principle public interface to reading and writing Bam disk files.
Definition: bamFile.h:41
BamCacheRecord::get_data
get_data
Returns a pointer to the data stored in the record, or NULL if there is no data.
Definition: bamCacheRecord.h:77
LoaderFileType::supports_compressed
virtual bool supports_compressed() const
Returns true if this file type can transparently load compressed files (with a .pz or ....
Definition: loaderFileType.cxx:54
BamCache
This class maintains a cache of Bam and/or Txo objects generated from model files and texture images ...
Definition: bamCache.h:42
extract_words
int extract_words(const string &str, vector_string &words)
Divides the string into a number of words according to whitespace.
Definition: string_utils.cxx:105
VirtualFileSystem::get_global_ptr
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
Definition: virtualFileSystem.cxx:742
virtualFileSystem.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ModelRoot
A node of this type is created automatically at the root of each model file that is loaded.
Definition: modelRoot.h:27
ModelPool::get_model
static ModelRoot * get_model(const Filename &filename, bool verify)
Returns the model that has already been previously loaded, or NULL otherwise.
Definition: modelPool.I:46
loaderFileTypeRegistry.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Namable
A base class for all things which can have a name.
Definition: namable.h:26
LoaderFileType::supports_save
virtual bool supports_save() const
Returns true if the file type can be used to save files, and save_file() is supported.
Definition: loaderFileType.cxx:92
loader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LoaderFileTypeRegistry::get_global_ptr
static LoaderFileTypeRegistry * get_global_ptr()
Returns a pointer to the global LoaderFileTypeRegistry object.
Definition: loaderFileTypeRegistry.cxx:270
ModelPool::add_model
static void add_model(const Filename &filename, ModelRoot *model)
Adds the indicated already-loaded model to the pool.
Definition: modelPool.I:69
PandaNode
A basic node of the scene graph or data graph.
Definition: pandaNode.h:64
ConfigVariableInt
This is a convenience class to specialize ConfigVariable as an integer type.
Definition: configVariableInt.h:24
config_express.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ModelRoot::set_fullpath
set_fullpath
Sets the full pathname of the model represented by this node, as found on disk.
Definition: modelRoot.h:37
config_pgraph.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BamCache::get_cache_models
get_cache_models
Returns whether model files (e.g.
Definition: bamCache.h:89
Filename::get_extension
std::string get_extension() const
Returns the file extension.
Definition: filename.I:400
Filename::get_basename
std::string get_basename() const
Returns the basename part of the filename.
Definition: filename.I:367
loaderFileType.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Filename
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
LoaderFileTypeRegistry::get_type_from_extension
LoaderFileType * get_type_from_extension(const std::string &extension)
Determines the type of the file based on the indicated extension (without a leading dot).
Definition: loaderFileTypeRegistry.cxx:173