diff --git a/swCommonLib/System/Dir.cpp b/swCommonLib/System/Dir.cpp index 4d5839c7..9febb751 100644 --- a/swCommonLib/System/Dir.cpp +++ b/swCommonLib/System/Dir.cpp @@ -23,4 +23,21 @@ bool Dir::CreateDirectory ( const filesystem::Path& path ) return std::filesystem::create_directories( path.String() ); } +// ================================ // + +std::vector< Path > Dir::ListFiles( const filesystem::Path& path ) +{ + if( std::filesystem::exists( path.String() ) ) + { + std::vector< Path > files; + for( auto const& dir_entry : std::filesystem::directory_iterator{ path.GetStdPath() } ) + { + if( dir_entry.is_regular_file() ) + files.push_back( filesystem::Path( dir_entry.path() ) ); + } + return files; + } + return std::vector< Path >(); +} + } diff --git a/swCommonLib/System/Dir.h b/swCommonLib/System/Dir.h index 1efe0eec..59d2582c 100644 --- a/swCommonLib/System/Dir.h +++ b/swCommonLib/System/Dir.h @@ -7,7 +7,7 @@ #include "Path.h" - +#include namespace filesystem { @@ -23,7 +23,8 @@ class Dir ~Dir() = default; - static bool CreateDirectory ( const filesystem::Path& path ); + static bool CreateDirectory ( const filesystem::Path& path ); + static std::vector< Path > ListFiles ( const filesystem::Path& path ); }; diff --git a/swCommonLib/System/Path.h b/swCommonLib/System/Path.h index ae7f5b64..5d58121a 100644 --- a/swCommonLib/System/Path.h +++ b/swCommonLib/System/Path.h @@ -1,14 +1,13 @@ #pragma once /** @file Path.h -@author nieznanysprawiciel -@copyright Plik jest częścią silnika graficznego SWEngine. +@author +@copyright This file is part of the SWEngine graphics engine. -Implementacja klasy Path. Ponieważ Path nie znajduje się jeszcze w standardzie c++, ale -zostanie do niego włączone dopiero wraz z c++17, to potrzebny jest ten wrapper. -Na razie implementacje dla różnych kompilatorów umieszczają tę klasę w różnych namespacach, -więc nie da się tego zaimplementowac w pełni przenośnie. -*/ +Implementation of the Path class. Since Path is not yet part of the C++ standard, +but will be included with C++17, this wrapper is needed. +Currently, implementations for different compilers place this class in different namespaces, +so it cannot be implemented fully portably.*/ // Supress deprecation warning. We nned to remember to use @@ -16,8 +15,8 @@ #define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING -//#include -#include "Filesystem/filesystem/path.h" +#include +//#include "Filesystem/filesystem/path.h" #include #include @@ -29,12 +28,10 @@ namespace filesystem { -//namespace experimental = std::tr2::sys; - class Path { private: - path_impl m_path; + std::filesystem::path m_path; public: @@ -57,7 +54,6 @@ class Path bool operator<= ( const Path& other ) const; bool operator> ( const Path& other ) const; bool operator>= ( const Path& other ) const; - //bool Compare ( const Path& path1, const Path& path2 ); friend Path operator/ ( const Path& path1, const Path& path2 ); @@ -73,7 +69,7 @@ class Path void Normalize (); void MakeAbsolute (); Path ChangeExtension ( const std::string& extension ) const; - + Path RelativeTo ( const Path& base ) const; //bool HasRoot () const; bool HasFileName () const; @@ -94,18 +90,15 @@ class Path public: ///@note This function may change or disapear in future. - const std::vector< std::string >& GetTokens () const; - - Path ClipFromRoot ( int num ) const; + std::vector< std::string > GetTokens() const; + const std::filesystem::path GetStdPath() const; }; // ================================ // // template< class Source > -inline Path::Path ( const Source& source ) - : m_path( path_impl( source ) ) -{} +inline Path::Path ( const Source& source ) : m_path( std::filesystem::path( source ) ) {} // ================================ // // @@ -120,7 +113,7 @@ inline Path::Path ( const std::wstring& path ) //std::wstring_convert< ConvertType, wchar_t > converter; //auto pathStr = converter.to_bytes( path ); - m_path = path_impl( path ); + m_path = std::filesystem::path( path ); } // ================================ // @@ -165,59 +158,52 @@ inline bool Path::operator!= ( const Path& other ) const // inline bool Path::operator< ( const Path& other ) const { - return m_path.str() < other.m_path.str(); + return m_path < other.m_path; } // ================================ // // inline bool Path::operator<= ( const Path& other ) const { - return m_path.str() <= other.m_path.str(); + return m_path <= other.m_path; } // ================================ // // inline bool Path::operator> ( const Path& other ) const { - return m_path.str() > other.m_path.str(); + return m_path > other.m_path; } // ================================ // // inline bool Path::operator>= ( const Path& other ) const { - return m_path.str() >= other.m_path.str(); + return m_path >= other.m_path; } -///**@brief Porównuje ścieżki. Przed porównaniem ścieżki są normalizowane. -//Paths must exist on file system.*/ -//inline bool Path::Compare ( const Path& path1, const Path& path2 ) -//{ -// return experimental::equivalent( path1.m_path, path2.m_path ); -//} - /**@brief */ inline std::string Path::String() const { - return m_path.str(); + return m_path.string(); } /**@brief */ inline std::wstring Path::WString() const { - return m_path.wstr(); + return m_path.wstring(); } /**@brief */ inline std::string Path::GetFileName() const { - return m_path.filename(); + return m_path.filename().string(); } /**@brief */ inline std::string Path::GetExtension() const { - return m_path.extension(); + return m_path.extension().string(); } /**@brief */ @@ -236,56 +222,17 @@ inline Path Path::GetDirectory() const } /**@brief Normalizes path. -@attention Obecna implementacja może nie działać do końca.*/ +@attention The current implementation may not work completely.*/ inline void Path::Normalize() { - auto& tokens = m_path.get_tokens(); - std::string normalized = ""; - - // Avoid reallocating string all the time. - size_t maxLen = 0; - for( auto& token : tokens ) - maxLen += token.size(); - - normalized.reserve( maxLen ); - normalized = *tokens.crbegin(); - - size_t tokensToOmit = 0; - for( auto i = ++tokens.crbegin(); i != tokens.crend(); ++i ) - { - if( *i == ".." ) - { - tokensToOmit++; - } - else - { - if( tokensToOmit == 0 ) - { - // Add token to path from back to beginning. - normalized = *i + "/" + normalized; - } - else - { - tokensToOmit--; - } - } - } - - // Add all .. signs that remained to the beginning. - while( tokensToOmit > 0 ) - { - normalized = "../" + normalized; - tokensToOmit--; - } - - m_path = path_impl( normalized ); + m_path = m_path.lexically_normal(); } // ================================ // // inline void Path::MakeAbsolute () { - m_path.make_absolute(); + m_path = std::filesystem::absolute( m_path ); } // ================================ // @@ -293,18 +240,19 @@ inline void Path::MakeAbsolute () inline Path Path::ChangeExtension( const std::string& extension ) const { auto ext = m_path.extension(); - auto filename = m_path.filename(); + auto filename = m_path.filename().string(); if( filename == "." || filename == ".." ) return Path( *this ); - auto startPos = filename.rfind( ext ); - if( startPos != std::string::npos ) - { - filename.replace( startPos, filename.length(), extension ); - return m_path.parent_path() / filename; - } - return Path( *this ); + return std::filesystem::path( m_path ).replace_extension( std::filesystem::path( extension ) ); +} + +// ================================ // + +inline Path Path::RelativeTo( const Path& base ) const +{ + return m_path.lexically_relative( base.m_path ); } ///**@brief */ @@ -346,14 +294,14 @@ inline bool Path::IsAbsolut() const /**@brief Check if file exists.*/ inline bool Path::Exists() const { - return m_path.exists(); + return std::filesystem::exists( m_path ); } // ================================ // // inline Path Path::WorkingDirectory() { - return path_impl::getcwd(); + return std::filesystem::current_path(); } /**@brief */ @@ -366,24 +314,21 @@ inline Path operator/( const Path& path1, const Path& path2 ) // ================================ // // -inline const std::vector< std::string >& Path::GetTokens () const +inline std::vector< std::string > Path::GetTokens () const { - return m_path.get_tokens(); -} + std::vector< std::string > tokens; + for( auto it = m_path.begin(); it != m_path.end(); ++it ) + tokens.push_back( it->string() ); -// ================================ // -// -inline Path Path::ClipFromRoot ( int num ) const -{ - return Path( m_path.clip_from_root( num ) ); + return tokens; } ///**@brief Returns standard library path. //Use only if you must.*/ -//inline const experimental::path& Path::GetStdPath() const -//{ -// return m_path; -//} +inline const std::filesystem::path Path::GetStdPath() const +{ + return m_path; +} } diff --git a/swCommonLib/Tests/FileSystemTest/PathTest.cpp b/swCommonLib/Tests/FileSystemTest/PathTest.cpp index 74087ac4..ad769519 100644 --- a/swCommonLib/Tests/FileSystemTest/PathTest.cpp +++ b/swCommonLib/Tests/FileSystemTest/PathTest.cpp @@ -47,12 +47,12 @@ TEST_CASE( "Path - Aquire Extension" ) CHECK( path6.GetExtension() == "" ); CHECK( path7.GetExtension() == "" ); CHECK( path8.GetExtension() == "" ); - CHECK( path9.GetExtension() == ".hidden" ); + CHECK( path9.GetExtension() == "" ); } // ================================ // // -TEST_CASE( "Path.ChnageExtension" ) +TEST_CASE( "Path.ChangeExtension" ) { filesystem::Path path1( "/foo/bar.txt" ); filesystem::Path path2( "/foo/bar." ); @@ -69,6 +69,6 @@ TEST_CASE( "Path.ChnageExtension" ) CHECK( path7.ChangeExtension( ".png" ) == "/foo/." ); CHECK( path8.ChangeExtension( ".png" ) == "/foo/.." ); - CHECK( path9.ChangeExtension( ".png" ) == "/foo/.png" ); + CHECK( path9.ChangeExtension( ".png" ) == "/foo/.hidden.png" ); } diff --git a/swCommonLib/Tests/FileSystemTest/TestNormalizePath.cpp b/swCommonLib/Tests/FileSystemTest/TestNormalizePath.cpp index 91ba3cae..99ba55f1 100644 --- a/swCommonLib/Tests/FileSystemTest/TestNormalizePath.cpp +++ b/swCommonLib/Tests/FileSystemTest/TestNormalizePath.cpp @@ -99,6 +99,6 @@ TEST_CASE( "Filesystem.Normalize.RamainingDots.DotsOnly" ) filesystem::Path path( "../../" ); path.Normalize(); - CHECK( path == "../../" ); + CHECK( path == filesystem::Path( "../../" ) ); } diff --git a/swGraphicAPI/Assets/TextAsset/Loader/FontPicker.cpp b/swGraphicAPI/Assets/TextAsset/Loader/FontPicker.cpp index 68a10697..089efeb8 100644 --- a/swGraphicAPI/Assets/TextAsset/Loader/FontPicker.cpp +++ b/swGraphicAPI/Assets/TextAsset/Loader/FontPicker.cpp @@ -6,6 +6,7 @@ #include "swGraphicAPI/Assets/TextAsset/stdafx.h" #include "swCommonLib/Common/RTTR.h" +#include "swCommonLib/System/Dir.h" #include "swGraphicAPI/Assets/TextAsset/Loader/FreeType.h" @@ -45,7 +46,21 @@ Nullable< FontSearchEntry > FontPicker::FindFontFile( PathsManager* pm, cons Nullable< std::vector< FontSearchEntry > > FontPicker::ListFonts( PathsManager* pm ) const { - return Nullable< std::vector< FontSearchEntry > >(); + std::vector< FontSearchEntry > entries; + + for( auto path : m_searchPaths ) + { + auto dir = pm->Translate( path ); + auto files = filesystem::Dir::ListFiles( dir ); + for( auto file : files ) + { + auto meta = FontMetadata( pm, file ); + if( meta.IsValid() ) + entries.push_back( meta.Get() ); + } + } + + return entries; } // ================================ // diff --git a/swGraphicAPI/ResourceManager/PathTranslators/AssetPath.cpp b/swGraphicAPI/ResourceManager/PathTranslators/AssetPath.cpp index 54012e84..623449f6 100644 --- a/swGraphicAPI/ResourceManager/PathTranslators/AssetPath.cpp +++ b/swGraphicAPI/ResourceManager/PathTranslators/AssetPath.cpp @@ -26,7 +26,7 @@ Nullable< AssetPath > AssetPath::FromString ( const std::string& assetPath ) if( std::regex_match( assetPath, match, sAssetPathRegex ) ) { // Ignore first match, it represents full match, that is full string. - return AssetPath( match[ 1 ], match[ 2 ] ); + return AssetPath( match[ 1 ].str(), match[ 2 ].str() ); } return std::make_shared< RuntimeException >( "String can't be converted to AssetPath." ); diff --git a/swGraphicAPI/ResourceManager/PathTranslators/PathsManager.cpp b/swGraphicAPI/ResourceManager/PathTranslators/PathsManager.cpp index 75771e2a..e37819b6 100644 --- a/swGraphicAPI/ResourceManager/PathTranslators/PathsManager.cpp +++ b/swGraphicAPI/ResourceManager/PathTranslators/PathsManager.cpp @@ -26,7 +26,7 @@ filesystem::Path PathsManager::Translate ( const filesystem::Path& path ) con // Absolut paths don't need translation. if( path.IsRelative() ) { - const auto& segments = path.GetTokens(); + const auto segments = path.GetTokens(); if( segments.size() > 0 ) { const auto& alias = segments[ 0 ]; @@ -35,7 +35,7 @@ filesystem::Path PathsManager::Translate ( const filesystem::Path& path ) con auto iter = m_aliases.find( alias ); if( iter != m_aliases.end() ) { - filesystem::Path relativePart = path.ClipFromRoot( 1 ); + filesystem::Path relativePart = path.RelativeTo( filesystem::Path( alias ) ); return iter->second / relativePart; } } diff --git a/swGraphicAPI/Tests/TestText/TestFontPicker.cpp b/swGraphicAPI/Tests/TestText/TestFontPicker.cpp index 53763799..9f479a80 100644 --- a/swGraphicAPI/Tests/TestText/TestFontPicker.cpp +++ b/swGraphicAPI/Tests/TestText/TestFontPicker.cpp @@ -41,3 +41,20 @@ TEST_CASE( "GraphicAPI.Loaders.Font.FontPicker.Metadata", "[GraphicAPI][FontLoad CHECK( meta2.Get().Style == FontStyle::Normal ); CHECK( meta2.Get().Weight == FontWeight::Normal ); } + +// ================================ // +// +TEST_CASE( "GraphicAPI.Loaders.Font.FontPicker.ListFonts", "[GraphicAPI][FontLoader][FreeTypeLoader]" ) +{ + auto rm = CreateResourceManagerWithFonts(); + auto api = ResourceManagerAPI( rm.get() ); + + FontPicker picker; + picker.RegisterSearchPath( "$(FontAssets)" ); + + auto list = picker.ListFonts( rm->GetPathsManager() ); + REQUIRE_IS_VALID( list ); + + auto& files = list.Get(); + CHECK( files.size() == 3 ); +}