Skip to content

Commit

Permalink
#5911: Migrate Skin parsing to use the shared DeclParser
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Mar 2, 2022
1 parent e966d6d commit 170eda7
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 161 deletions.
2 changes: 2 additions & 0 deletions include/idecltypes.h
Expand Up @@ -15,6 +15,7 @@ enum class Type
SoundShader,
Model,
Particle,
Skin,
};

inline std::string getTypeName(Type type)
Expand All @@ -27,6 +28,7 @@ inline std::string getTypeName(Type type)
case Type::SoundShader: return "SoundShader";
case Type::Model: return "Model";
case Type::Particle: return "Particle";
case Type::Skin: return "Skin";
default:
throw std::runtime_error("Unhandled decl type");
}
Expand Down
7 changes: 2 additions & 5 deletions radiantcore/shaders/ShaderFileLoader.h
Expand Up @@ -87,11 +87,8 @@ class ShaderFileLoader :
{
rMessage() << _library->getNumDefinitions() << " shader definitions found." << std::endl;

// Move the working copy of our library instance
auto library = _library;
_library.reset();

return library;
// Move the resource contained in the local shared_ptr
return std::move(_library);
}

private:
Expand Down
159 changes: 13 additions & 146 deletions radiantcore/skins/Doom3SkinCache.cpp
Expand Up @@ -10,16 +10,13 @@
namespace skins
{

namespace
{
// CONSTANTS
const char* const SKINS_FOLDER = "skins/";
}

Doom3SkinCache::Doom3SkinCache() :
_defLoader(SKINS_FOLDER, "skin", 1, std::bind(&Doom3SkinCache::loadSkinFiles, this)),
_nullSkin("")
{}
{
_defLoader.signal_finished().connect(
[this]() { _sigSkinsReloaded.emit(); }
);
}

ModelSkin& Doom3SkinCache::capture(const std::string& name)
{
Expand Down Expand Up @@ -62,145 +59,15 @@ sigc::signal<void> Doom3SkinCache::signal_skinsReloaded()
// Realise the skin cache
void Doom3SkinCache::ensureDefsLoaded()
{
// The worker function contained in the def loader will
// fill the local structures when it's done
_defLoader.ensureFinished();
}

void Doom3SkinCache::loadSkinFiles()
{
rMessage() << "[skins] Loading skins." << std::endl;

// Use a functor to traverse the skins directory, catching any parse
// exceptions that may be thrown
try
{
GlobalFileSystem().forEachFile(
SKINS_FOLDER, "skin",
[&] (const vfs::FileInfo& fileInfo)
{
// Open the .skin file and get its contents as a std::string
auto file = GlobalFileSystem().openTextFile(SKINS_FOLDER + fileInfo.name);
assert(file);

std::istream is(&(file->getInputStream()));

try
{
// Pass the contents back to the SkinCache module for parsing
parseFile(is, fileInfo.name);
}
catch (parser::ParseException& e)
{
rError() << "[skins]: in " << fileInfo.name << ": " << e.what() << std::endl;
}
}
);
}
catch (parser::ParseException& e)
{
rError() << "[skins]: " << e.what() << std::endl;
}

rMessage() << "[skins] Found " << _allSkins.size() << " skins." << std::endl;

// Done loading skins
_sigSkinsReloaded.emit();
}

// Parse the contents of a .skin file
void Doom3SkinCache::parseFile(std::istream& contents, const std::string& filename)
{
// Construct a DefTokeniser to parse the file
parser::BasicDefTokeniser<std::istream> tok(contents);

// Call the parseSkin() function for each skin decl
while (tok.hasMoreTokens())
if (_allSkins.empty())
{
try
{
// Try to parse the skin
Doom3ModelSkinPtr modelSkin = parseSkin(tok);
std::string skinName = modelSkin->getName();

modelSkin->setSkinFileName(filename);

auto found = _namedSkins.find(skinName);

// Is this already defined?
if (found != _namedSkins.end())
{
rWarning() << "[skins] in " << filename << ": skin " + skinName +
" previously defined in " +
found->second->getSkinFileName() + "!" << std::endl;
// Don't insert the skin into the list
}
else
{
// Add the populated Doom3ModelSkin to the hashtable and the name to the
// list of all skins
_namedSkins.emplace(skinName, modelSkin);
_allSkins.emplace_back(skinName);
}
}
catch (parser::ParseException& e)
{
rWarning() << "[skins]: in " << filename << ": " << e.what() << std::endl;
}
}
}

// Parse an individual skin declaration
Doom3ModelSkinPtr Doom3SkinCache::parseSkin(parser::DefTokeniser& tok)
{
// [ "skin" ] <name> "{"
// [ "model" <modelname> ]
// ( <sourceTex> <destTex> )*
// "}"

// Parse the skin name, this is either the first token or the second token
// (preceded by "skin")
std::string skinName = tok.nextToken();
// Get the result of the loader and move the contents
auto result = _defLoader.get();

if (skinName == "skin")
{
skinName = tok.nextToken();
_allSkins = std::move(result->allSkins);
_modelSkins = std::move(result->modelSkins);
_namedSkins = std::move(result->namedSkins);
}

tok.assertNextToken("{");

// Create the skin object
auto skin = std::make_shared<Doom3ModelSkin>(skinName);

// Read key/value pairs until end of decl
std::string key = tok.nextToken();
while (key != "}")
{
// Read the value
std::string value = tok.nextToken();

if (value == "}")
{
rWarning() << "[skins] Warning: '}' found where shader name expected in skin: "
<< skinName << std::endl;
}

// If this is a model key, add to the model->skin map, otherwise assume
// this is a remap declaration
if (key == "model")
{
_modelSkins[value].push_back(skinName);
}
else
{
skin->addRemap(key, value);
}

// Get next key
key = tok.nextToken();
}

return skin;
}

const std::string& Doom3SkinCache::getName() const
Expand Down Expand Up @@ -234,7 +101,7 @@ void Doom3SkinCache::refresh()

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

// Load the skins in a new thread
refresh();
Expand All @@ -243,4 +110,4 @@ void Doom3SkinCache::initialiseModule(const IApplicationContext& ctx)
// Module instance
module::StaticModuleRegistration<Doom3SkinCache> skinCacheModule;

} // namespace skins
} // namespace
16 changes: 6 additions & 10 deletions radiantcore/skins/Doom3SkinCache.h
Expand Up @@ -9,7 +9,7 @@
#include <map>
#include <string>
#include <vector>
#include "parser/ThreadedDeclParser.h"
#include "SkinDeclParser.h"

namespace skins
{
Expand All @@ -21,28 +21,24 @@ class Doom3SkinCache :
public ModelSkinCache
{
// Table of named skin objects
typedef std::map<std::string, ModelSkinPtr> NamedSkinMap;
NamedSkinMap _namedSkins;
std::map<std::string, ModelSkinPtr> _namedSkins;

// List of all skins
StringList _allSkins;
std::vector<std::string> _allSkins;

// Map between model paths and a vector of names of the associated skins,
// which are contained in the main NamedSkinMap.
typedef std::map<std::string, std::vector<std::string> > ModelSkinMap;
ModelSkinMap _modelSkins;
std::map<std::string, std::vector<std::string>> _modelSkins;

// Helper which will invoke loadSkinFiles() in a separate thread
parser::ThreadedDeclParser<void> _defLoader;
// Helper which will load the skin defs in a separate thread
SkinDeclParser _defLoader;

// Empty Doom3ModelSkin to return if a named skin is not found
Doom3ModelSkin _nullSkin;

sigc::signal<void> _sigSkinsReloaded;

public:
/* Constructor.
*/
Doom3SkinCache();

/* Return a specific named skin. If the named skin cannot be found, return
Expand Down

0 comments on commit 170eda7

Please sign in to comment.