refactor
This commit is contained in:
170
apps/LoopThroughWithOpenGLCompositing/RuntimeParameterUtils.cpp
Normal file
170
apps/LoopThroughWithOpenGLCompositing/RuntimeParameterUtils.cpp
Normal file
@@ -0,0 +1,170 @@
|
||||
#include "stdafx.h"
|
||||
#include "RuntimeParameterUtils.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cctype>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string TrimText(const std::string& text)
|
||||
{
|
||||
std::size_t start = 0;
|
||||
while (start < text.size() && std::isspace(static_cast<unsigned char>(text[start])))
|
||||
++start;
|
||||
|
||||
std::size_t end = text.size();
|
||||
while (end > start && std::isspace(static_cast<unsigned char>(text[end - 1])))
|
||||
--end;
|
||||
|
||||
return text.substr(start, end - start);
|
||||
}
|
||||
|
||||
bool IsFiniteNumber(double value)
|
||||
{
|
||||
return std::isfinite(value) != 0;
|
||||
}
|
||||
|
||||
std::vector<double> JsonArrayToNumbers(const JsonValue& value)
|
||||
{
|
||||
std::vector<double> numbers;
|
||||
for (const JsonValue& item : value.asArray())
|
||||
{
|
||||
if (item.isNumber())
|
||||
numbers.push_back(item.asNumber());
|
||||
}
|
||||
return numbers;
|
||||
}
|
||||
}
|
||||
|
||||
std::string MakeSafePresetFileStem(const std::string& presetName)
|
||||
{
|
||||
std::string trimmed = TrimText(presetName);
|
||||
std::string safe;
|
||||
safe.reserve(trimmed.size());
|
||||
|
||||
for (unsigned char ch : trimmed)
|
||||
{
|
||||
if (std::isalnum(ch))
|
||||
safe.push_back(static_cast<char>(std::tolower(ch)));
|
||||
else if (ch == ' ' || ch == '-' || ch == '_')
|
||||
{
|
||||
if (safe.empty() || safe.back() == '-')
|
||||
continue;
|
||||
safe.push_back('-');
|
||||
}
|
||||
}
|
||||
|
||||
while (!safe.empty() && safe.back() == '-')
|
||||
safe.pop_back();
|
||||
|
||||
return safe;
|
||||
}
|
||||
|
||||
ShaderParameterValue DefaultValueForDefinition(const ShaderParameterDefinition& definition)
|
||||
{
|
||||
ShaderParameterValue value;
|
||||
switch (definition.type)
|
||||
{
|
||||
case ShaderParameterType::Float:
|
||||
value.numberValues = definition.defaultNumbers.empty() ? std::vector<double>{ 0.0 } : definition.defaultNumbers;
|
||||
break;
|
||||
case ShaderParameterType::Vec2:
|
||||
value.numberValues = definition.defaultNumbers.size() == 2 ? definition.defaultNumbers : std::vector<double>{ 0.0, 0.0 };
|
||||
break;
|
||||
case ShaderParameterType::Color:
|
||||
value.numberValues = definition.defaultNumbers.size() == 4 ? definition.defaultNumbers : std::vector<double>{ 1.0, 1.0, 1.0, 1.0 };
|
||||
break;
|
||||
case ShaderParameterType::Boolean:
|
||||
value.booleanValue = definition.defaultBoolean;
|
||||
break;
|
||||
case ShaderParameterType::Enum:
|
||||
value.enumValue = definition.defaultEnumValue;
|
||||
break;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
bool NormalizeAndValidateParameterValue(const ShaderParameterDefinition& definition, const JsonValue& value, ShaderParameterValue& normalizedValue, std::string& error)
|
||||
{
|
||||
normalizedValue = DefaultValueForDefinition(definition);
|
||||
|
||||
switch (definition.type)
|
||||
{
|
||||
case ShaderParameterType::Float:
|
||||
{
|
||||
if (!value.isNumber())
|
||||
{
|
||||
error = "Expected numeric value for float parameter '" + definition.id + "'.";
|
||||
return false;
|
||||
}
|
||||
double number = value.asNumber();
|
||||
if (!IsFiniteNumber(number))
|
||||
{
|
||||
error = "Float parameter '" + definition.id + "' must be finite.";
|
||||
return false;
|
||||
}
|
||||
if (!definition.minNumbers.empty())
|
||||
number = std::max(number, definition.minNumbers.front());
|
||||
if (!definition.maxNumbers.empty())
|
||||
number = std::min(number, definition.maxNumbers.front());
|
||||
normalizedValue.numberValues = { number };
|
||||
return true;
|
||||
}
|
||||
case ShaderParameterType::Vec2:
|
||||
case ShaderParameterType::Color:
|
||||
{
|
||||
std::vector<double> numbers = JsonArrayToNumbers(value);
|
||||
const std::size_t expectedSize = definition.type == ShaderParameterType::Vec2 ? 2 : 4;
|
||||
if (numbers.size() != expectedSize)
|
||||
{
|
||||
error = "Expected array value of size " + std::to_string(expectedSize) + " for parameter '" + definition.id + "'.";
|
||||
return false;
|
||||
}
|
||||
for (std::size_t index = 0; index < numbers.size(); ++index)
|
||||
{
|
||||
if (!IsFiniteNumber(numbers[index]))
|
||||
{
|
||||
error = "Parameter '" + definition.id + "' contains a non-finite value.";
|
||||
return false;
|
||||
}
|
||||
if (index < definition.minNumbers.size())
|
||||
numbers[index] = std::max(numbers[index], definition.minNumbers[index]);
|
||||
if (index < definition.maxNumbers.size())
|
||||
numbers[index] = std::min(numbers[index], definition.maxNumbers[index]);
|
||||
}
|
||||
normalizedValue.numberValues = numbers;
|
||||
return true;
|
||||
}
|
||||
case ShaderParameterType::Boolean:
|
||||
if (!value.isBoolean())
|
||||
{
|
||||
error = "Expected boolean value for parameter '" + definition.id + "'.";
|
||||
return false;
|
||||
}
|
||||
normalizedValue.booleanValue = value.asBoolean();
|
||||
return true;
|
||||
case ShaderParameterType::Enum:
|
||||
{
|
||||
if (!value.isString())
|
||||
{
|
||||
error = "Expected string value for enum parameter '" + definition.id + "'.";
|
||||
return false;
|
||||
}
|
||||
const std::string selectedValue = value.asString();
|
||||
for (const ShaderParameterOption& option : definition.enumOptions)
|
||||
{
|
||||
if (option.value == selectedValue)
|
||||
{
|
||||
normalizedValue.enumValue = selectedValue;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
error = "Enum parameter '" + definition.id + "' received unsupported option '" + selectedValue + "'.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user