summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--o3d/converter/cross/converter.cc6
-rw-r--r--o3d/converter/cross/converter.h5
-rw-r--r--o3d/converter/cross/converter_main.cc12
-rw-r--r--o3d/import/cross/collada.cc77
-rw-r--r--o3d/import/cross/collada.h49
-rw-r--r--o3d/utils/cross/file_path_utils.cc53
-rw-r--r--o3d/utils/cross/file_path_utils.h21
-rw-r--r--o3d/utils/cross/file_path_utils_test.cc52
8 files changed, 233 insertions, 42 deletions
diff --git a/o3d/converter/cross/converter.cc b/o3d/converter/cross/converter.cc
index 497b8cd..9abde79 100644
--- a/o3d/converter/cross/converter.cc
+++ b/o3d/converter/cross/converter.cc
@@ -66,11 +66,12 @@ namespace o3d {
namespace {
void AddBinaryElements(const Collada& collada,
TarGzGenerator* archive_generator) {
- std::vector<FilePath> paths = collada.GetOriginalDataFilenames();
+ const ColladaDataMap& data_map(collada.original_data_map());
+ std::vector<FilePath> paths = data_map.GetOriginalDataFilenames();
for (std::vector<FilePath>::const_iterator iter = paths.begin();
iter != paths.end();
++iter) {
- const std::string& data = collada.GetOriginalData(*iter);
+ const std::string& data = data_map.GetOriginalData(*iter);
archive_generator->AddFile(FilePathToUTF8(*iter), data.size());
archive_generator->AddFileBytes(
@@ -120,6 +121,7 @@ bool Convert(const FilePath& in_filename,
collada_options.condition_document = options.condition;
collada_options.keep_original_data = true;
collada_options.base_path = options.base_path;
+ collada_options.file_paths = options.file_paths;
collada_options.up_axis = options.up_axis;
Collada collada(pack.Get(), collada_options);
bool result = collada.ImportFile(in_filename, root, param_float);
diff --git a/o3d/converter/cross/converter.h b/o3d/converter/cross/converter.h
index dd0141c..d613564 100644
--- a/o3d/converter/cross/converter.h
+++ b/o3d/converter/cross/converter.h
@@ -38,8 +38,10 @@
#ifndef O3D_CONVERTER_CROSS_CONVERTER_H_
#define O3D_CONVERTER_CROSS_CONVERTER_H_
+#include <vector>
#include "base/file_path.h"
#include "core/cross/types.h"
+#include "utils/cross/file_path_utils.h"
namespace o3d {
namespace converter {
@@ -55,6 +57,9 @@ struct Options {
keep_materials(false) {
}
+ // A list of paths to search for assets..
+ std::vector<FilePath> file_paths;
+
// The path to the "base" of the model path, from which all paths
// are made relative. Defaults to the current directory.
FilePath base_path;
diff --git a/o3d/converter/cross/converter_main.cc b/o3d/converter/cross/converter_main.cc
index 650e0b7..e332db4 100644
--- a/o3d/converter/cross/converter_main.cc
+++ b/o3d/converter/cross/converter_main.cc
@@ -40,6 +40,7 @@
#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/file_path.h"
+#include "base/string_util.h"
#include "converter/cross/converter.h"
#include "utils/cross/file_path_utils.h"
@@ -86,7 +87,9 @@ int CrossMain(int argc, char**argv) {
<< "--no-condition\n"
<< " Stops the converter from conditioning shaders.\n"
<< "--base-path=<path>\n"
- << " Sets the base path for finding textures and other external\n"
+ << " Sets the path to remove from URIs of external files\n"
+ << "--asset-paths=<comma separted list of paths>\n"
+ << " Sets the paths for finding textures and other external\n"
<< " files.\n"
<< "--up-axis=x,y,z\n"
<< " Converts the file to have this up axis.\n"
@@ -108,6 +111,13 @@ int CrossMain(int argc, char**argv) {
options.base_path = o3d::WideToFilePath(
command_line->GetSwitchValue(L"base-path"));
}
+ if (command_line->HasSwitch(L"asset-paths")) {
+ std::vector<std::wstring> paths;
+ SplitString(command_line->GetSwitchValue(L"asset-paths"), ',', &paths);
+ for (size_t ii = 0; ii < paths.size(); ++ii) {
+ options.file_paths.push_back(o3d::WideToFilePath(paths[ii]));
+ }
+ }
if (command_line->HasSwitch(L"up-axis")) {
wstring up_axis_string = command_line->GetSwitchValue(L"up-axis");
int x, y, z;
diff --git a/o3d/import/cross/collada.cc b/o3d/import/cross/collada.cc
index fa06c70..0e88ae2 100644
--- a/o3d/import/cross/collada.cc
+++ b/o3d/import/cross/collada.cc
@@ -126,6 +126,44 @@ Matrix4 FMMatrix44ToMatrix4(const FMMatrix44& fmmatrix44) {
}
} // anonymous namespace
+void ColladaDataMap::Clear() {
+ original_data_.clear();
+}
+
+bool ColladaDataMap::AddData(const FilePath& file_path,
+ const std::string& data,
+ ServiceLocator* service_locator) {
+ std::pair<OriginalDataMap::iterator, bool> result =
+ original_data_.insert(std::pair<FilePath, std::string>(file_path, data));
+ if (!result.second) {
+ O3D_ERROR(service_locator)
+ << "Attempt to map 2 resources to the same file path:"
+ << FilePathToUTF8(file_path).c_str();
+ }
+ return result.second;
+}
+
+std::vector<FilePath> ColladaDataMap::GetOriginalDataFilenames() const {
+ std::vector<FilePath> result;
+ for (OriginalDataMap::const_iterator iter = original_data_.begin();
+ iter != original_data_.end();
+ ++iter) {
+ result.push_back(iter->first);
+ }
+ return result;
+}
+
+const std::string& ColladaDataMap::GetOriginalData(
+ const FilePath& filename) const {
+ static const std::string empty;
+ OriginalDataMap::const_iterator entry = original_data_.find(filename);
+ if (entry != original_data_.end()) {
+ return entry->second;
+ } else {
+ return empty;
+ }
+}
+
// Import the given COLLADA file or ZIP file into the given scene.
// This is the external interface to o3d.
bool Collada::Import(Pack* pack,
@@ -178,7 +216,7 @@ Collada::~Collada() {
void Collada::ClearData() {
textures_.clear();
- original_data_.clear();
+ original_data_map_.Clear();
effects_.clear();
shapes_.clear();
skinned_shapes_.clear();
@@ -194,26 +232,6 @@ void Collada::ClearData() {
unique_filename_counter_ = 0;
}
-std::vector<FilePath> Collada::GetOriginalDataFilenames() const {
- std::vector<FilePath> result;
- for (OriginalDataMap::const_iterator iter = original_data_.begin();
- iter != original_data_.end();
- ++iter) {
- result.push_back(iter->first);
- }
- return result;
-}
-
-const std::string& Collada::GetOriginalData(const FilePath& filename) const {
- static const std::string empty;
- OriginalDataMap::const_iterator entry = original_data_.find(filename);
- if (entry != original_data_.end()) {
- return entry->second;
- } else {
- return empty;
- }
-}
-
// Import the given COLLADA file or ZIP file under the given parent node.
// Parameters:
// filename: The COLLADA or ZIPped COLLADA file to import.
@@ -1660,6 +1678,11 @@ Texture* Collada::BuildTextureFromImage(FCDImage* image) {
GetRelativePathIfPossible(base_path_, uri, &uri);
}
+ if (!FindFile(options_.file_paths, file_path, &file_path)) {
+ O3D_ERROR(service_locator_) << "Could not find file: " << filename;
+ return NULL;
+ }
+
tex = Texture::Ref(
pack_->CreateTextureFromFile(FilePathToUTF8(uri),
file_path,
@@ -1674,7 +1697,7 @@ Texture* Collada::BuildTextureFromImage(FCDImage* image) {
// Cache the original data by URI so we can recover it later.
std::string contents;
file_util::ReadFileToString(file_path, &contents);
- original_data_[uri] = contents;
+ original_data_map_.AddData(uri, contents, service_locator_);
}
if (tempfile.size() > 0) ZipArchive::DeleteFile(tempfile);
@@ -1984,7 +2007,10 @@ Effect* Collada::BuildEffect(FCDocument* doc, FCDEffect* collada_effect) {
}
} else {
FilePath temp_path = file_path;
- GetRelativePathIfPossible(base_path_, temp_path, &temp_path);
+ if (!FindFile(options_.file_paths, temp_path, &temp_path)) {
+ O3D_ERROR(service_locator_) << "Could not find file: " << path;
+ return NULL;
+ }
file_util::ReadFileToString(temp_path, &effect_string);
}
}
@@ -2007,7 +2033,7 @@ Effect* Collada::BuildEffect(FCDocument* doc, FCDEffect* collada_effect) {
}
if (options_.keep_original_data) {
// Cache the original data by URI so we can recover it later.
- original_data_[file_path] = effect_string;
+ original_data_map_.AddData(file_path, effect_string, service_locator_);
}
}
} else {
@@ -2076,7 +2102,8 @@ Effect* Collada::BuildEffect(FCDocument* doc, FCDEffect* collada_effect) {
}
if (options_.keep_original_data) {
// Cache the original data by URI so we can recover it later.
- original_data_[file_path] = effect_string;
+ original_data_map_.AddData(file_path, effect_string,
+ service_locator_);
}
}
}
diff --git a/o3d/import/cross/collada.h b/o3d/import/cross/collada.h
index a102e08..c2f659f 100644
--- a/o3d/import/cross/collada.h
+++ b/o3d/import/cross/collada.h
@@ -41,6 +41,7 @@
#include "base/file_path.h"
#include "core/cross/param.h"
#include "core/cross/types.h"
+#include "utils/cross/file_path_utils.h"
class FCDocument;
class FCDAnimated;
@@ -127,6 +128,31 @@ class NodeInstance {
std::vector<NodeInstance *> children_;
};
+class ColladaDataMap {
+ public:
+ // Adds a data to a filepath. Note, it is an error to associate more than one
+ // data to the same filepath.
+ bool AddData(const FilePath& file_path,
+ const std::string& data,
+ ServiceLocator* service_locator);
+
+ // Access to the filenames of the original data for texture and
+ // sound assets imported when ImportFile was called. These will
+ // only return results after an import if the keep_original_data
+ // option was set to true when the Collada object was created.
+ std::vector<FilePath> GetOriginalDataFilenames() const;
+ const std::string& GetOriginalData(const FilePath& filename) const;
+
+ // Clears the map.
+ void Clear();
+
+ private:
+ // A map containing the original data (still in original format)
+ // used to create the textures, sounds, etc., indexed by filename.
+ typedef std::map<FilePath, std::string> OriginalDataMap;
+ OriginalDataMap original_data_;
+};
+
class Collada {
public:
struct Options {
@@ -153,6 +179,9 @@ class Collada {
// The base path to use for determining the relative paths for
// asset URIs.
FilePath base_path;
+
+ // A List of paths to search for files in.
+ std::vector<FilePath> file_paths;
};
// Collada Param Names.
@@ -215,16 +244,13 @@ class Collada {
bool ImportFile(const FilePath& filename, Transform* parent,
ParamFloat* animation_input);
- // Access to the filenames of the original data for texture and
- // sound assets imported when ImportFile was called. These will
- // only return results after an import if the keep_original_data
- // option was set to true when the Collada object was created.
- std::vector<FilePath> GetOriginalDataFilenames() const;
- const std::string& GetOriginalData(const FilePath& filename) const;
-
// Init the Collada Importer.
static void Init(ServiceLocator* service_locator);
+ const ColladaDataMap& original_data_map() const {
+ return original_data_map_;
+ }
+
private:
// Imports the given ZIP file into the given pack.
bool ImportZIP(const FilePath& filename, Transform* parent,
@@ -429,11 +455,6 @@ class Collada {
// A map of the Textures created by the importer, indexed by filename.
std::map<const std::wstring, Texture*> textures_;
- // A map containing the original data (still in original format)
- // used to create the textures, sounds, etc., indexed by filename.
- typedef std::map<FilePath, std::string> OriginalDataMap;
- OriginalDataMap original_data_;
-
// A map of the Effects created by the importer, indexed by DAE id.
std::map<const std::string, Effect*> effects_;
@@ -453,7 +474,11 @@ class Collada {
// determining the relative paths to other files.
FilePath base_path_;
+ // Original data by FilePath
+ ColladaDataMap original_data_map_;
+
ColladaZipArchive *collada_zip_archive_;
+
// Some temporaries used by the state importer
bool cull_enabled_;
bool cull_front_;
diff --git a/o3d/utils/cross/file_path_utils.cc b/o3d/utils/cross/file_path_utils.cc
index db4216e..910c3a6 100644
--- a/o3d/utils/cross/file_path_utils.cc
+++ b/o3d/utils/cross/file_path_utils.cc
@@ -158,4 +158,57 @@ bool GetRelativePathIfPossible(const FilePath& base_dir,
}
}
+namespace { // anonymous namespace.
+
+// Tries to find a file path_to_find in path_to_search. Will start with
+// base name and progressively try each higher path. Example:
+//
+// FindFile('this/that', 'foo/bar/baf.txt');
+//
+// Looks for:
+// this/that/foo/bar/baf.txt
+// this/that/bar/baf.txt
+// this/that/baf.txt
+bool FindFileHelper(const FilePath& path_to_search,
+ const FilePath& path_to_find,
+ FilePath* found_path) {
+ std::vector<FilePath::StringType> parts;
+ file_util::PathComponents(path_to_find, &parts);
+
+ for (size_t ii = 0; ii < parts.size(); ++ii) {
+ // build a path from parts.
+ FilePath path(path_to_search);
+ for (size_t jj = ii; jj < parts.size(); ++jj) {
+ path = path.Append(parts[jj]);
+ }
+ if (file_util::PathExists(path)) {
+ *found_path = path;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+} // anonymous namespace
+
+bool FindFile(const std::vector<FilePath>& paths_to_search,
+ const FilePath& path_to_find,
+ FilePath* found_path) {
+ if (file_util::PathExists(path_to_find)) {
+ *found_path = path_to_find;
+ return true;
+ }
+
+ for (size_t ii = 0; ii < paths_to_search.size(); ++ii) {
+ FilePath absolute_path(paths_to_search[ii]);
+ o3d::AbsolutePath(&absolute_path);
+
+ if (FindFileHelper(absolute_path, path_to_find, found_path)) {
+ return true;
+ }
+ }
+ return false;
+}
+
} // end namespace o3d
diff --git a/o3d/utils/cross/file_path_utils.h b/o3d/utils/cross/file_path_utils.h
index 30de903..7398e8b 100644
--- a/o3d/utils/cross/file_path_utils.h
+++ b/o3d/utils/cross/file_path_utils.h
@@ -37,10 +37,10 @@
#define O3D_UTILS_CROSS_FILE_PATH_UTILS_H_
#include <string>
+#include <vector>
+#include "base/file_path.h"
#include "core/cross/types.h"
-class FilePath;
-
namespace o3d {
// TODO: Go through the process to add these to FilePath
// itself in the Chromium depot.
@@ -67,6 +67,23 @@ bool GetRelativePathIfPossible(const FilePath& base_dir,
const FilePath& candidate,
FilePath *result);
+// Tries to find a file path_to_find in paths_to_search. Will start with
+// base name and progressively try each higher path. Example:
+//
+// FindFile(['this/that', 'there'], 'foo/bar/baf.txt');
+//
+// Looks for:
+// foo/bar/baf.txt
+// this/that/foo/bar/baf.txt
+// this/that/bar/baf.txt
+// this/that/baf.txt
+// there/foo/bar/baf.txt
+// there/bar/baf.txt
+// there/baf.txt
+bool FindFile(const std::vector<FilePath>& paths_to_search,
+ const FilePath& path_to_find,
+ FilePath* found_path);
+
} // namespace o3d
#endif // O3D_UTILS_CROSS_FILE_PATH_UTILS_H_
diff --git a/o3d/utils/cross/file_path_utils_test.cc b/o3d/utils/cross/file_path_utils_test.cc
index e1447fc..e5b9ede 100644
--- a/o3d/utils/cross/file_path_utils_test.cc
+++ b/o3d/utils/cross/file_path_utils_test.cc
@@ -40,6 +40,26 @@
namespace o3d {
+namespace { // anonymous namespace
+
+bool FilePathsEqual(const FilePath& path_1, const FilePath path_2) {
+ const FilePath::StringType& p1(path_1.value());
+ const FilePath::StringType& p2(path_2.value());
+ if (p1.size() == p2.size()) {
+ for (size_t ii = 0; ii < p1.size(); ++ii) {
+ if (p1[ii] != p2[ii]) {
+ if (!FilePath::IsSeparator(p1[ii]) || !FilePath::IsSeparator(p2[ii])) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+} // anonymous namespace
+
class FilePathUtilsTest : public testing::Test {
};
@@ -180,4 +200,36 @@ TEST_F(FilePathUtilsTest, RelativePathsRelativeInputs) {
EXPECT_STREQ(expected_result.value().c_str(), result.value().c_str());
EXPECT_TRUE(is_relative);
}
+
+TEST_F(FilePathUtilsTest, FindFile) {
+ String folder_name_1(*g_program_path + "/unittest_data");
+ String folder_name_2(*g_program_path + "/bitmap_test");
+ FilePath folder_path_1 = UTF8ToFilePath(folder_name_1);
+ FilePath folder_path_2 = UTF8ToFilePath(folder_name_2);
+ String file_name_1("fur.fx");
+ String file_name_2("someplace/somewhere/tga-256x256-32bit.tga");
+ FilePath file_path_1 = UTF8ToFilePath(file_name_1);
+ FilePath file_path_2 = UTF8ToFilePath(file_name_2);
+ FilePath out_path;
+
+ FilePath expected_path_1(folder_path_1);
+ expected_path_1 = expected_path_1.Append(file_path_1);
+ FilePath expected_path_2(folder_path_2);
+ expected_path_2 =
+ expected_path_2.Append(UTF8ToFilePath("tga-256x256-32bit.tga"));
+
+ std::vector<FilePath> paths;
+ EXPECT_FALSE(FindFile(paths, file_path_1, &out_path));
+ EXPECT_FALSE(FindFile(paths, file_path_2, &out_path));
+ paths.push_back(folder_path_1);
+ EXPECT_TRUE(FindFile(paths, file_path_1, &out_path));
+ EXPECT_FALSE(FindFile(paths, file_path_2, &out_path));
+ EXPECT_TRUE(FilePathsEqual(out_path, expected_path_1));
+ paths.push_back(folder_path_2);
+ EXPECT_TRUE(FindFile(paths, file_path_1, &out_path));
+ EXPECT_TRUE(FilePathsEqual(out_path, expected_path_1));
+ EXPECT_TRUE(FindFile(paths, file_path_2, &out_path));
+ EXPECT_TRUE(FilePathsEqual(out_path, expected_path_2));
+}
+
} // namespace o3d