Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/origin/openmapsfrompk4'
Browse files Browse the repository at this point in the history
# Conflicts:
#	radiantcore/Makefile.am
#	tools/msvc/DarkRadiant.vcxproj.filters
#	tools/msvc/DarkRadiantCore.vcxproj
#	tools/msvc/DarkRadiantCore.vcxproj.filters
#	tools/msvc/Tests/Tests.vcxproj.filters
  • Loading branch information
codereader committed Nov 30, 2020
2 parents 505a16d + 1b0fb80 commit e10a696
Show file tree
Hide file tree
Showing 86 changed files with 6,187 additions and 997 deletions.
64 changes: 64 additions & 0 deletions include/iarchive.h
Expand Up @@ -17,6 +17,24 @@

class InputStream;

// Interface providing additional info about a given file
// used by the FileInfo structure to load extended info
// file like size, containing archive, physical path, etc.
class IArchiveFileInfoProvider
{
public:
virtual ~IArchiveFileInfoProvider() {}

// Get file size of the file given by the relative path (like "def/func.def") in bytes
virtual std::size_t getFileSize(const std::string& relativePath) = 0;

// Returns true if this file is an actual file on disk (as opposed to a file in a PAK)
virtual bool getIsPhysical(const std::string& relativePath) = 0;

// Returns the absolute file system path to the archive the given file is located in
virtual std::string getArchivePath(const std::string& relativePath) = 0;
};

/**
* A file opened in binary mode.
* \ingroup vfs
Expand Down Expand Up @@ -57,3 +75,49 @@ class ArchiveTextFile :
};
typedef std::shared_ptr<ArchiveTextFile> ArchiveTextFilePtr;

/**
* Representation of an archive in the virtual filesystem.
* This might be a PK4/ZIP file or a regular mod directory.
*
* \ingroup vfs
*/
class IArchive
{
public:
typedef std::shared_ptr<IArchive> Ptr;

virtual ~IArchive() {}

class Visitor
{
public:
virtual ~Visitor() {}

// Invoked for each file in an Archive
virtual void visitFile(const std::string& name, IArchiveFileInfoProvider& infoProvider) = 0;

// Invoked for each directory in an Archive. Return true to skip the directory.
virtual bool visitDirectory(const std::string& name, std::size_t depth) = 0;
};

/// \brief Returns a new object associated with the file identified by \p name, or 0 if the file cannot be opened.
/// Name comparisons are case-insensitive.
virtual ArchiveFilePtr openFile(const std::string& name) = 0;

/// \brief Returns a new object associated with the file identified by \p name, or 0 if the file cannot be opened.
/// Name comparisons are case-insensitive.
virtual ArchiveTextFilePtr openTextFile(const std::string& name) = 0;

/// Returns true if the file identified by \p name can be opened.
/// Name comparisons are case-insensitive.
virtual bool containsFile(const std::string& name) = 0;

/// \brief Performs a depth-first traversal of the archive tree starting at \p root.
/// Traverses the entire tree if \p root is "".
/// When a file is encountered, calls \c visitor.file passing the file name.
/// When a directory is encountered, calls \c visitor.directory passing the directory name.
/// Skips the directory if \c visitor.directory returned true.
/// Root comparisons are case-insensitive.
/// Names are mixed-case.
virtual void traverse(Visitor& visitor, const std::string& root) = 0;
};
66 changes: 59 additions & 7 deletions include/ifilesystem.h
Expand Up @@ -14,11 +14,7 @@
#include <algorithm>

#include "imodule.h"

class ArchiveFile;
typedef std::shared_ptr<ArchiveFile> ArchiveFilePtr;
class ArchiveTextFile;
typedef std::shared_ptr<ArchiveTextFile> ArchiveTextFilePtr;
#include "iarchive.h"

namespace vfs
{
Expand Down Expand Up @@ -61,8 +57,30 @@ inline std::ostream& operator<< (std::ostream& s, const Visibility& v)
}

/// Metadata about a file in the virtual filesystem
struct FileInfo
class FileInfo
{
private:
// Info provider to load additional info on demand, used by e.g. getSize()
IArchiveFileInfoProvider* _infoProvider;
public:
FileInfo(const std::string& topDir_, const std::string& name_,
Visibility visibility_) :
_infoProvider(nullptr),
topDir(topDir_),
name(name_),
visibility(visibility_)
{}

FileInfo(const std::string& topDir_, const std::string& name_,
Visibility visibility_, IArchiveFileInfoProvider& infoProvider) :
FileInfo(topDir_, name_, visibility_)
{
_infoProvider = &infoProvider;
}

FileInfo(const FileInfo& other) = default;
FileInfo& operator=(const FileInfo& other) = default;

/// Top-level directory (if any), e.g. "def" or "models"
std::string topDir;

Expand All @@ -81,6 +99,24 @@ struct FileInfo
return topDir + (topDir.back() == '/' ? "" : "/") + name;
}

