Skip to content

Commit

Permalink
#5108: Add ArchivedMapResource specialisation, which will load the ma…
Browse files Browse the repository at this point in the history
…p from any PAK file.

Add two virtual method to be overridden by the ArchivedMapResource
  • Loading branch information
codereader committed Nov 29, 2020
1 parent 753549d commit d9f4dae
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 34 deletions.
13 changes: 11 additions & 2 deletions include/imapresource.h
Expand Up @@ -83,9 +83,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
2 changes: 1 addition & 1 deletion radiant/ui/prefabselector/PrefabSelector.cpp
Expand Up @@ -402,7 +402,7 @@ void PrefabSelector::onSelectionChanged(wxutil::FileSystemView::SelectionChanged

const auto& prefabPath = ev.GetSelectedPath();

_mapResource = GlobalMapResourceManager().loadFromPath(prefabPath);
_mapResource = GlobalMapResourceManager().createFromPath(prefabPath);

if (!_mapResource)
{
Expand Down
20 changes: 20 additions & 0 deletions radiantcore/map/ArchivedMapResource.h
@@ -0,0 +1,20 @@
#pragma once

#include "MapResource.h"

namespace map
{

class ArchivedMapResource :
public MapResource
{
public:
ArchivedMapResource(const std::string& archivePath, const std::string& filePathWithinArchive) :
MapResource(filePathWithinArchive)
{}

protected:

};

}
6 changes: 4 additions & 2 deletions radiantcore/map/Map.cpp
Expand Up @@ -101,7 +101,9 @@ void Map::loadMapResourceFromLocation(const MapLocation& location)
// Map loading started
emitMapEvent(MapLoading);

_resource = GlobalMapResourceManager().loadFromPath(location.path);
_resource = location.isArchive ?
GlobalMapResourceManager().createFromArchiveFile(location.path, location.archiveRelativePath) :
GlobalMapResourceManager().createFromPath(location.path);

if (!_resource)
{
Expand Down Expand Up @@ -394,7 +396,7 @@ bool Map::import(const std::string& filename)
{
bool success = false;

IMapResourcePtr resource = GlobalMapResourceManager().loadFromPath(filename);
IMapResourcePtr resource = GlobalMapResourceManager().createFromPath(filename);

try
{
Expand Down
55 changes: 35 additions & 20 deletions radiantcore/map/MapResource.cpp
Expand Up @@ -253,11 +253,13 @@ RootNodePtr MapResource::loadMapNode()
{
RootNodePtr rootNode;

// Build the map path
auto fullpath = getAbsoluteResourcePath();
// Open a stream - will throw on failure
auto stream = openMapfileStream();

// Open a stream (from physical file or VFS) - will throw on failure
auto stream = openFileStream(fullpath);
if (!stream || !stream->isOpen())
{
throw OperationException(_("Could not open map stream"));
}

try
{
Expand All @@ -283,31 +285,19 @@ RootNodePtr MapResource::loadMapNode()
// Check if an info file is supported by this map format
if (format->allowInfoFileCreation())
{
try
{
// Load for an additional info file
auto infoFilename = fullpath.substr(0, fullpath.rfind('.'));
infoFilename += getInfoFileExtension();
auto infoFileStream = openInfofileStream();

auto infoFileStream = openFileStream(infoFilename);

if (infoFileStream->isOpen())
{
loader.loadInfoFile(infoFileStream->getStream(), rootNode);
}
}
catch (const OperationException& ex)
if (infoFileStream && infoFileStream->isOpen())
{
// Info file load file does not stop us, just issue a warning
rWarning() << ex.what() << std::endl;
loader.loadInfoFile(infoFileStream->getStream(), rootNode);
}
}
}
catch (const OperationException& ex)
{
// Re-throw the exception, prepending the map file path to the message (if not cancelled)
throw ex.operationCancelled() ? ex :
OperationException(fmt::format(_("Failure reading map file:\n{0}\n\n{1}"), fullpath, ex.what()));
OperationException(fmt::format(_("Failure reading map file:\n{0}\n\n{1}"), getAbsoluteResourcePath(), ex.what()));
}

return rootNode;
Expand All @@ -326,6 +316,31 @@ stream::MapResourceStream::Ptr MapResource::openFileStream(const std::string& pa
return stream;
}

stream::MapResourceStream::Ptr MapResource::openMapfileStream()
{
return openFileStream(getAbsoluteResourcePath());
}

stream::MapResourceStream::Ptr MapResource::openInfofileStream()
{
try
{
auto fullpath = getAbsoluteResourcePath();

// Load for an additional info file
auto infoFilename = fullpath.substr(0, fullpath.rfind('.'));
infoFilename += getInfoFileExtension();

return openFileStream(infoFilename);
}
catch (const OperationException& ex)
{
// Info file load file does not stop us, just issue a warning
rWarning() << ex.what() << std::endl;
return stream::MapResourceStream::Ptr();
}
}

std::string MapResource::getInfoFileExtension()
{
std::string extension = game::current::getValue<std::string>(GKEY_INFO_FILE_EXTENSION);
Expand Down
13 changes: 9 additions & 4 deletions radiantcore/map/MapResource.h
Expand Up @@ -2,7 +2,6 @@

#include "imapresource.h"
#include "imapformat.h"
#include "imapinfofile.h"
#include "imodel.h"
#include "imap.h"
#include <set>
Expand Down Expand Up @@ -50,6 +49,15 @@ class MapResource :
static void saveFile(const MapFormat& format, const scene::IMapRootNodePtr& root,
const GraphTraversalFunc& traverse, const std::string& filename);

protected:
// Implementation-specific method to open the stream of the primary .map or .mapx file
// May return an empty reference, may throw OperationException on failure
virtual stream::MapResourceStream::Ptr openMapfileStream();

// Implementation-specific method to open the info file stream (.darkradiant) file
// May return an empty reference, may throw OperationException on failure
virtual stream::MapResourceStream::Ptr openInfofileStream();

private:
void constructPaths(const std::string& resourcePath);
std::string getAbsoluteResourcePath();
Expand All @@ -74,8 +82,5 @@ class MapResource :
// Checks if file can be overwritten (throws on failure)
static void throwIfNotWriteable(const fs::path& path);
};
// Resource pointer types
typedef std::shared_ptr<MapResource> MapResourcePtr;
typedef std::weak_ptr<MapResource> MapResourceWeakPtr;

} // namespace map
13 changes: 9 additions & 4 deletions radiantcore/map/MapResourceManager.cpp
Expand Up @@ -6,16 +6,22 @@
#include "os/path.h"
#include "module/StaticModule.h"
#include "MapResource.h"
#include "ArchivedMapResource.h"

namespace map
{

IMapResourcePtr MapResourceManager::loadFromPath(const std::string& path)
IMapResourcePtr MapResourceManager::createFromPath(const std::string& path)
{
// Create a new MapResource and return it.
return std::make_shared<MapResource>(path);
}

IMapResourcePtr MapResourceManager::createFromArchiveFile(const std::string& archivePath,
const std::string& filePathWithinArchive)
{
return std::make_shared<ArchivedMapResource>(archivePath, filePathWithinArchive);
}

MapResourceManager::ExportEvent& MapResourceManager::signal_onResourceExporting()
{
return _resourceExporting;
Expand All @@ -26,7 +32,6 @@ MapResourceManager::ExportEvent& MapResourceManager::signal_onResourceExported()
return _resourceExported;
}

// RegisterableModule implementation
const std::string& MapResourceManager::getName() const
{
static std::string _name(MODULE_MAPRESOURCEMANAGER);
Expand All @@ -49,7 +54,7 @@ const StringSet& MapResourceManager::getDependencies() const

void MapResourceManager::initialiseModule(const IApplicationContext& ctx)
{
rMessage() << "MapResourceManager::initialiseModule called." << std::endl;
rMessage() << getName() << "::initialiseModule called." << std::endl;
}

// Define the MapResourceManager registerable module
Expand Down
4 changes: 3 additions & 1 deletion radiantcore/map/MapResourceManager.h
Expand Up @@ -14,7 +14,9 @@ class MapResourceManager :
ExportEvent _resourceExported;

public:
IMapResourcePtr loadFromPath(const std::string& path) override;
IMapResourcePtr createFromPath(const std::string& path) override;
IMapResourcePtr createFromArchiveFile(const std::string& archivePath,
const std::string& filePathWithinArchive) override;

ExportEvent& signal_onResourceExporting() override;
ExportEvent& signal_onResourceExported() override;
Expand Down
1 change: 1 addition & 0 deletions tools/msvc/DarkRadiantCore.vcxproj
Expand Up @@ -803,6 +803,7 @@
<ClInclude Include="..\..\radiantcore\map\algorithm\MapImporter.h" />
<ClInclude Include="..\..\radiantcore\map\algorithm\Models.h" />
<ClInclude Include="..\..\radiantcore\map\algorithm\Skins.h" />
<ClInclude Include="..\..\radiantcore\map\ArchivedMapResource.h" />
<ClInclude Include="..\..\radiantcore\map\AutoSaver.h" />
<ClInclude Include="..\..\radiantcore\map\CounterManager.h" />
<ClInclude Include="..\..\radiantcore\map\EditingStopwatch.h" />
Expand Down
3 changes: 3 additions & 0 deletions tools/msvc/DarkRadiantCore.vcxproj.filters
Expand Up @@ -2052,5 +2052,8 @@
<ClInclude Include="..\..\radiantcore\map\MapResourceLoader.h">
<Filter>src\map</Filter>
</ClInclude>
<ClInclude Include="..\..\radiantcore\map\ArchivedMapResource.h">
<Filter>src\map</Filter>
</ClInclude>
</ItemGroup>
</Project>

0 comments on commit d9f4dae

Please sign in to comment.