Skip to content

Commit

Permalink
#5565: Fall back to the user engine path if the mod path is empty (wh…
Browse files Browse the repository at this point in the history
…ich is also the case in the unit test scenario).

More work on the unit tests.
  • Loading branch information
codereader committed Mar 28, 2021
1 parent efcebd8 commit 9efd76f
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 13 deletions.
7 changes: 7 additions & 0 deletions libs/materials/ParseLib.h
Expand Up @@ -7,6 +7,13 @@
namespace shaders
{

// A regex pattern that can be used to detect a material name in a single line of a material file
// which is optionally detecting an opening curly brace in the same line
inline std::string getDeclNamePatternForMaterialName(const std::string& name)
{
return "^\\s*" + name + "\\s*(\\{*).*$";
}

constexpr std::pair<const char*, Material::Flags> MaterialFlagKeywords[]
{
{ "noShadows", Material::FLAG_NOSHADOWS },
Expand Down
9 changes: 8 additions & 1 deletion radiantcore/shaders/Doom3ShaderSystem.cpp
Expand Up @@ -29,6 +29,7 @@
#include "stream/TemporaryOutputStream.h"
#include "string/predicate.h"
#include "string/replace.h"
#include "materials/ParseLib.h"
#include "parser/DefBlockTokeniser.h"
#include <functional>

Expand Down Expand Up @@ -463,6 +464,12 @@ void Doom3ShaderSystem::saveMaterial(const std::string& name)

// Construct the output path for this material
fs::path outputPath = GlobalGameManager().getModPath();

if (outputPath.empty())
{
outputPath = GlobalGameManager().getUserEnginePath();
}

outputPath /= material->getShaderFileInfo().fullPath();

auto outputDir = os::getContainingDir(outputPath.string());
Expand Down Expand Up @@ -491,7 +498,7 @@ void Doom3ShaderSystem::saveMaterial(const std::string& name)
}

// Write the file to the output stream, up to the point the material def should be written to
std::regex pattern("^[\\s]*" + material->getName() + "\\s*(\\{)*\\s*$");
std::regex pattern(getDeclNamePatternForMaterialName(material->getName()));

decl::SpliceHelper::PipeStreamUntilInsertionPoint(inheritStream, stream, pattern);

Expand Down
4 changes: 2 additions & 2 deletions radiantcore/shaders/MaterialSourceGenerator.cpp
Expand Up @@ -656,10 +656,10 @@ void MaterialSourceGenerator::WriteMaterialGenerationComment(std::ostream& strea

void MaterialSourceGenerator::WriteFullMaterialToStream(std::ostream& stream, const MaterialPtr& material)
{
stream << material->getName();
stream << material->getName() << "\n";
stream << "{";
stream << material->getDefinition();
stream << "}" << std::endl << std::endl;
stream << "}" << "\n" << std::endl;
}

}
50 changes: 40 additions & 10 deletions test/MaterialExport.cpp
@@ -1,7 +1,9 @@
#include "RadiantTest.h"

#include <regex>
#include "ishaders.h"
#include "string/trim.h"
#include "string/replace.h"
#include "materials/ParseLib.h"
#include <fmt/format.h>

Expand Down Expand Up @@ -1070,16 +1072,16 @@ TEST_F(MaterialExportTest, BlendShortcuts)
material->revertModifications();
}

void expectFileContainsText(const fs::path& path, const std::string& textToFind)
bool fileContainsText(const fs::path& path, const std::string& textToFind)
{
std::stringstream contents;
std::stringstream contentStream;
std::ifstream input(path);

contents << input.rdbuf();
contentStream << input.rdbuf();

EXPECT_NE(contents.str().find(textToFind), std::string::npos)
<< "The text '" << textToFind << "' was not found "
<< " in the file " << path;
std::string contents = string::replace_all_copy(contentStream.str(), "\r\n", "\n");

return contents.find(textToFind) != std::string::npos;
}

class BackupCopy
Expand All @@ -1104,6 +1106,29 @@ class BackupCopy
}
};

TEST_F(MaterialExportTest, MaterialDefDetectionRegex)
{
std::smatch matches;
std::string line1("textures/exporttest/renderBump1 { // comment");
std::string line2(" textures/exporttest/renderBump1 { // comment");
std::string line3("textures/exporttest/renderBump1");
std::string line4("textures/exporttest/renderBump1 // comment");

std::regex pattern(shaders::getDeclNamePatternForMaterialName("textures/exporttest/renderBump1"));

EXPECT_TRUE(std::regex_match(line1, matches, pattern));
EXPECT_EQ(matches[1].str(), "{");

EXPECT_TRUE(std::regex_match(line2, matches, pattern));
EXPECT_EQ(matches[1].str(), "{");

EXPECT_TRUE(std::regex_match(line3, matches, pattern));
EXPECT_EQ(matches[1].str(), "");

EXPECT_TRUE(std::regex_match(line4, matches, pattern));
EXPECT_EQ(matches[1].str(), "");
}

TEST_F(MaterialExportTest, WritingMaterialFiles)
{
// Create a backup copy of the material file we're going to manipulate
Expand All @@ -1112,16 +1137,21 @@ TEST_F(MaterialExportTest, WritingMaterialFiles)

std::string description = "Newly Generated Block";

expectFileContainsText(exportTestFile, "textures/exporttest/renderBump1 {\n"
" renderBump textures/output.tga models/hipoly\n"
"}");
auto originalDefinition = "textures/exporttest/renderBump1 { // Opening brace in the same line as the name (DON'T REMOVE THIS)\n"
" renderBump textures/output.tga models/hipoly \n"
"}";
EXPECT_TRUE(fileContainsText(exportTestFile, originalDefinition)) << "Original definition not found in file " << exportTestFile;

auto material = GlobalMaterialManager().getMaterial("textures/exporttest/renderBump1");
material->setDescription(description);

GlobalMaterialManager().saveMaterial(material->getName());

expectFileContainsText(exportTestFile, "textures/exporttest/renderBump1\n{" + material->getDefinition() + "}");
EXPECT_TRUE(fileContainsText(exportTestFile, "textures/exporttest/renderBump1\n{" + material->getDefinition() + "}"))
<< "New definition not found in file";

EXPECT_FALSE(fileContainsText(exportTestFile, originalDefinition))
<< "Original definition still in file";
}

}

0 comments on commit 9efd76f

Please sign in to comment.