00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "loader.h"
00020 #include "loaderFileType.h"
00021 #include "loaderFileTypeRegistry.h"
00022 #include "config_pgraph.h"
00023
00024 #include "config_express.h"
00025 #include "config_util.h"
00026 #include "virtualFileSystem.h"
00027 #include "event.h"
00028 #include "pt_Event.h"
00029 #include "throw_event.h"
00030 #include "eventParameter.h"
00031 #include "circBuffer.h"
00032 #include "filename.h"
00033 #include "load_dso.h"
00034
00035 #include "plist.h"
00036 #include "pvector.h"
00037 #include <algorithm>
00038
00039
00040 bool Loader::_file_types_loaded = false;
00041
00042
00043
00044
00045
00046
00047
00048 class LoaderToken : public ReferenceCount {
00049 public:
00050 INLINE LoaderToken(uint id, const string &event_name, const Filename &path,
00051 bool search, PandaNode *node=NULL) :
00052 _id(id),
00053 _event_name(event_name),
00054 _path(path),
00055 _search(search),
00056 _node(node)
00057 { }
00058 uint _id;
00059 string _event_name;
00060 Filename _path;
00061 bool _search;
00062 PT(PandaNode) _node;
00063 };
00064
00065
00066
00067
00068
00069
00070 Loader::
00071 Loader() : AsyncUtility() {
00072 _token_board = new LoaderTokenBoard;
00073 }
00074
00075
00076
00077
00078
00079
00080 Loader::
00081 ~Loader() {
00082 destroy_thread();
00083 delete _token_board;
00084 }
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 int Loader::
00095 find_all_files(const Filename &filename, const DSearchPath &search_path,
00096 Loader::Results &results) const {
00097 if (!_file_types_loaded) {
00098 load_file_types();
00099 }
00100 string extension = filename.get_extension();
00101
00102 int num_added = 0;
00103
00104 if (!extension.empty()) {
00105
00106 LoaderFileTypeRegistry *reg = LoaderFileTypeRegistry::get_ptr();
00107 LoaderFileType *requested_type =
00108 reg->get_type_from_extension(extension);
00109
00110 if (requested_type != (LoaderFileType *)NULL) {
00111 if (!filename.is_local()) {
00112
00113 results.add_file(filename, requested_type);
00114 num_added++;
00115
00116 } else {
00117
00118 DSearchPath::Results files;
00119 if (use_vfs) {
00120 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00121 num_added = vfs->find_all_files(filename, search_path, files);
00122 } else {
00123 num_added = search_path.find_all_files(filename, files);
00124 }
00125
00126 for (int i = 0; i < num_added; i++) {
00127 results.add_file(files.get_file(i), requested_type);
00128 }
00129 }
00130 }
00131
00132 } else {
00133
00134
00135 LoaderFileTypeRegistry *reg = LoaderFileTypeRegistry::get_ptr();
00136 int num_types = reg->get_num_types();
00137
00138 if (!filename.is_local()) {
00139
00140 for (int t = 0; t < num_types; t++) {
00141 LoaderFileType *type = reg->get_type(t);
00142 Filename file(filename);
00143 file.set_extension(type->get_extension());
00144
00145 if (use_vfs) {
00146 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00147 if (vfs->exists(file)) {
00148 results.add_file(file, type);
00149 num_added++;
00150 }
00151 } else {
00152 if (file.exists()) {
00153 results.add_file(file, type);
00154 num_added++;
00155 }
00156 }
00157 }
00158
00159 } else {
00160
00161 int num_dirs = search_path.get_num_directories();
00162 for (int i = 0; i < num_dirs; i++) {
00163 const Filename &directory = search_path.get_directory(i);
00164
00165 for (int t = 0; t < num_types; t++) {
00166 LoaderFileType *type = reg->get_type(t);
00167 Filename file(directory, filename);
00168 file.set_extension(type->get_extension());
00169
00170 if (use_vfs) {
00171 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00172 if (vfs->exists(file)) {
00173 results.add_file(file, type);
00174 num_added++;
00175 }
00176 } else {
00177 if (file.exists()) {
00178 results.add_file(file, type);
00179 num_added++;
00180 }
00181 }
00182 }
00183 }
00184 }
00185 }
00186
00187 return num_added;
00188 }
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 uint Loader::
00208 request_load(const string &event_name, const Filename &filename, bool search) {
00209 if (!_file_types_loaded) {
00210 load_file_types();
00211 }
00212
00213 PT(LoaderToken) tok;
00214 if (asynchronous_loads) {
00215
00216
00217 if (!_threaded) {
00218 loader_cat.info()
00219 << "Loader::request_load() - create_thread() was "
00220 << "never called! Calling it now..." << endl;
00221 create_thread();
00222 }
00223
00224
00225 #ifdef OLD_HAVE_IPC
00226 _lock.lock();
00227 #endif
00228
00229 if (_token_board->_waiting.full()) {
00230 loader_cat.error()
00231 << "Loader::request_load() - Too many pending requests\n";
00232 return 0;
00233 }
00234
00235 if (loader_cat.is_debug()) {
00236 loader_cat.debug()
00237 << "Load requested for file: " << filename << "\n";
00238 }
00239
00240 tok = new LoaderToken(_next_token++, event_name, filename, search);
00241 _token_board->_waiting.push_back(tok);
00242
00243 #ifdef OLD_HAVE_IPC
00244 _request_cond->signal();
00245 _lock.unlock();
00246 #endif
00247
00248 } else {
00249
00250
00251 if (_token_board->_waiting.full()) {
00252 loader_cat.error()
00253 << "Loader::request_load() - Too many pending requests\n";
00254 return 0;
00255 }
00256
00257 if (loader_cat.is_debug()) {
00258 loader_cat.debug()
00259 << "Load requested for file: " << filename << "\n";
00260 }
00261
00262 tok = new LoaderToken(_next_token++, event_name, filename, search);
00263 _token_board->_waiting.push_back(tok);
00264 process_request();
00265 }
00266
00267 return tok->_id;
00268 }
00269
00270
00271
00272
00273
00274
00275
00276 bool Loader::
00277 check_load(uint id) {
00278 return _token_board->is_done_token(id);
00279 }
00280
00281
00282
00283
00284
00285
00286
00287
00288 PT(PandaNode) Loader::
00289 fetch_load(uint id) {
00290 PT(LoaderToken) tok = _token_board->get_done_token(id);
00291 if (tok.is_null()) {
00292 loader_cat.debug()
00293 << "Request to fetch id " << id << " which has not yet completed.\n";
00294 return NULL;
00295 }
00296 PT(PandaNode) node = tok->_node;
00297 return node;
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 void Loader::
00309 load_file_types() {
00310 nassertv(load_file_type != (Config::ConfigTable::Symbol *)NULL);
00311
00312 if (!_file_types_loaded) {
00313 Config::ConfigTable::Symbol::iterator ti;
00314 for (ti = load_file_type->begin(); ti != load_file_type->end(); ++ti) {
00315 Filename dlname = Filename::dso_filename("lib" + (*ti).Val() + ".so");
00316 loader_cat.info()
00317 << "loading file type module: " << dlname.to_os_specific() << endl;
00318 void *tmp = load_dso(dlname);
00319 if (tmp == (void *)NULL) {
00320 loader_cat.info()
00321 << "Unable to load: " << load_dso_error() << endl;
00322 }
00323 }
00324 _file_types_loaded = true;
00325 }
00326 }
00327
00328
00329
00330
00331
00332
00333
00334 bool Loader::
00335 process_request() {
00336 if (_shutdown) {
00337 if (loader_cat.is_debug())
00338 loader_cat.debug()
00339 << "Loader shutting down...\n";
00340 return false;
00341 }
00342
00343
00344 while (!_token_board->_waiting.empty()) {
00345 PT(LoaderToken) tok = _token_board->_waiting.front();
00346 _token_board->_waiting.pop_front();
00347 tok->_node = load_file(tok->_path, tok->_search);
00348 if (tok->_node == (PandaNode *)NULL) {
00349 loader_cat.error()
00350 << "Loader::callback() - couldn't find file: "
00351 << tok->_path << "\n";
00352 } else {
00353 _token_board->_done.push_back(tok);
00354
00355
00356 if (!tok->_event_name.empty()) {
00357 PT_Event done = new Event(tok->_event_name);
00358 done->add_parameter(EventParameter((int)tok->_id));
00359 throw_event(done);
00360 }
00361 }
00362
00363 if (loader_cat.is_debug()) {
00364 loader_cat.debug()
00365 << "loading complete for " << tok->_path << "\n";
00366 }
00367 }
00368
00369 return true;
00370 }
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383 PT(PandaNode) Loader::
00384 load_file(const Filename &filename, bool search) const {
00385 Results results;
00386 int num_files;
00387
00388 if (search) {
00389
00390 num_files = find_all_files(filename, get_model_path(), results);
00391 } else {
00392
00393 num_files = find_all_files(filename, DSearchPath("."), results);
00394 }
00395
00396 if (num_files == 0) {
00397
00398
00399 string extension = filename.get_extension();
00400 if (!extension.empty()) {
00401 LoaderFileTypeRegistry *reg = LoaderFileTypeRegistry::get_ptr();
00402 LoaderFileType *requested_type =
00403 reg->get_type_from_extension(extension);
00404 if (requested_type == (LoaderFileType *)NULL) {
00405 loader_cat.error()
00406 << "Extension of file " << filename
00407 << " is unrecognized; cannot load.\n";
00408 loader_cat.error(false)
00409 << "Currently known scene file types are:\n";
00410 reg->write_types(loader_cat.error(false), 2);
00411 return NULL;
00412 }
00413 }
00414
00415 if (search) {
00416 loader_cat.error()
00417 << "Couldn't load file " << filename << ": not found on model path.\n";
00418
00419 } else {
00420 loader_cat.error()
00421 << "Couldn't load file " << filename << ": does not exist.\n";
00422 }
00423 return NULL;
00424 }
00425
00426 for (int i = 0; i < num_files; i++) {
00427 const Filename &path = results.get_file(i);
00428 LoaderFileType *type = results.get_file_type(i);
00429 PT(PandaNode) result = type->load_file(path, true);
00430 if (result != (PandaNode *)NULL) {
00431 return result;
00432 }
00433 }
00434
00435
00436 if (search) {
00437 loader_cat.error()
00438 << "Couldn't load file " << filename
00439 << ": all matching files on model path invalid.\n";
00440
00441 } else {
00442 loader_cat.error()
00443 << "Couldn't load file " << filename
00444 << ": invalid.\n";
00445 }
00446 return NULL;
00447 }
00448