Просмотр исходного кода

Add some new capabilities to the resource filesystem

Panagiotis Christopoulos Charitos 2 лет назад
Родитель
Сommit
fc7bb86583

+ 7 - 5
AnKi/Core/App.cpp

@@ -323,11 +323,13 @@ Error App::initInternal()
 	String executableFname;
 	ANKI_CHECK(getApplicationPath(executableFname));
 	ANKI_CORE_LOGI("Executable path is: %s", executableFname.cstr());
-	String shadersPath;
-	getParentFilepath(executableFname, shadersPath);
-	shadersPath += ":";
-	shadersPath += g_dataPathsCVar.get();
-	g_dataPathsCVar.set(shadersPath);
+	String extraPaths;
+	getParentFilepath(executableFname, extraPaths);
+	extraPaths += "|ankiprogbin"; // Shaders
+	extraPaths += ":" ANKI_SOURCE_DIRECTORY "|EngineAssets,!AndroidProject"; // EngineAssets
+	extraPaths += ":";
+	extraPaths += g_dataPathsCVar.get();
+	g_dataPathsCVar.set(extraPaths);
 #endif
 
 	ANKI_CHECK(ResourceManager::allocateSingleton().init(allocCb, allocCbUserData));

+ 71 - 16
AnKi/Resource/ResourceFilesystem.cpp

@@ -15,10 +15,48 @@
 namespace anki {
 
 StringCVar g_dataPathsCVar(CVarSubsystem::kResource, "DataPaths", ".",
-						   "The engine loads assets only in from these paths. Separate them with : (it's smart enough to identify drive "
-						   "letters in Windows)");
-static StringCVar g_dataPathExcludeStringsCVar(CVarSubsystem::kResource, "DataPathExcludedStrings", "AndroidProject",
-											   "A list of string separated by : that will be used to exclude paths from rsrc_dataPaths");
+						   "The engine loads assets only in from these paths. Separate them with : (it's smart enough to identify drive letters in "
+						   "Windows). After a path you can add an optional | and what follows it is a number of words to include or exclude paths. "
+						   "eg. my_path|include_this,include_that,+exclude_this");
+
+static Error tokenizePath(CString path, ResourceString& actualPath, ResourceStringList& includedWords, ResourceStringList& excludedWords)
+{
+	ResourceStringList tokens;
+	tokens.splitString(path, '|');
+
+	const PtrSize count = tokens.getSize();
+	if(count != 1 && count != 2)
+	{
+		ANKI_RESOURCE_LOGE("Tokenization of path failed: %s", path.cstr());
+		return Error::kUserData;
+	}
+
+	actualPath = tokens.getFront();
+
+	// Further tokenization
+	if(count == 2)
+	{
+		const ResourceString excludeInclude = *(tokens.getBegin() + 1);
+
+		ResourceStringList tokens;
+		tokens.splitString(excludeInclude, ',');
+
+		for(const auto& word : tokens)
+		{
+			if(word[0] == '!')
+			{
+				ResourceString w(&word[1], word.getEnd());
+				excludedWords.emplaceBack(std::move(w));
+			}
+			else
+			{
+				includedWords.emplaceBack(word);
+			}
+		}
+	}
+
+	return Error::kNone;
+}
 
 /// C resource file
 class CResourceFile final : public ResourceFile
@@ -200,9 +238,6 @@ Error ResourceFilesystem::init()
 	ResourceStringList paths;
 	paths.splitString(g_dataPathsCVar.get(), ':');
 
-	ResourceStringList excludedStrings;
-	excludedStrings.splitString(g_dataPathExcludeStringsCVar.get(), ':');
-
 	// Workaround the fact that : is used in drives in Windows
 #if ANKI_OS_WINDOWS
 	ResourceStringList paths2;
@@ -234,9 +269,14 @@ Error ResourceFilesystem::init()
 		return Error::kUserData;
 	}
 
-	for(auto& path : paths)
+	for(const auto& path : paths)
 	{
-		ANKI_CHECK(addNewPath(path.toCString(), excludedStrings));
+		ResourceStringList includedStrings;
+		ResourceStringList excludedStrings;
+		ResourceString actualPath;
+		ANKI_CHECK(tokenizePath(path, actualPath, includedStrings, excludedStrings));
+
+		ANKI_CHECK(addNewPath(actualPath, includedStrings, excludedStrings));
 	}
 
 #if ANKI_OS_ANDROID
@@ -247,23 +287,38 @@ Error ResourceFilesystem::init()
 	return Error::kNone;
 }
 
