fix search path weirdnesses

This commit is contained in:
David Rose 2003-02-11 20:14:23 +00:00
parent edfaea28b8
commit b75c54b446
16 changed files with 218 additions and 92 deletions

View File

@ -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++;
}
}

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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);
}
}
////////////////////////////////////////////////////////////////////

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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";

View File

@ -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);
}

View File

@ -15,13 +15,11 @@
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef TOKENBOARD_H
#define TOKENBOARD_H
//
////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////
#include <pandabase.h>
#include "pandabase.h"
#include "plist.h"
#include "circBuffer.h"
#include "pointerTo.h"

View File

@ -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++;
}
}

View File

@ -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();

View File

@ -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);
}

View File

@ -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;
}

View File

@ -15,6 +15,7 @@
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#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;