// See IArchiveFileInfoProvider::getFileSize
std::size_t getSize() const
{
return _infoProvider ? _infoProvider->getFileSize(fullPath()) : 0;
}

// See IArchiveFileInfoProvider::getIsPhysicalFile
bool getIsPhysicalFile() const
{
return _infoProvider ? _infoProvider->getIsPhysical(fullPath()) : false;
}

// See IArchiveFileInfoProvider::getArchivePath
std::string getArchivePath() const
{
return _infoProvider ? _infoProvider->getArchivePath(fullPath()) : "";
}

/// Equality comparison with another FileInfo
bool operator== (const FileInfo& rhs) const
{
Expand Down Expand Up @@ -149,6 +185,9 @@ class VirtualFileSystem :
/// \brief Shuts down the filesystem.
virtual void shutdown() = 0;

// Returns the extension set this VFS instance has been initialised with
virtual const ExtensionSet& getArchiveExtensions() const = 0;

// greebo: Adds/removes observers to/from the VFS
// Observers should also check isInitialised() after adding themselves
// since the VFS might have been initialised already. Calling addObserver()
Expand All @@ -174,6 +213,11 @@ class VirtualFileSystem :
/// This is a variant of openTextFile taking an absolute path as argument.
virtual ArchiveTextFilePtr openTextFileInAbsolutePath(const std::string& filename) = 0;

// Opens an independent archive located in the given physical path.
// (This archive can be located somewhere outside the current VFS hierarchy.)
// Loading this archive won't have any effect on the VFS setup, it is opened stand-alone.
virtual IArchive::Ptr openArchiveInAbsolutePath(const std::string& pathToArchive) = 0;

/// \brief Calls the visitor function for each file under \p basedir matching \p extension.
/// Use "*" as \p extension to match all file extensions.
virtual void forEachFile(const std::string& basedir,
Expand All @@ -183,12 +227,20 @@ class VirtualFileSystem :

// Similar to forEachFile, this routine traverses an absolute path
// searching for files matching a certain extension and invoking
// the givne visitor functor on each occurrence.
// the given visitor functor on each occurrence.
virtual void forEachFileInAbsolutePath(const std::string& path,
const std::string& extension,
const VisitorFunc& visitorFunc,
std::size_t depth = 1) = 0;

// Similar to forEachFile, this routine traverses an archive in the given path
// searching for files matching a certain extension and invoking
// the given visitor functor on each occurrence.
virtual void forEachFileInArchive(const std::string& absoluteArchivePath,
const std::string& extension,
const VisitorFunc& visitorFunc,
std::size_t depth = 1) = 0;

/// \brief Returns the absolute filename for a relative \p name, or "" if not found.
virtual std::string findFile(const std::string& name) = 0;

Expand Down
19 changes: 14 additions & 5 deletions include/ifiletypes.h
Expand Up @@ -7,9 +7,6 @@
/**
* Simple structure to store a file pattern (e.g. "*.map")
* along with its name (e.g. "Map files") and extension.
*
* If a module has been registering itself for a certain
* filetype/extension combo, its name is in associatedModule.
*/
struct FileTypePattern
{
Expand All @@ -22,13 +19,18 @@ struct FileTypePattern
// The mask pattern ("*.map")
std::string pattern;

// Optional icon string, referring to an image in the bitmaps folder
std::string icon;

// Constructor with optional initialisation parameters
FileTypePattern(const std::string& name_ = "",
const std::string& extension_ = "",
const std::string& pattern_ = "") :
const std::string& pattern_ = "",
const std::string& icon_ = "") :
name(name_),
extension(extension_),
pattern(pattern_)
pattern(pattern_),
icon(icon_)
{}
};
typedef std::list<FileTypePattern> FileTypePatterns;
Expand Down Expand Up @@ -68,6 +70,12 @@ class IFileTypeRegistry :
* @returns: a list of FileTypePatterns containing extension, display name, etc.
*/
virtual FileTypePatterns getPatternsForType(const std::string& fileType) = 0;

/**
* Tries to find an icon file for the given extension. If not empty,
* the returned string refers to a filename in the bitmaps/ folder.
*/
virtual std::string getIconForExtension(const std::string& extension) = 0;
};

namespace filetype
Expand All @@ -79,6 +87,7 @@ const char* const TYPE_MAP_EXPORT = "mapexport";
const char* const TYPE_PREFAB = "prefab";
const char* const TYPE_REGION = "region";
const char* const TYPE_MODEL_EXPORT = "modelexport";
const char* const TYPE_PAK = "pak";

}

