refactor
Some checks failed
CI / Native Windows Build And Tests (push) Failing after 6s
CI / React UI Build (push) Successful in 10s

This commit is contained in:
2026-05-03 11:39:21 +10:00
parent 12dda9fc8c
commit 059032c234
11 changed files with 1163 additions and 209 deletions

View 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;
}