-Error ResourceFilesystem::addNewPath(const CString& filepath, const ResourceStringList& excludedStrings)
+Error ResourceFilesystem::addNewPath(CString filepath, const ResourceStringList& includedStrings, const ResourceStringList& excludedStrings)
 {
 	ANKI_RESOURCE_LOGV("Adding new resource path: %s", filepath.cstr());
 
 	U32 fileCount = 0; // Count files manually because it's slower to get that number from the list
 	constexpr CString extension(".ankizip");
 
-	auto rejectPath = [&](CString p) -> Bool {
+	auto includePath = [&](CString p) -> Bool {
 		for(const ResourceString& s : excludedStrings)
 		{
-			if(p.find(s) != CString::kNpos)
+			const Bool found = p.find(s) != CString::kNpos;
+			if(found)
 			{
-				return true;
+				return false;
 			}
 		}
 
-		return false;
+		if(!includedStrings.isEmpty())
+		{
+			for(const ResourceString& s : includedStrings)
+			{
+				const Bool found = p.find(s) != CString::kNpos;
+				if(found)
+				{
+					return true;
+				}
+			}
+
+			return false;
+		}
+
+		return true;
 	};
 
 	PtrSize pos;
@@ -301,7 +356,7 @@ Error ResourceFilesystem::addNewPath(const CString& filepath, const ResourceStri
 			}
 
 			const Bool itsADir = info.uncompressed_size == 0;
-			if(!itsADir && !rejectPath(&filename[0]))
+			if(!itsADir && includePath(&filename[0]))
 			{
 				path.m_files.pushBackSprintf("%s", &filename[0]);
 				++fileCount;
@@ -317,7 +372,7 @@ Error ResourceFilesystem::addNewPath(const CString& filepath, const ResourceStri
 		// It's simple directory
 
 		ANKI_CHECK(walkDirectoryTree(filepath, [&](const CString& fname, Bool isDir) -> Error {
-			if(!isDir && !rejectPath(fname))
+			if(!isDir && includePath(fname))
 			{
 				path.m_files.pushBackSprintf("%s", fname.cstr());
 				++fileCount;

+ 1 - 1
AnKi/Resource/ResourceFilesystem.h

@@ -145,7 +145,7 @@ private:
 	ResourceString m_cacheDir;
 
 	/// Add a filesystem path or an archive. The path is read-only.
-	Error addNewPath(const CString& path, const ResourceStringList& excludedStrings);
+	Error addNewPath(CString path, const ResourceStringList& includeStrings, const ResourceStringList& excludedStrings);
 
 	Error openFileInternal(const ResourceFilename& filename, ResourceFile*& rfile);
 };

+ 2 - 5
Samples/Common/SampleApp.cpp

@@ -13,20 +13,17 @@ Error SampleApp::init(int argc, char** argv, CString sampleName)
 	g_windowFullscreenCVar.set(1);
 
 #if !ANKI_OS_ANDROID
-	CString mainDataPath = ANKI_SOURCE_DIRECTORY;
 	HeapMemoryPool tmpPool(allocAligned, nullptr);
 	BaseString<MemoryPoolPtrWrapper<HeapMemoryPool>> assetsDataPath(&tmpPool);
 	assetsDataPath.sprintf("%s/Samples/%s", ANKI_SOURCE_DIRECTORY, sampleName.cstr());
 
 	if(!directoryExists(assetsDataPath))
 	{
-		ANKI_LOGE("Cannot find directory \"%s\". Have you moved the clone of the repository? "
-				  "I'll continue but expect issues",
-				  assetsDataPath.cstr());
+		ANKI_LOGE("Cannot find directory \"%s\". Have you moved the clone of the repository? I'll continue but expect issues", assetsDataPath.cstr());
 	}
 	else
 	{
-		g_dataPathsCVar.set(BaseString<MemoryPoolPtrWrapper<HeapMemoryPool>>(&tmpPool).sprintf("%s:%s", mainDataPath.cstr(), assetsDataPath.cstr()));
+		g_dataPathsCVar.set(BaseString<MemoryPoolPtrWrapper<HeapMemoryPool>>(&tmpPool).sprintf("%s|.anki,lua", assetsDataPath.cstr()));
 	}
 #endif
 

+ 2 - 2
Tests/Resource/ResourceFilesystem.cpp

@@ -14,7 +14,7 @@ ANKI_TEST(Resource, ResourceFilesystem)
 	ANKI_TEST_EXPECT_NO_ERR(fs.init());
 
 	{
-		ANKI_TEST_EXPECT_NO_ERR(fs.addNewPath("Tests/Data/Dir/../Dir/", ResourceStringList()));
+		ANKI_TEST_EXPECT_NO_ERR(fs.addNewPath("Tests/Data/Dir/../Dir/", ResourceStringList(), ResourceStringList()));
 		ResourceFilePtr file;
 		ANKI_TEST_EXPECT_NO_ERR(fs.openFile("subdir0/hello.txt", file));
 		ResourceString txt;
@@ -23,7 +23,7 @@ ANKI_TEST(Resource, ResourceFilesystem)
 	}
 
 	{
-		ANKI_TEST_EXPECT_NO_ERR(fs.addNewPath("./Tests/Data/Dir.AnKiZLibip", ResourceStringList()));
+		ANKI_TEST_EXPECT_NO_ERR(fs.addNewPath("./Tests/Data/Dir.AnKiZLibip", ResourceStringList(), ResourceStringList()));
 		ResourceFilePtr file;
 		ANKI_TEST_EXPECT_NO_ERR(fs.openFile("subdir0/hello.txt", file));
 		ResourceString txt;