Expand Down
53 changes: 46 additions & 7 deletions include/imapresource.h
Expand Up @@ -30,16 +30,42 @@ class IMapResource
virtual bool load() = 0;

// Exception type thrown by the the MapResource implementation
struct OperationException :
class OperationException :
public std::runtime_error
{
private:
bool _cancelled;

public:
OperationException(const std::string& msg) :
runtime_error(msg)
{
rError() << "MapResource operation failed: " << msg << std::endl;
}
OperationException(msg, false)
{}

OperationException(const std::string& msg, bool cancelled) :
runtime_error(msg),
_cancelled(cancelled)
{
if (!_cancelled)
{
rError() << "MapResource operation failed: " << msg << std::endl;
}
}

// Returns true if the operation has been cancelled by the user
bool operationCancelled() const
{
return _cancelled;
}
};

/**
* Returns true if this resource refers to a read-only location.
* This returns true for archived resources (loaded from PAK files),
* but might be returning true for other resource types too (e.g. when
* this process is lacking write access to the resource).
*/
virtual bool isReadOnly() = 0;

/**
* Save this resource
*
Expand All @@ -54,6 +80,10 @@ class IMapResource

virtual const scene::IMapRootNodePtr& getRootNode() = 0;

// Sets the root node of this resource. The use case is to create a resource
// around an existing map root for e.g. saving a read-only resource to a new path
virtual void setRootNode(const scene::IMapRootNodePtr& root) = 0;

virtual void clear() = 0;
};
typedef std::shared_ptr<IMapResource> IMapResourcePtr;
Expand All @@ -65,9 +95,18 @@ class IMapResourceManager :
{
public:
/**
* Load the named map resource from VFS or from a physical path.
* Create a named map resource from VFS or from a physical path.
*/
virtual IMapResourcePtr loadFromPath(const std::string& path) = 0;
virtual IMapResourcePtr createFromPath(const std::string& path) = 0;

/**
* Create a named map resource that is contained within a PAK archive
* outside the VFS.
* archivePath is the absolute path to the archive file, e.g. "/home/greebo/outpost.pk4"
* filePathWithinArchive is the relative path within the archive, e.g. "maps/outpost.map"
*/
virtual IMapResourcePtr createFromArchiveFile(const std::string& archivePath,
const std::string& filePathWithinArchive) = 0;

// Signal emitted when a MapExport is starting / is finished
typedef sigc::signal<void, const scene::IMapRootNodePtr&> ExportEvent;
Expand Down
Binary file added install/bitmaps/file.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added install/bitmaps/package.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions install/menu.xml
Expand Up @@ -4,6 +4,7 @@
<menuItem name="new" caption="&amp;New Map" command="NewMap" />
<menuSeparator />
<menuItem name="open" caption="&amp;Open..." command="OpenMap" />
<menuItem name="openMapFromProject" caption="&amp;Open Map from Project..." command="OpenMapFromProject" />
<menuItem name="import" caption="&amp;Import map..." command="ImportMap" />
<menuItem name="loadprefab" caption="Import &amp;prefab..." command="LoadPrefab" />
<menuSeparator />
Expand Down
1 change: 0 additions & 1 deletion libs/debugging/ScopedDebugTimer.h
Expand Up @@ -36,7 +36,6 @@
#endif

#include <string>
#include "stream/TextFileInputStream.h"

namespace {

Expand Down
2 changes: 1 addition & 1 deletion libs/os/file.h
Expand Up @@ -99,7 +99,7 @@ inline bool fileOrDirExists(const fs::path& path)
}
}

// Returns the file size in bytes, or static_cast<uintmax_t>(-1)
// Returns the file size in bytes, or static_cast<std::size_t>(-1)
inline std::size_t getFileSize(const std::string& path)
{
try
Expand Down
29 changes: 29 additions & 0 deletions libs/os/filesize.h
@@ -0,0 +1,29 @@
#pragma once

#include <fmt/format.h>

namespace os
{

// Formats the given number in bytes/kB/MB/GB
inline std::string getFormattedFileSize(std::size_t size)
{
if (size > 1024 * 1024 * 1024)
{
return fmt::format("{0:0.2f} GB", (static_cast<double>(size) / (1024 * 1024 * 1024)));
}
else if (size > 1024 * 1024)
{
return fmt::format("{0:0.1f} MB", (static_cast<double>(size) / (1024 * 1024)));
}
else if (size > 1024)
{
return fmt::format("{0:0.0f} kB", (static_cast<double>(size) / 1024));
}
else
{
return fmt::format("{0:d} bytes", size);
}
}

}

0 comments on commit e10a696

Please sign in to comment.