Skip to content

Commit

Permalink
#6052: Adjust parser to treat mirrorRenderMap dimensions optional.
Browse files Browse the repository at this point in the history
The token must not be exhausted when looking for the dimensions.
  • Loading branch information
codereader committed Aug 5, 2022
1 parent bb408aa commit 53255f1
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 28 deletions.
14 changes: 14 additions & 0 deletions libs/string/convert.h
Expand Up @@ -257,6 +257,20 @@ inline bool tryConvertToFloat(const std::string& src, float& value)
return lastChar != firstChar;
}

// Attempts to convert the given source string to an int value,
// returning true on success. The value reference will then be holding
// the resulting int value (or 0 in case of failure).
// Note: this is using the exception-less std::strtol, making it preferable
// over the string::convert<int> method (in certain hot code paths).
inline bool tryConvertToInt(const std::string& src, int& value)
{
char* lastChar;
auto* firstChar = src.c_str();
value = static_cast<int>(std::strtol(firstChar, &lastChar, 10));

return lastChar != firstChar;
}

// Convert the given type to a std::string
template<typename Src>
inline std::string to_string(const Src& value)
Expand Down
61 changes: 33 additions & 28 deletions radiantcore/shaders/ShaderTemplate.cpp
Expand Up @@ -598,10 +598,8 @@ bool ShaderTemplate::parseBlendMaps(parser::DefTokeniser& tokeniser, const std::
{
if (token == "map")
{
_currentLayer->setBindableTexture(
MapExpression::createForToken(tokeniser)
);
_currentLayer->setMapType(IShaderLayer::MapType::Map);
_currentLayer->setBindableTexture(MapExpression::createForToken(tokeniser));
// Don't reset the map type of this layer, "map" can occur in multiple scenarios
}
else if (token == "cameracubemap")
{
Expand Down Expand Up @@ -663,35 +661,13 @@ bool ShaderTemplate::parseBlendMaps(parser::DefTokeniser& tokeniser, const std::
else if (token == "remoterendermap")
{
_currentLayer->setMapType(IShaderLayer::MapType::RemoteRenderMap);

try
{
auto width = std::stoi(tokeniser.nextToken());
auto height = std::stoi(tokeniser.nextToken());
_currentLayer->setRenderMapSize(Vector2(width, height));
}
catch (std::logic_error& e)
{
rWarning() << "Error parsing remoteRenderMap. Expected two integers: "
<< e.what() << std::endl;
}
parseRenderMapSize(tokeniser, true); // remoteRenderMap dimension is mandatory
}
else if (token == "mirrorrendermap")
{
_currentLayer->setMapType(IShaderLayer::MapType::MirrorRenderMap);
_currentLayer->setTexGenType(IShaderLayer::TexGenType::TEXGEN_SCREEN);

try
{
auto width = std::stoi(tokeniser.nextToken());
auto height = std::stoi(tokeniser.nextToken());
_currentLayer->setRenderMapSize(Vector2(width, height));
}
catch (std::invalid_argument& e)
{
rWarning() << "Error parsing mirrorRenderMap. Expected two integers: "
<< e.what() << std::endl;
}
parseRenderMapSize(tokeniser, true); // mirrorRenderMap dimension is optional
}
else
{
Expand All @@ -701,6 +677,35 @@ bool ShaderTemplate::parseBlendMaps(parser::DefTokeniser& tokeniser, const std::
return true;
}

void ShaderTemplate::parseRenderMapSize(parser::DefTokeniser& tokeniser, bool optional)
{
// Parse the dimensions without immediately exhausting the upcoming token
// Will not exhaust the tokens that are not convertible to an integer
int width;
if (string::tryConvertToInt(tokeniser.peek(), width))
{
tokeniser.nextToken(); // exhaust
}
else if (!optional)
{
rWarning() << "Error parsing render map width. Expected two integers." << std::endl;
return;
}

int height;
if (string::tryConvertToInt(tokeniser.peek(), height))
{
tokeniser.nextToken(); // exhaust
}
else if (!optional)
{
rWarning() << "Error parsing render map height. Expected two integers." << std::endl;
return;
}

_currentLayer->setRenderMapSize({ width, height });
}

bool ShaderTemplate::parseStageModifiers(parser::DefTokeniser& tokeniser,
const std::string& token)
{
Expand Down
1 change: 1 addition & 0 deletions radiantcore/shaders/ShaderTemplate.h
Expand Up @@ -551,6 +551,7 @@ class ShaderTemplate final :
bool parseMaterialType(parser::DefTokeniser&, const std::string&);
bool parseCondition(parser::DefTokeniser&, const std::string&);
IShaderExpression::Ptr parseSingleExpressionTerm(parser::DefTokeniser& tokeniser);
void parseRenderMapSize(parser::DefTokeniser&, bool optional);

bool saveLayer();
void determineCoverage();
Expand Down

0 comments on commit 53255f1

Please sign in to comment.