From 9f9d44834bc405f781e58699a5b819a59c923dd7 Mon Sep 17 00:00:00 2001 From: Alexis Maiquez Murcia Date: Thu, 4 Apr 2019 16:51:54 +0200 Subject: [PATCH] - Removed the whole "fileResolver" class in favour of using the actual irrlicht file-handling functions ~ Added a small utils class to read full files to ram for the purpose of parsing json files Most of these files are really small, so there shouldn't really be any memory concerns + Added support for loading backgrounds directly from PKG files Signed-off-by: Alexis Maiquez Murcia --- CMakeLists.txt | 2 +- main.cpp | 11 +- wallpaperengine/effect.cpp | 4 +- wallpaperengine/fs/fileResolver.cpp | 136 ------------------- wallpaperengine/fs/fileResolver.h | 104 -------------- wallpaperengine/fs/utils.cpp | 32 +++++ wallpaperengine/fs/utils.h | 36 +++++ wallpaperengine/image.cpp | 27 +--- wallpaperengine/image.h | 3 +- wallpaperengine/irr/CFileList.cpp | 157 +++++++++++++++++++++ wallpaperengine/irr/CFileList.h | 136 +++++++++++++++++++ wallpaperengine/irr/CPkgReader.cpp | 195 +++++++++++++++++++++++++++ wallpaperengine/irr/CPkgReader.h | 82 +++++++++++ wallpaperengine/project.cpp | 14 +- wallpaperengine/project.h | 2 +- wallpaperengine/scene.cpp | 8 +- wallpaperengine/scene.h | 2 +- wallpaperengine/shaders/compiler.cpp | 7 +- wallpaperengine/shaders/compiler.h | 4 +- wallpaperengine/texture.cpp | 2 +- wallpaperengine/texture.h | 2 +- 21 files changed, 673 insertions(+), 293 deletions(-) delete mode 100644 wallpaperengine/fs/fileResolver.cpp delete mode 100644 wallpaperengine/fs/fileResolver.h create mode 100644 wallpaperengine/fs/utils.cpp create mode 100644 wallpaperengine/fs/utils.h create mode 100644 wallpaperengine/irr/CFileList.cpp create mode 100644 wallpaperengine/irr/CFileList.h create mode 100644 wallpaperengine/irr/CPkgReader.cpp create mode 100644 wallpaperengine/irr/CPkgReader.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9879ec4..217ca7b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,6 @@ find_package(LZ4 REQUIRED) include_directories(${X11_INCLUDE_DIR} ${IRRLICHT_INCLUDE_DIR} ${LZ4_INCLUDE_DIR} .) -add_executable(wallengine main.cpp wallpaperengine/shaders/compiler.h wallpaperengine/shaders/compiler.cpp wallpaperengine/project.cpp wallpaperengine/project.h wallpaperengine/scene.cpp wallpaperengine/scene.h wallpaperengine/object.cpp wallpaperengine/object.h wallpaperengine/camera.cpp wallpaperengine/camera.h wallpaperengine/core.cpp wallpaperengine/core.h wallpaperengine/image.cpp wallpaperengine/image.h wallpaperengine/object3d.cpp wallpaperengine/object3d.h wallpaperengine/effect.cpp wallpaperengine/effect.h wallpaperengine/fs/fileResolver.cpp wallpaperengine/fs/fileResolver.h wallpaperengine/irrlicht.cpp wallpaperengine/irrlicht.h wallpaperengine/config.cpp wallpaperengine/config.h wallpaperengine/video/renderer.cpp wallpaperengine/video/renderer.h wallpaperengine/video/node.cpp wallpaperengine/video/node.h wallpaperengine/video/material.cpp wallpaperengine/video/material.h wallpaperengine/texture.cpp wallpaperengine/texture.h wallpaperengine/irr/CImageLoaderTEX.h wallpaperengine/irr/CImageLoaderTEX.cpp) +add_executable(wallengine main.cpp wallpaperengine/shaders/compiler.h wallpaperengine/shaders/compiler.cpp wallpaperengine/project.cpp wallpaperengine/project.h wallpaperengine/scene.cpp wallpaperengine/scene.h wallpaperengine/object.cpp wallpaperengine/object.h wallpaperengine/camera.cpp wallpaperengine/camera.h wallpaperengine/core.cpp wallpaperengine/core.h wallpaperengine/image.cpp wallpaperengine/image.h wallpaperengine/object3d.cpp wallpaperengine/object3d.h wallpaperengine/effect.cpp wallpaperengine/effect.h wallpaperengine/fs/utils.cpp wallpaperengine/fs/utils.h wallpaperengine/irrlicht.cpp wallpaperengine/irrlicht.h wallpaperengine/config.cpp wallpaperengine/config.h wallpaperengine/video/renderer.cpp wallpaperengine/video/renderer.h wallpaperengine/video/node.cpp wallpaperengine/video/node.h wallpaperengine/video/material.cpp wallpaperengine/video/material.h wallpaperengine/texture.cpp wallpaperengine/texture.h wallpaperengine/irr/CImageLoaderTEX.h wallpaperengine/irr/CImageLoaderTEX.cpp wallpaperengine/irr/CPkgReader.h wallpaperengine/irr/CPkgReader.cpp wallpaperengine/irr/CFileList.h wallpaperengine/irr/CFileList.cpp) target_link_libraries(wallengine ${X11_LIBRARIES} ${X11_Xxf86vm_LIB} ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ${ZLIB_LIBRARIES} ${IRRLICHT_LIBRARY} ${LZ4_LIBRARY}) \ No newline at end of file diff --git a/main.cpp b/main.cpp index fc451c5..6897d6a 100644 --- a/main.cpp +++ b/main.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "wallpaperengine/shaders/compiler.h" #include "wallpaperengine/project.h" @@ -97,8 +98,6 @@ void preconfigure_wallpaper_engine () wp::config::path::base = wp::irrlicht::device->getFileSystem ()->getAbsolutePath ("../"); wp::config::path::resources = wp::config::path::base + "/res"; wp::config::path::shaders = wp::config::path::resources + "/shaders"; - - wp::fs::resolver.changeWorkingDirectory (wp::config::path::base); } int main (int argc, char* argv[]) @@ -123,14 +122,18 @@ int main (int argc, char* argv[]) // do_decompress (); irr::io::path _wp_engine_folder = "/home/almamu/Development/tmp/nier__automata_-_become_as_gods_edition/"; + irr::io::path _wp_project_file = _wp_engine_folder + "project.json"; // set our working directory - wp::fs::resolver.changeWorkingDirectory (_wp_engine_folder); + wp::irrlicht::device->getFileSystem ()->changeWorkingDirectoryTo (_wp_engine_folder); // register custom loader wp::irrlicht::driver->addExternalImageLoader (new irr::video::CImageLoaderTex ()); + wp::irrlicht::device->getFileSystem ()->addArchiveLoader (new CArchiveLoaderPkg (wp::irrlicht::device->getFileSystem ())); + // wp::irrlicht::device->getFileSystem ()->addFileArchive ("./", true, false, irr::io::E_FILE_ARCHIVE_TYPE::EFAT_FOLDER); + // wp::irrlicht::device->getFileSystem ()->addFileArchive (_wp_engine_folder + "scene.pkg", true, false); // add the pkg file to the lookup list - wp::project* wp_project = new wp::project (); + wp::project* wp_project = new wp::project (_wp_project_file); if (wp_project->getScene ()->isOrthogonal() == true) { diff --git a/wallpaperengine/effect.cpp b/wallpaperengine/effect.cpp index 3e52e0c..1b7480a 100644 --- a/wallpaperengine/effect.cpp +++ b/wallpaperengine/effect.cpp @@ -1,4 +1,4 @@ -#include +#include #include "effect.h" namespace wp @@ -10,7 +10,7 @@ namespace wp if (file != json_data.end () && (*file).is_string () == true) { - this->m_file = wp::fs::resolver.resolve (*file); + this->m_file = ("effects/" + (*file).get ()).c_str (); } } }; \ No newline at end of file diff --git a/wallpaperengine/fs/fileResolver.cpp b/wallpaperengine/fs/fileResolver.cpp deleted file mode 100644 index dccfcf6..0000000 --- a/wallpaperengine/fs/fileResolver.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include -#include - -// filesystem includes -#include - -// engine includes -#include - -namespace wp -{ - namespace fs - { - fileResolver::fileResolver () - { - this->m_environment.push_back ("."); - } - - fileResolver::fileResolver (std::vector environment) - { - this->m_environment.insert (this->m_environment.end (), environment.begin (), environment.end ()); - } - - void fileResolver::appendEnvironment (irr::io::path path) - { - this->m_environment.push_back (wp::irrlicht::device->getFileSystem ()->getAbsolutePath (path)); - } - - void fileResolver::removeEnvironment(irr::io::path path) - { - std::vector::const_iterator cur = this->m_environment.begin (); - std::vector::const_iterator end = this->m_environment.end (); - irr::io::path absolute = wp::irrlicht::device->getFileSystem ()->getAbsolutePath (path); - - for (; cur != end; cur ++) - { - if (*cur == path) - { - this->m_environment.erase (cur); - return; - } - } - } - - void fileResolver::prependEnvironment (irr::io::path path) - { - this->m_environment.insert ( - this->m_environment.begin (), - wp::irrlicht::device->getFileSystem ()->getAbsolutePath (path) - ); - } - - void fileResolver::changeWorkingDirectory (irr::io::path newpath) - { - this->m_environment.erase (this->m_environment.begin ()); - this->prependEnvironment (newpath); - } - - irr::io::path fileResolver::getWorkingDirectory () - { - return *this->m_environment.begin (); - } - - fs::fileResolver fileResolver::clone () - { - return fileResolver (this->m_environment); - } - - irr::io::path fileResolver::resolve (irr::io::path name) - { - std::vector::const_iterator cur = this->m_environment.begin (); - std::vector::const_iterator end = this->m_environment.end (); - irr::io::path tmp = ""; - - // try to resolve the path - for (; cur != end; cur ++) - { - tmp = *cur; - tmp += "/"; - tmp += name; - - if (wp::irrlicht::device->getFileSystem ()->existFile (tmp) == true) - { - wp::irrlicht::device->getLogger ()->log ("Resolved file to", tmp.c_str ()); - - return tmp; - } - } - - wp::irrlicht::device->getLogger ()->log ("Failed resolving file ", name.c_str (), irr::ELL_ERROR); - - return ""; - } - - irr::io::path fileResolver::resolveOnWorkingDirectory (irr::io::path name) - { - irr::io::path file = *this->m_environment.begin () + "/" + name; - - if (wp::irrlicht::device->getFileSystem ()->existFile (file) == true) - { - wp::irrlicht::device->getLogger ()->log ("Resolved file in working directory to", file.c_str ()); - - // perform stat over the file to check for directory - return file; - } - - wp::irrlicht::device->getLogger ()->log ("Failed resolving file on working directory for ", name.c_str (), irr::ELL_ERROR); - - return ""; - } - - irr::io::path fileResolver::resolve (json name) - { - std::string tmp = name; - return this->resolve (tmp.c_str ()); - } - - irr::io::path fileResolver::resolveOnWorkingDirectory (json name) - { - std::string tmp = name; - return this->resolveOnWorkingDirectory (tmp.c_str ()); - } - - irr::io::path fileResolver::resolve (const char* name) - { - return this->resolve (irr::io::path(name)); - } - - irr::io::path fileResolver::resolveOnWorkingDirectory (const char* name) - { - return this->resolveOnWorkingDirectory(irr::io::path (name)); - } - - fileResolver resolver; - } -} \ No newline at end of file diff --git a/wallpaperengine/fs/fileResolver.h b/wallpaperengine/fs/fileResolver.h deleted file mode 100644 index 4268a21..0000000 --- a/wallpaperengine/fs/fileResolver.h +++ /dev/null @@ -1,104 +0,0 @@ -/** - * @author Alexis Maiquez Murcia - */ -#ifndef WALLENGINE_RESOLVER_H -#define WALLENGINE_RESOLVER_H - -#include -#include -#include -#include - -namespace wp -{ - using json = nlohmann::json; - - namespace fs - { - /** - * Custom file resolver to limit our searches to specific folders - */ - class fileResolver - { - public: - /** - * Basic constructor, uses current path as base folder - */ - fileResolver (); - /** - * Creates a file resolver using a list as environment folders - * - * @param environment List of directories to use for finding files - */ - fileResolver (std::vector environment); - - /** - * Adds a new folder to the environment list - * - * @param path - */ - void appendEnvironment (irr::io::path path); - /** - * Removes the given folder from the environment list - * - * @param path - */ - void removeEnvironment (irr::io::path path); - /** - * Updates the current working directory - * - * @param newpath - */ - void changeWorkingDirectory (irr::io::path newpath); - /** - * @return The current working directory - */ - irr::io::path getWorkingDirectory (); - /** - * @return A clone of this fileResolver - */ - fileResolver clone (); - /** - * Resolves the given filename or relative path - * on the current working directory or any of the registered - * environment folders - * - * @param name The filename/relative path to resolve - * - * @return The full path to the file - */ - irr::io::path resolve (irr::io::path name); - /** - * Resolves the given filename or relative path - * on the current working directory only - * - * @param name The filename/relative path to resolve - * - * @return The full path to the file - */ - irr::io::path resolveOnWorkingDirectory (irr::io::path name); - irr::io::path resolve (json name); - irr::io::path resolveOnWorkingDirectory (json name); - irr::io::path resolve (const char* name); - irr::io::path resolveOnWorkingDirectory (const char* name); - - protected: - void prependEnvironment (irr::io::path path); - - private: - /** - * List of environment paths in which the resolver will look for - * files in when trying to resolve them - */ - std::vector m_environment; - }; - - /** - * Static resolver used trough most of the application - */ - extern fileResolver resolver; - }; -} - - -#endif //WALLENGINE_RESOLVER_H diff --git a/wallpaperengine/fs/utils.cpp b/wallpaperengine/fs/utils.cpp new file mode 100644 index 0000000..aa4d7d8 --- /dev/null +++ b/wallpaperengine/fs/utils.cpp @@ -0,0 +1,32 @@ +#include +#include + +// filesystem includes +#include + +// engine includes +#include + +namespace wp +{ + namespace fs + { + std::string utils::loadFullFile (irr::io::path file) + { + irr::io::IReadFile* reader = wp::irrlicht::device->getFileSystem ()->createAndOpenFile (file); + + if (reader == NULL) + return ""; + + char* filedata = new char [reader->getSize () + 1]; + memset (filedata, 0, reader->getSize () + 1); + + reader->read (filedata, reader->getSize ()); + + std::string content = filedata; + delete [] filedata; + + return content; + } + } +} \ No newline at end of file diff --git a/wallpaperengine/fs/utils.h b/wallpaperengine/fs/utils.h new file mode 100644 index 0000000..5af61ef --- /dev/null +++ b/wallpaperengine/fs/utils.h @@ -0,0 +1,36 @@ +/** + * @author Alexis Maiquez Murcia + */ +#ifndef WALLENGINE_RESOLVER_H +#define WALLENGINE_RESOLVER_H + +#include +#include +#include +#include + +namespace wp +{ + using json = nlohmann::json; + + namespace fs + { + /** + * Custom file resolver to limit our searches to specific folders + */ + class utils + { + public: + /** + * Loads a full file into an std::string + * + * @param file + * @return + */ + static std::string loadFullFile (irr::io::path file); + }; + }; +} + + +#endif //WALLENGINE_RESOLVER_H diff --git a/wallpaperengine/image.cpp b/wallpaperengine/image.cpp index 1b1c850..a8ea5ba 100644 --- a/wallpaperengine/image.cpp +++ b/wallpaperengine/image.cpp @@ -1,7 +1,7 @@ #include #include -#include +#include #include #include @@ -24,27 +24,18 @@ namespace wp // basic texture, main thing to assign first if (file_it != json_data.end () && (*file_it).is_string () == true) { - this->m_file = wp::fs::resolver.resolve (*file_it); + this->m_file = (*file_it).get ().c_str (); + this->m_content = wp::fs::utils::loadFullFile (this->m_file); - this->m_content = ""; - std::ifstream _in (this->m_file.c_str ()); - this->m_content.append (std::istreambuf_iterator (_in), std::istreambuf_iterator ()); json content = json::parse (this->m_content); json::const_iterator it = content.find ("material"); if (it != content.end () && (*it).is_string () == true) { - irr::io::path materialfile = wp::fs::resolver.resolveOnWorkingDirectory ((*it)); - - std::ifstream _in (materialfile.c_str ()); - std::string texturejson_content = ""; - texturejson_content.append (std::istreambuf_iterator (_in), std::istreambuf_iterator ()); + irr::io::path materialfile = (*it).get ().c_str (); + std::string texturejson_content = wp::fs::utils::loadFullFile (materialfile); json materialcontent = json::parse (texturejson_content); - // change working directory for the resolver to the materials folder - this->m_resolver = wp::fs::resolver.clone (); - this->m_resolver.changeWorkingDirectory(this->m_resolver.resolveOnWorkingDirectory ("materials")); - // now try to read the texture if any json::const_iterator it = materialcontent.find ("passes"); @@ -64,13 +55,9 @@ namespace wp for (; texturesCur != texturesEnd; texturesCur ++) { - // TODO: SUPPORT PROPER WALLPAPERENGINE FORMATS - std::string name = (*texturesCur); - name += ".tex"; - irr::io::path texturePath = this->m_resolver.resolveOnWorkingDirectory (name); - std::string basename = (*texturesCur); + irr::io::path texturepath = ("materials/" + (*texturesCur).get () + ".tex").c_str (); - this->m_textures.push_back (new wp::texture (texturePath)); + this->m_textures.push_back (new wp::texture (texturepath)); } } } diff --git a/wallpaperengine/image.h b/wallpaperengine/image.h index b5878e0..5e110e7 100644 --- a/wallpaperengine/image.h +++ b/wallpaperengine/image.h @@ -4,7 +4,7 @@ #include #include -#include +#include #include namespace wp @@ -26,7 +26,6 @@ namespace wp irr::video::S3DVertex m_vertices [4]; irr::video::SMaterial m_material; - wp::fs::fileResolver m_resolver; irr::core::vector3df m_origin; irr::io::path m_file; std::string m_content; diff --git a/wallpaperengine/irr/CFileList.cpp b/wallpaperengine/irr/CFileList.cpp new file mode 100644 index 0000000..62348a5 --- /dev/null +++ b/wallpaperengine/irr/CFileList.cpp @@ -0,0 +1,157 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include + +#include "CFileList.h" + +namespace irr +{ + namespace io + { + + static const io::path emptyFileListEntry; + + CFileList::CFileList(const io::path& path, bool ignoreCase, bool ignorePaths) + : IgnorePaths(ignorePaths), IgnoreCase(ignoreCase), Path(path) + { + Path.replace('\\', '/'); + } + + CFileList::~CFileList() + { + Files.clear(); + } + + u32 CFileList::getFileCount() const + { + return Files.size(); + } + + void CFileList::sort() + { + Files.sort(); + } + + const io::path& CFileList::getFileName(u32 index) const + { + if (index >= Files.size()) + return emptyFileListEntry; + + return Files[index].Name; + } + + +//! Gets the full name of a file in the list, path included, based on an index. + const io::path& CFileList::getFullFileName(u32 index) const + { + if (index >= Files.size()) + return emptyFileListEntry; + + return Files[index].FullName; + } + +//! adds a file or folder + u32 CFileList::addItem(const io::path& fullPath, u32 offset, u32 size, bool isDirectory, u32 id) + { + SFileListEntry entry; + entry.ID = id ? id : Files.size(); + entry.Offset = offset; + entry.Size = size; + entry.Name = fullPath; + entry.Name.replace('\\', '/'); + entry.IsDirectory = isDirectory; + + // remove trailing slash + if (entry.Name.lastChar() == '/') + { + entry.IsDirectory = true; + entry.Name[entry.Name.size()-1] = 0; + entry.Name.validate(); + } + + if (IgnoreCase) + entry.Name.make_lower(); + + entry.FullName = entry.Name; + + core::deletePathFromFilename(entry.Name); + + if (IgnorePaths) + entry.FullName = entry.Name; + + //os::Printer::log(Path.c_str(), entry.FullName); + + Files.push_back(entry); + + return Files.size() - 1; + } + +//! Returns the ID of a file in the file list, based on an index. + u32 CFileList::getID(u32 index) const + { + return index < Files.size() ? Files[index].ID : 0; + } + + bool CFileList::isDirectory(u32 index) const + { + bool ret = false; + if (index < Files.size()) + ret = Files[index].IsDirectory; + + return ret; + } + +//! Returns the size of a file + u32 CFileList::getFileSize(u32 index) const + { + return index < Files.size() ? Files[index].Size : 0; + } + +//! Returns the size of a file + u32 CFileList::getFileOffset(u32 index) const + { + return index < Files.size() ? Files[index].Offset : 0; + } + + +//! Searches for a file or folder within the list, returns the index + s32 CFileList::findFile(const io::path& filename, bool isDirectory = false) const + { + SFileListEntry entry; + // we only need FullName to be set for the search + entry.FullName = filename; + entry.IsDirectory = isDirectory; + + // exchange + entry.FullName.replace('\\', '/'); + + // remove trailing slash + if (entry.FullName.lastChar() == '/') + { + entry.IsDirectory = true; + entry.FullName[entry.FullName.size()-1] = 0; + entry.FullName.validate(); + } + + if (IgnoreCase) + entry.FullName.make_lower(); + + if (IgnorePaths) + core::deletePathFromFilename(entry.FullName); + + return Files.binary_search(entry); + } + + +//! Returns the base path of the file list + const io::path& CFileList::getPath() const + { + return Path; + } + + + } // end namespace irr +} // end namespace io + diff --git a/wallpaperengine/irr/CFileList.h b/wallpaperengine/irr/CFileList.h new file mode 100644 index 0000000..2483b6c --- /dev/null +++ b/wallpaperengine/irr/CFileList.h @@ -0,0 +1,136 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __C_FILE_LIST_H_INCLUDED__ +#define __C_FILE_LIST_H_INCLUDED__ + +#include + + +namespace irr +{ +namespace io +{ + +//! An entry in a list of files, can be a folder or a file. +struct SFileListEntry +{ + //! The name of the file + /** If this is a file or folder in the virtual filesystem and the archive + was created with the ignoreCase flag then the file name will be lower case. */ + io::path Name; + + //! The name of the file including the path + /** If this is a file or folder in the virtual filesystem and the archive was + created with the ignoreDirs flag then it will be the same as Name. */ + io::path FullName; + + //! The size of the file in bytes + u32 Size; + + //! The ID of the file in an archive + /** This is used to link the FileList entry to extra info held about this + file in an archive, which can hold things like data offset and CRC. */ + u32 ID; + + //! FileOffset inside an archive + u32 Offset; + + //! True if this is a folder, false if not. + bool IsDirectory; + + //! The == operator is provided so that CFileList can slowly search the list! + bool operator ==(const struct SFileListEntry& other) const + { + if (IsDirectory != other.IsDirectory) + return false; + + return FullName.equals_ignore_case(other.FullName); + } + + //! The < operator is provided so that CFileList can sort and quickly search the list. + bool operator <(const struct SFileListEntry& other) const + { + if (IsDirectory != other.IsDirectory) + return IsDirectory; + + return FullName.lower_ignore_case(other.FullName); + } +}; + + +//! Implementation of a file list +class CFileList : public IFileList +{ +public: + + // CFileList methods + + //! Constructor + /** \param path The path of this file archive */ + CFileList(const io::path& path, bool ignoreCase, bool ignorePaths); + + //! Destructor + virtual ~CFileList(); + + //! Add as a file or folder to the list + /** \param fullPath The file name including path, up to the root of the file list. + \param isDirectory True if this is a directory rather than a file. + \param offset The offset where the file is stored in an archive + \param size The size of the file in bytes. + \param id The ID of the file in the archive which owns it */ + virtual u32 addItem(const io::path& fullPath, u32 offset, u32 size, bool isDirectory, u32 id=0); + + //! Sorts the file list. You should call this after adding any items to the file list + virtual void sort(); + + //! Returns the amount of files in the filelist. + virtual u32 getFileCount() const; + + //! Gets the name of a file in the list, based on an index. + virtual const io::path& getFileName(u32 index) const; + + //! Gets the full name of a file in the list, path included, based on an index. + virtual const io::path& getFullFileName(u32 index) const; + + //! Returns the ID of a file in the file list, based on an index. + virtual u32 getID(u32 index) const; + + //! Returns true if the file is a directory + virtual bool isDirectory(u32 index) const; + + //! Returns the size of a file + virtual u32 getFileSize(u32 index) const; + + //! Returns the offest of a file + virtual u32 getFileOffset(u32 index) const; + + //! Searches for a file or folder within the list, returns the index + virtual s32 findFile(const io::path& filename, bool isFolder) const; + + //! Returns the base path of the file list + virtual const io::path& getPath() const; + +protected: + + //! Ignore paths when adding or searching for files + bool IgnorePaths; + + //! Ignore case when adding or searching for files + bool IgnoreCase; + + //! Path to the file list + io::path Path; + + //! List of files + core::array Files; +}; + + +} // end namespace irr +} // end namespace io + + +#endif + diff --git a/wallpaperengine/irr/CPkgReader.cpp b/wallpaperengine/irr/CPkgReader.cpp new file mode 100644 index 0000000..a6ddd5f --- /dev/null +++ b/wallpaperengine/irr/CPkgReader.cpp @@ -0,0 +1,195 @@ +// +// Created by almamu on 4/04/19. +// + +#include +#include "CPkgReader.h" + +CArchiveLoaderPkg::CArchiveLoaderPkg(irr::io::IFileSystem* fs) + : FileSystem(fs) +{ +#ifdef _DEBUG + setDebugName("CArchiveLoaderWAD"); +#endif +} + + +//! returns true if the file maybe is able to be loaded by this class +bool CArchiveLoaderPkg::isALoadableFileFormat(const irr::io::path& filename) const +{ + return irr::core::hasFileExtension (filename, "pkg"); +} + + +//! Creates an archive from the filename +/** \param file File handle to check. +\return Pointer to newly created archive, or 0 upon error. */ +irr::io::IFileArchive* CArchiveLoaderPkg::createArchive(const irr::io::path& filename, bool ignoreCase, bool ignorePaths) const +{ + irr::io::IFileArchive *archive = nullptr; + irr::io::IReadFile* file = FileSystem->createAndOpenFile(filename); + + if (file) + { + archive = createArchive (file, ignoreCase, ignorePaths); + file->drop (); + } + + return archive; +} + +//! creates/loads an archive from the file. +//! \return Pointer to the created archive. Returns 0 if loading failed. +irr::io::IFileArchive* CArchiveLoaderPkg::createArchive(irr::io::IReadFile* file, bool ignoreCase, bool ignorePaths) const +{ + irr::io::IFileArchive *archive = nullptr; + + if (file) + { + file->seek (0); + archive = new CPkgReader (file, ignoreCase, ignorePaths); + } + + return archive; +} + + +//! Check if the file might be loaded by this class +/** Check might look into the file. +\param file File handle to check. +\return True if file seems to be loadable. */ +bool CArchiveLoaderPkg::isALoadableFileFormat(irr::io::IReadFile* file) const +{ + unsigned int size; + char* pointer; + + file->read (&size, 4); + + // the string doesnt include the null terminator + size ++; + + pointer = new char [size]; + memset (pointer, 0, size); + + file->read (pointer, size - 1); + + if (strcmp (pointer, "PKGV0002") != 0) + { + delete [] pointer; + return false; + } + + delete [] pointer; + return true; +} + +//! Check to see if the loader can create archives of this type. +bool CArchiveLoaderPkg::isALoadableFileFormat(irr::io::E_FILE_ARCHIVE_TYPE fileType) const +{ + return false; +} + +CPkgReader::CPkgReader (irr::io::IReadFile* file, bool ignoreCase, bool ignorePaths) + : CFileList((file ? file->getFileName() : irr::io::path("")), ignoreCase, ignorePaths), mFile(file) +{ + if (this->mFile) + { + this->mFile->grab (); + this->scanPkgHeader (); + } +} + +CPkgReader::~CPkgReader() +{ + if (this->mFile) + this->mFile->drop(); +} + + +//! get the archive type +irr::io::E_FILE_ARCHIVE_TYPE CPkgReader::getType() const +{ + return irr::io::E_FILE_ARCHIVE_TYPE::EFAT_ZIP; +} + +const irr::io::IFileList* CPkgReader::getFileList() const +{ + return this; +} + +void CPkgReader::scanPkgHeader () +{ + char* headerVersion = this->readSizedString (); + + if (strcmp ("PKGV0002", headerVersion) != 0) + { + wp::irrlicht::device->getLogger ()->log ("Unexpected package header... Aborting load", this->mFile->getFileName ().c_str (), irr::ELL_ERROR); + + delete [] headerVersion; + return; + } + + delete [] headerVersion; + + unsigned int entriesCount; + + this->mFile->read (&entriesCount, 4); + + + + for (int i = 0; i < entriesCount; i ++) + { + char* filename = this->readSizedString (); + unsigned int offset, length; + + this->mFile->read (&offset, 4); + this->mFile->read (&length, 4); + + this->addItem (filename, offset, length, false); + + delete [] filename; + } + + // after the header is read we have to update the actual offsets + for (int i = 0; i < this->Files.size (); i ++) + { + this->Files [i].Offset += this->mFile->getPos (); + } +} + +char* CPkgReader::readSizedString () +{ + unsigned int size; + char* pointer; + + this->mFile->read (&size, 4); + + // the string doesnt include the null terminator + size ++; + + pointer = new char [size]; + memset (pointer, 0, size); + + this->mFile->read (pointer, size - 1); + + return pointer; +} + +irr::io::IReadFile* CPkgReader::createAndOpenFile (const irr::io::path& filename) +{ + irr::s32 index = this->findFile (filename, false); + + if (index != -1) + return createAndOpenFile (index); + + return nullptr; +} + +irr::io::IReadFile* CPkgReader::createAndOpenFile (irr::u32 index) +{ + if (index > this->Files.size ()) + return nullptr; + + const irr::io::SFileListEntry entry = Files [index]; + return irr::io::createLimitReadFile (entry.FullName, mFile, entry.Offset, entry.Size); +} \ No newline at end of file diff --git a/wallpaperengine/irr/CPkgReader.h b/wallpaperengine/irr/CPkgReader.h new file mode 100644 index 0000000..7f958d6 --- /dev/null +++ b/wallpaperengine/irr/CPkgReader.h @@ -0,0 +1,82 @@ +// +// Created by almamu on 4/04/19. +// + +#ifndef WALLENGINE_CPKGREADER_H +#define WALLENGINE_CPKGREADER_H + +#include +#include + +#include "CFileList.h" + +//! Archiveloader capable of loading WAD Archives +class CArchiveLoaderPkg : public irr::io::IArchiveLoader +{ +public: + + //! Constructor + CArchiveLoaderPkg(irr::io::IFileSystem* fs); + + //! returns true if the file maybe is able to be loaded by this class + //! based on the file extension (e.g. ".zip") + virtual bool isALoadableFileFormat(const irr::io::path& filename) const; + + //! Check if the file might be loaded by this class + /** Check might look into the file. + \param file File handle to check. + \return True if file seems to be loadable. */ + virtual bool isALoadableFileFormat(irr::io::IReadFile* file) const; + + //! Check to see if the loader can create archives of this type. + /** Check based on the archive type. + \param fileType The archive type to check. + \return True if the archile loader supports this type, false if not */ + virtual bool isALoadableFileFormat(irr::io::E_FILE_ARCHIVE_TYPE fileType) const; + + //! Creates an archive from the filename + /** \param file File handle to check. + \return Pointer to newly created archive, or 0 upon error. */ + virtual irr::io::IFileArchive* createArchive(const irr::io::path& filename, bool ignoreCase, bool ignorePaths) const; + + //! creates/loads an archive from the file. + //! \return Pointer to the created archive. Returns 0 if loading failed. + virtual irr::io::IFileArchive* createArchive(irr::io::IReadFile* file, bool ignoreCase, bool ignorePaths) const; + +private: + irr::io::IFileSystem* FileSystem; +}; + +class CPkgReader : public virtual irr::io::IFileArchive, virtual irr::io::CFileList +{ +public: + + //! constructor + CPkgReader (irr::io::IReadFile* file, bool ignoreCase, bool ignorePaths); + + //! destructor + virtual ~CPkgReader (); + + //! opens a file by file name + virtual irr::io::IReadFile* createAndOpenFile (const irr::io::path& filename); + + //! opens a file by index + virtual irr::io::IReadFile* createAndOpenFile (unsigned int index); + + //! returns the list of files + virtual const IFileList* getFileList () const; + + //! get the archive type + virtual irr::io::E_FILE_ARCHIVE_TYPE getType () const; + +protected: + void scanPkgHeader (); + + char* readSizedString (); + + irr::io::IFileSystem* mFileSystem; + irr::io::IReadFile* mFile; +}; + + +#endif //WALLENGINE_CPKGREADER_H diff --git a/wallpaperengine/project.cpp b/wallpaperengine/project.cpp index e3ccc68..b812014 100644 --- a/wallpaperengine/project.cpp +++ b/wallpaperengine/project.cpp @@ -3,20 +3,16 @@ #include #include -#include "fs/fileResolver.h" +#include "wallpaperengine/fs/utils.h" #include "project.h" #include "irrlicht.h" namespace wp { - project::project () + project::project (irr::io::path& jsonfile_path) { - irr::io::path projectFile = wp::fs::resolver.resolveOnWorkingDirectory ("project.json"); - - std::ifstream _in (projectFile.c_str ()); - this->m_content = ""; - this->m_content.append (std::istreambuf_iterator (_in), std::istreambuf_iterator ()); + this->m_content = wp::fs::utils::loadFullFile (jsonfile_path); this->m_projectFile = json::parse (this->m_content); json::const_iterator file_it = this->m_projectFile.find ("file"); @@ -26,8 +22,8 @@ namespace wp if (file_it != this->m_projectFile.end ()) { // load scene file - this->m_file = wp::fs::resolver.resolveOnWorkingDirectory (*file_it); - this->m_scene = new scene (this->m_file.c_str ()); + this->m_file = (*file_it).get ().c_str (); + this->m_scene = new scene (this->m_file); } if (type_it != this->m_projectFile.end ()) diff --git a/wallpaperengine/project.h b/wallpaperengine/project.h index ec46218..2385aac 100644 --- a/wallpaperengine/project.h +++ b/wallpaperengine/project.h @@ -12,7 +12,7 @@ namespace wp class project { public: - project (); + project (irr::io::path& jsonfile_path); scene* getScene (); diff --git a/wallpaperengine/scene.cpp b/wallpaperengine/scene.cpp index 3c4c48b..2540a1a 100644 --- a/wallpaperengine/scene.cpp +++ b/wallpaperengine/scene.cpp @@ -6,15 +6,15 @@ #include #include +#include "wallpaperengine/fs/utils.h" + namespace wp { using json = nlohmann::json; - scene::scene (irr::io::path file) + scene::scene (irr::io::path& file) { - std::ifstream _in (file.c_str ()); - this->m_content = ""; - this->m_content.append (std::istreambuf_iterator (_in), std::istreambuf_iterator ()); + this->m_content = wp::fs::utils::loadFullFile (file); this->m_json = json::parse (this->m_content); // check basic elements diff --git a/wallpaperengine/scene.h b/wallpaperengine/scene.h index 97ea0ad..48b428c 100644 --- a/wallpaperengine/scene.h +++ b/wallpaperengine/scene.h @@ -16,7 +16,7 @@ namespace wp class scene : public wp::video::node { public: - scene (irr::io::path file); + scene (irr::io::path& file); ~scene (); camera* getCamera (); diff --git a/wallpaperengine/shaders/compiler.cpp b/wallpaperengine/shaders/compiler.cpp index 552b311..da3a181 100644 --- a/wallpaperengine/shaders/compiler.cpp +++ b/wallpaperengine/shaders/compiler.cpp @@ -7,7 +7,7 @@ #include // filesystem -#include +#include // video engine #include @@ -54,9 +54,6 @@ namespace wp // append file content this->m_type = type; - this->m_resolver = wp::fs::resolver.clone (); - this->m_resolver.appendEnvironment (wp::config::path::shaders); - this->m_file = file; } @@ -201,7 +198,7 @@ namespace wp std::string compiler::lookupShaderFile (std::string filename) { // get file information - irr::io::path shader = this->m_resolver.resolve (filename.c_str ()); + irr::io::path shader = ("shaders/" + filename).c_str (); if (shader == "") { diff --git a/wallpaperengine/shaders/compiler.h b/wallpaperengine/shaders/compiler.h index 49f42b2..55830a8 100644 --- a/wallpaperengine/shaders/compiler.h +++ b/wallpaperengine/shaders/compiler.h @@ -6,7 +6,7 @@ #include #include -#include +#include namespace wp { @@ -193,7 +193,7 @@ namespace wp /** * The file resolver to be used by the compiler to load the files */ - wp::fs::fileResolver m_resolver; + wp::fs::utils m_resolver; }; } } diff --git a/wallpaperengine/texture.cpp b/wallpaperengine/texture.cpp index 5ab6c2f..b250320 100644 --- a/wallpaperengine/texture.cpp +++ b/wallpaperengine/texture.cpp @@ -6,7 +6,7 @@ namespace wp { - texture::texture (irr::io::path file) + texture::texture (irr::io::path& file) { this->m_texture = wp::irrlicht::driver->getTexture (file); } diff --git a/wallpaperengine/texture.h b/wallpaperengine/texture.h index 6ae43e9..fd45b81 100644 --- a/wallpaperengine/texture.h +++ b/wallpaperengine/texture.h @@ -8,7 +8,7 @@ namespace wp class texture { public: - texture (irr::io::path file); + texture (irr::io::path& file); irr::video::ITexture* getIrrTexture ();