Browse Source

fix search path weirdnesses

David Rose 23 years ago
parent
commit
b75c54b446

+ 20 - 2
dtool/src/dtoolutil/dSearchPath.cxx

@@ -277,7 +277,16 @@ find_file(const Filename &filename) const {
     for (di = _directories.begin(); di != _directories.end(); ++di) {
       Filename match((*di), filename);
       if (match.exists()) {
-        return match;
+        if ((*di) == "." && filename.is_fully_qualified()) {
+          // A special case for the "." directory: to avoid prefixing
+          // an endless stream of ./ in front of files, if the
+          // filename already has a ./ prefixed
+          // (i.e. is_fully_fully_qualified() is true), we don't
+          // prefix another one.
+          return filename;
+        } else {
+          return match;
+        }
       }
     }
   }
@@ -307,7 +316,16 @@ find_all_files(const Filename &filename,
     for (di = _directories.begin(); di != _directories.end(); ++di) {
       Filename match((*di), filename);
       if (match.exists()) {
-        results.add_file(match);
+        if ((*di) == "." && filename.is_fully_qualified()) {
+          // A special case for the "." directory: to avoid prefixing
+          // an endless stream of ./ in front of files, if the
+          // filename already has a ./ prefixed
+          // (i.e. is_fully_fully_qualified() is true), we don't
+          // prefix another one.
+          results.add_file(filename);
+        } else {
+          results.add_file(match);
+        }
         num_added++;
       }
     }

+ 33 - 0
dtool/src/dtoolutil/filename.cxx

@@ -518,6 +518,39 @@ set_extension(const string &s) {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Filename::extract_components
+//       Access: Public
+//  Description: Extracts out the individual directory components of
+//               the path into a series of strings.  get_basename()
+//               will be the last component stored in the vector.
+//               Note that no distinction is made by this method
+//               between a leading slash and no leading slash, but you
+//               can call is_local() to differentiate the two cases.
+////////////////////////////////////////////////////////////////////
+void Filename::
+extract_components(vector_string &components) const {
+  components.clear();
+
+  size_t p = 0;
+  if (!_filename.empty() && _filename[0] == '/') {
+    // Skip the leading slash.
+    p = 1;
+  }
+  while (p < _filename.length()) {
+    size_t q = _filename.find('/', p);
+    if (q == string::npos) {
+      components.push_back(_filename.substr(p));
+      return;
+    }
+    components.push_back(_filename.substr(p, q - p));
+    p = q + 1;
+  }
+
+  // A trailing slash means we have an empty get_basename().
+  components.push_back(string());
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: Filename::standardize
 //       Access: Public

+ 1 - 0
dtool/src/dtoolutil/filename.h

@@ -122,6 +122,7 @@ PUBLISHED:
   INLINE void set_type(Type type);
   INLINE Type get_type() const;
 
+  void extract_components(vector_string &components) const;
   void standardize();
 
   // The following functions deal with the outside world.

+ 26 - 0
panda/src/egg/eggData.I

@@ -24,6 +24,7 @@
 ////////////////////////////////////////////////////////////////////
 INLINE EggData::
 EggData() {
+  _auto_resolve_externals = false;
   _coordsys = CS_default;
 }
 
@@ -36,6 +37,7 @@ EggData() {
 INLINE EggData::
 EggData(const EggData &copy) :
   EggGroupNode(copy),
+  _auto_resolve_externals(copy._auto_resolve_externals),
   _coordsys(copy._coordsys),
   _egg_filename(copy._egg_filename) {
 }
@@ -48,11 +50,35 @@ EggData(const EggData &copy) :
 INLINE EggData &EggData::
 operator = (const EggData &copy) {
   EggGroupNode::operator = (copy);
+  _auto_resolve_externals = copy._auto_resolve_externals;
   _coordsys = copy._coordsys;
   _egg_filename = copy._egg_filename;
   return *this;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggData::set_auto_resolve_externals
+//       Access: Public
+//  Description: Indicates whether the EggData object will
+//               automatically resolve any external references when
+//               read() is called.  The default is false.
+////////////////////////////////////////////////////////////////////
+INLINE void EggData::
+set_auto_resolve_externals(bool resolve) {
+  _auto_resolve_externals = resolve;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggData::get_auto_resolve_externals
+//       Access: Public
+//  Description: Indicates whether the EggData object will
+//               automatically resolve any external references when
+//               read() is called.  The default is false.
+////////////////////////////////////////////////////////////////////
+INLINE bool EggData::
+get_auto_resolve_externals() const {
+  return _auto_resolve_externals;
+}
 
 ////////////////////////////////////////////////////////////////////
 //     Function: EggData::get_coordinate_system

+ 11 - 24
panda/src/egg/eggData.cxx

@@ -87,18 +87,12 @@ resolve_egg_filename(Filename &egg_filename, const DSearchPath &searchpath) {
 ////////////////////////////////////////////////////////////////////
 bool EggData::
 read(Filename filename) {
-  if (!resolve_egg_filename(filename)) {
-    egg_cat.error()
-      << "Could not find " << filename << "\n";
-    return false;
-  }
+  filename.set_text();
+  set_egg_filename(filename);
 
   if (use_vfs) {
     VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
     
-    filename.set_text();
-    set_egg_filename(filename);
-    
     istream *file = vfs->open_read_file(filename);
     if (file == (istream *)NULL) {
       egg_cat.error() << "Unable to open " << filename << "\n";
@@ -113,15 +107,6 @@ read(Filename filename) {
     return read_ok;
 
   } else {
-    if (!resolve_egg_filename(filename)) {
-      egg_cat.error()
-        << "Could not find " << filename << "\n";
-      return false;
-    }
-    
-    filename.set_text();
-    set_egg_filename(filename);
-    
     ifstream file;
     if (!filename.open_read(file)) {
       egg_cat.error() << "Unable to open " << filename << "\n";
@@ -174,7 +159,7 @@ read(istream &in) {
 
 
 ////////////////////////////////////////////////////////////////////
-//     Function: EggData::resolve_externals
+//     Function: EggData::load_externals
 //       Access: Public
 //  Description: Loads up all the egg files referenced by <File>
 //               entries within the egg structure, and inserts their
@@ -185,9 +170,9 @@ read(istream &in) {
 //               successfully, false otherwise.
 ////////////////////////////////////////////////////////////////////
 bool EggData::
-resolve_externals(const DSearchPath &searchpath) {
+load_externals(const DSearchPath &searchpath) {
   return
-    r_resolve_externals(searchpath, get_coordinate_system());
+    r_load_externals(searchpath, get_coordinate_system());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -330,10 +315,12 @@ post_read() {
     set_coordinate_system(old_coordsys);
   }
 
-  // Resolve filenames that are relative to the egg file.
-  DSearchPath dir;
-  dir.append_directory(get_egg_filename().get_dirname());
-  resolve_filenames(dir);
+  if (get_auto_resolve_externals()) {
+    // Resolve filenames that are relative to the egg file.
+    DSearchPath dir;
+    dir.append_directory(get_egg_filename().get_dirname());
+    resolve_filenames(dir);
+  }
 }
 
 ////////////////////////////////////////////////////////////////////

+ 5 - 1
panda/src/egg/eggData.h

@@ -55,13 +55,16 @@ public:
   bool read(Filename filename);
   bool read(istream &in);
 
-  bool resolve_externals(const DSearchPath &searchpath = DSearchPath());
+  bool load_externals(const DSearchPath &searchpath = DSearchPath());
   int collapse_equivalent_textures();
   int collapse_equivalent_materials();
 
   bool write_egg(Filename filename);
   bool write_egg(ostream &out);
 
+  INLINE void set_auto_resolve_externals(bool resolve);
+  INLINE bool get_auto_resolve_externals() const;
+
   void set_coordinate_system(CoordinateSystem coordsys);
   INLINE CoordinateSystem get_coordinate_system() const;
 
@@ -79,6 +82,7 @@ private:
   void post_read();
   void pre_write();
 
+  bool _auto_resolve_externals;
   CoordinateSystem _coordsys;
   Filename _egg_filename;
 

+ 7 - 8
panda/src/egg/eggGroupNode.cxx

@@ -31,8 +31,8 @@
 #include "pt_EggMaterial.h"
 #include "config_egg.h"
 
-#include <dSearchPath.h>
-#include <deg_2_rad.h>
+#include "dSearchPath.h"
+#include "deg_2_rad.h"
 
 #include <algorithm>
 
@@ -903,17 +903,16 @@ find_materials(EggMaterialCollection *collection) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: EggGroupNode::r_resolve_externals
+//     Function: EggGroupNode::r_load_externals
 //       Access: Protected
 //  Description: Walks the tree and locates unloaded external
 //               reference nodes, which it attempts to locate and load
 //               in.  The reference node is replaced with the entire
 //               subtree loaded.  This is intended to be called from
-//               EggData::resolve_externals().
+//               EggData::load_externals().
 ////////////////////////////////////////////////////////////////////
 bool EggGroupNode::
-r_resolve_externals(const DSearchPath &searchpath,
-                    CoordinateSystem coordsys) {
+r_load_externals(const DSearchPath &searchpath, CoordinateSystem coordsys) {
   bool success = true;
 
   Children::iterator ci;
@@ -944,7 +943,7 @@ r_resolve_externals(const DSearchPath &searchpath,
           // The external file was read correctly.  Add its contents
           // into the tree at this point.
           success =
-            ext_data.resolve_externals(searchpath)
+            ext_data.load_externals(searchpath)
             && success;
           new_node->steal_children(ext_data);
         }
@@ -953,7 +952,7 @@ r_resolve_externals(const DSearchPath &searchpath,
     } else if (child->is_of_type(EggGroupNode::get_class_type())) {
       EggGroupNode *group_child = DCAST(EggGroupNode, child);
       success =
-        group_child->r_resolve_externals(searchpath, coordsys)
+        group_child->r_load_externals(searchpath, coordsys)
         && success;
     }
   }

+ 7 - 7
panda/src/egg/eggGroupNode.h

@@ -19,14 +19,14 @@
 #ifndef EGGGROUPNODE_H
 #define EGGGROUPNODE_H
 
-#include <pandabase.h>
+#include "pandabase.h"
 
 #include "eggNode.h"
 
-#include <coordinateSystem.h>
-#include <typedObject.h>
-#include <pointerTo.h>
-#include <luse.h>
+#include "coordinateSystem.h"
+#include "typedObject.h"
+#include "pointerTo.h"
+#include "luse.h"
 
 #include "plist.h"
 
@@ -135,8 +135,8 @@ protected:
   CoordinateSystem find_coordsys_entry();
   int find_textures(EggTextureCollection *collection);
   int find_materials(EggMaterialCollection *collection);
-  bool r_resolve_externals(const DSearchPath &searchpath,
-                           CoordinateSystem coordsys);
+  bool r_load_externals(const DSearchPath &searchpath, 
+                        CoordinateSystem coordsys);
 
 private:
   Children _children;

+ 2 - 2
panda/src/egg/test_egg.cxx

@@ -17,7 +17,7 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "eggData.h"
-#include <notify.h>
+#include "notify.h"
 
 
 int
@@ -32,7 +32,7 @@ main(int argc, char *argv[]) {
   data.set_coordinate_system(CS_default);
 
   if (data.read(egg_filename)) {
-    data.resolve_externals("");
+    data.load_externals("");
     data.write_egg(cout);
   } else {
     nout << "Errors.\n";

+ 2 - 1
panda/src/egg2pg/load_egg_file.cxx

@@ -26,7 +26,7 @@
 
 static PT(PandaNode)
 load_from_loader(EggLoader &loader) {
-  loader._data.resolve_externals();
+  loader._data.load_externals();
 
   loader.build_graph();
 
@@ -79,6 +79,7 @@ load_egg_file(const string &filename, CoordinateSystem cs) {
 
   EggLoader loader;
   loader._data.set_egg_filename(egg_filename);
+  loader._data.set_auto_resolve_externals(true);
   if (cs != CS_default) {
     loader._data.set_coordinate_system(cs);
   }

+ 3 - 5
panda/src/express/tokenBoard.h

@@ -15,13 +15,11 @@
 // [email protected] .
 //
 ////////////////////////////////////////////////////////////////////
+
 #ifndef TOKENBOARD_H
 #define TOKENBOARD_H
-//
-////////////////////////////////////////////////////////////////////
-// Includes
-////////////////////////////////////////////////////////////////////
-#include <pandabase.h>
+
+#include "pandabase.h"
 #include "plist.h"
 #include "circBuffer.h"
 #include "pointerTo.h"

+ 20 - 1
panda/src/express/virtualFileSystem.cxx

@@ -347,6 +347,15 @@ find_file(const Filename &filename, const DSearchPath &searchpath) const {
   int num_directories = searchpath.get_num_directories();
   for (int i = 0; i < num_directories; i++) {
     Filename match(searchpath.get_directory(i), filename);
+    if (searchpath.get_directory(i) == "." && 
+        filename.is_fully_qualified()) {
+      // A special case for the "." directory: to avoid prefixing
+      // an endless stream of ./ in front of files, if the
+      // filename already has a ./ prefixed
+      // (i.e. is_fully_fully_qualified() is true), we don't
+      // prefix another one.
+      match = filename;
+    }
     PT(VirtualFile) found_file = get_file(match);
     if (found_file != (VirtualFile *)NULL) {
       return found_file;
@@ -430,7 +439,17 @@ find_all_files(const Filename &filename, const DSearchPath &searchpath,
     for (int i = 0; i < num_directories; i++) {
       Filename match(searchpath.get_directory(i), filename);
       if (exists(match)) {
-        results.add_file(match);
+        if (searchpath.get_directory(i) == "." && 
+            filename.is_fully_qualified()) {
+          // A special case for the "." directory: to avoid prefixing
+          // an endless stream of ./ in front of files, if the
+          // filename already has a ./ prefixed
+          // (i.e. is_fully_fully_qualified() is true), we don't
+          // prefix another one.
+          results.add_file(filename);
+        } else {
+          results.add_file(match);
+        }
         num_added++;
       }
     }

+ 5 - 7
panda/src/framework/windowFramework.cxx

@@ -373,15 +373,13 @@ load_models(const NodePath &parent, const pvector<Filename> &files) {
 NodePath WindowFramework::
 load_model(const NodePath &parent, Filename filename) {
   nout << "Loading " << filename << "\n";
-  
-  // First, we always try to resolve a filename from the current
-  // directory.  This means a local filename will always be found
-  // before the model path is searched.
-  DSearchPath local_path(".");
-  filename.resolve_filename(local_path);
+
+  // If the filename already exists where it is, or if it is fully
+  // qualified, don't search along the model path for it.
+  bool search = !(filename.is_fully_qualified() || filename.exists());
   
   Loader loader;
-  PT(PandaNode) node = loader.load_sync(filename);
+  PT(PandaNode) node = loader.load_sync(filename, search);
   if (node == (PandaNode *)NULL) {
     nout << "Unable to load " << filename << "\n";
     return NodePath::not_found();

+ 8 - 3
panda/src/pgraph/loader.I

@@ -115,12 +115,17 @@ add_file(const Filename &file, LoaderFileType *type) {
 ////////////////////////////////////////////////////////////////////
 //     Function: Loader::load_sync
 //       Access: Published
-//  Description: Loads the file immediately, waiting for it to complete.
+//  Description: Loads the file immediately, waiting for it to
+//               complete.
+//
+//               If search is true, the file is searched for along the
+//               model path; otherwise, only the exact filename is
+//               loaded.
 ////////////////////////////////////////////////////////////////////
 INLINE PT(PandaNode) Loader::
-load_sync(const Filename &filename) const {
+load_sync(const Filename &filename, bool search) const {
   if (!_file_types_loaded) {
     load_file_types();
   }
-  return load_file(filename);
+  return load_file(filename, search);
 }

+ 62 - 27
panda/src/pgraph/loader.cxx

@@ -47,14 +47,18 @@ bool Loader::_file_types_loaded = false;
 ////////////////////////////////////////////////////////////////////
 class LoaderToken : public ReferenceCount {
 public:
-  INLINE LoaderToken(uint id, Filename path, const string &event_name,
-        PandaNode *node=NULL) : _id(id), _node(node) {
-    _path = path;
-    _event_name = event_name;
-  }
+  INLINE LoaderToken(uint id, const string &event_name, const Filename &path, 
+                     bool search, PandaNode *node=NULL) : 
+    _id(id), 
+    _event_name(event_name), 
+    _path(path),
+    _search(search),
+    _node(node) 
+  { }
   uint _id;
-  Filename _path;
   string _event_name;
+  Filename _path;
+  bool _search;
   PT(PandaNode) _node;
 };
 
@@ -82,12 +86,14 @@ Loader::
 ////////////////////////////////////////////////////////////////////
 //     Function: Loader::find_all_files
 //       Access: Published
-//  Description: Searches along the model path for the given file
-//               name, and fills up the results list with all possible
-//               matches and their associated types, in order.
+//  Description: Searches along the given search path for the given
+//               file name, and fills up the results list with all
+//               possible matches and their associated types, in
+//               order.
 ////////////////////////////////////////////////////////////////////
 int Loader::
-find_all_files(const Filename &filename, Loader::Results &results) const {
+find_all_files(const Filename &filename, const DSearchPath &search_path,
+               Loader::Results &results) const {
   if (!_file_types_loaded) {
     load_file_types();
   }
@@ -109,13 +115,12 @@ find_all_files(const Filename &filename, Loader::Results &results) const {
 
       } else {
         // Local filename, search along the path.
-        const DSearchPath &model_path = get_model_path();
         DSearchPath::Results files;
         if (use_vfs) {
           VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
-          num_added = vfs->find_all_files(filename, model_path, files);
+          num_added = vfs->find_all_files(filename, search_path, files);
         } else {
-          num_added = model_path.find_all_files(filename, files);
+          num_added = search_path.find_all_files(filename, files);
         }
         
         for (int i = 0; i < num_added; i++) {
@@ -153,10 +158,9 @@ find_all_files(const Filename &filename, Loader::Results &results) const {
 
     } else {
       // Local filename, look it up on the model path.
-      const DSearchPath &model_path = get_model_path();
-      int num_dirs = model_path.get_num_directories();
+      int num_dirs = search_path.get_num_directories();
       for (int i = 0; i < num_dirs; i++) {
-        const Filename &directory = model_path.get_directory(i);
+        const Filename &directory = search_path.get_directory(i);
         
         for (int t = 0; t < num_types; t++) {
           LoaderFileType *type = reg->get_type(t);
@@ -195,9 +199,13 @@ find_all_files(const Filename &filename, Loader::Results &results) const {
 //               The return value is an integer which can be used to
 //               identify this particular request later to
 //               fetch_load(), or 0 if there has been an error.
+//
+//               If search is true, the file is searched for along the
+//               model path; otherwise, only the exact filename is
+//               loaded.
 ////////////////////////////////////////////////////////////////////
 uint Loader::
-request_load(const Filename &filename, const string &event_name) {
+request_load(const string &event_name, const Filename &filename, bool search) {
   if (!_file_types_loaded) {
     load_file_types();
   }
@@ -229,7 +237,7 @@ request_load(const Filename &filename, const string &event_name) {
           << "Load requested for file: " << filename << "\n";
       }
 
-      tok = new LoaderToken(_next_token++, filename, event_name);
+      tok = new LoaderToken(_next_token++, event_name, filename, search);
       _token_board->_waiting.push_back(tok);
 
 #ifdef OLD_HAVE_IPC
@@ -251,7 +259,7 @@ request_load(const Filename &filename, const string &event_name) {
         << "Load requested for file: " << filename << "\n";
     }
 
-    tok = new LoaderToken(_next_token++, filename, event_name);
+    tok = new LoaderToken(_next_token++, event_name, filename, search);
     _token_board->_waiting.push_back(tok);
     process_request();
   }
@@ -336,7 +344,7 @@ process_request() {
   while (!_token_board->_waiting.empty()) {
     PT(LoaderToken) tok = _token_board->_waiting.front();
     _token_board->_waiting.pop_front();
-    tok->_node = load_file(tok->_path);
+    tok->_node = load_file(tok->_path, tok->_search);
     if (tok->_node == (PandaNode *)NULL) {
       loader_cat.error()
         << "Loader::callback() - couldn't find file: "
@@ -367,12 +375,24 @@ process_request() {
 //  Description: Loads a single scene graph file, if possible.
 //               Returns the Node that is the root of the file, or
 //               NULL if the file cannot be loaded.
+//
+//               If search is true, the file is searched for along the
+//               model path; otherwise, only the exact filename is
+//               loaded.
 ////////////////////////////////////////////////////////////////////
 PT(PandaNode) Loader::
-load_file(const Filename &filename) const {
-  // First, look for the file along the search path.
+load_file(const Filename &filename, bool search) const {
   Results results;
-  int num_files = find_all_files(filename, results);
+  int num_files;
+
+  if (search) {
+    // Look for the file along the model path.
+    num_files = find_all_files(filename, get_model_path(), results);
+  } else {
+    // Look for the file only where it is.
+    num_files = find_all_files(filename, DSearchPath("."), results);
+  }
+
   if (num_files == 0) {
     // Couldn't find the file.  Either it doesn't exist, or it's an
     // unknown file type.  Report a useful message either way.
@@ -391,8 +411,15 @@ load_file(const Filename &filename) const {
         return NULL;
       }
     }
-    loader_cat.error()
-      << "Couldn't load file " << filename << ": not found on model path.\n";
+
+    if (search) {
+      loader_cat.error()
+        << "Couldn't load file " << filename << ": not found on model path.\n";
+
+    } else {
+      loader_cat.error()
+        << "Couldn't load file " << filename << ": does not exist.\n";
+    }
     return NULL;
   }
 
@@ -406,8 +433,16 @@ load_file(const Filename &filename) const {
   }
 
   // None of the matching files could be loaded.  Oh well.
-  loader_cat.error()
-    << "Couldn't load file " << filename << ": all matching files on model path invalid.\n";
+  if (search) {
+    loader_cat.error()
+      << "Couldn't load file " << filename
+      << ": all matching files on model path invalid.\n";
+
+  } else {
+    loader_cat.error()
+      << "Couldn't load file " << filename
+      << ": invalid.\n";
+  }
   return NULL;
 }
 

+ 6 - 4
panda/src/pgraph/loader.h

@@ -15,6 +15,7 @@
 // [email protected] .
 //
 ////////////////////////////////////////////////////////////////////
+
 #ifndef LOADER_H
 #define LOADER_H
 
@@ -67,11 +68,12 @@ PUBLISHED:
   Loader();
   ~Loader();
 
-  int find_all_files(const Filename &filename, Results &results) const;
+  int find_all_files(const Filename &filename, const DSearchPath &search_path,
+                     Results &results) const;
 
-  INLINE PT(PandaNode) load_sync(const Filename &filename) const;
+  INLINE PT(PandaNode) load_sync(const Filename &filename, bool search = true) const;
 
-  uint request_load(const Filename &filename, const string &event_name);
+  uint request_load(const string &event_name, const Filename &filename, bool search = true);
   bool check_load(uint id);
   PT(PandaNode) fetch_load(uint id);
 
@@ -80,7 +82,7 @@ private:
   static bool _file_types_loaded;
 
   virtual bool process_request(void);
-  PT(PandaNode) load_file(const Filename &filename) const;
+  PT(PandaNode) load_file(const Filename &filename, bool search) const;
 
   typedef TokenBoard<LoaderToken> LoaderTokenBoard;
   LoaderTokenBoard *_token_board;