#include "core/params.hpp" #include namespace effector { std::string ParamSpec::flag() const { std::string flag = "--" + key; std::replace(flag.begin(), flag.end(), '_', '-'); return flag; } ParamSpec ParamSpec::makeInt(std::string key, std::string label, long defaultValue, long minimum, long maximum, std::string help, long step) { ParamSpec spec; spec.type = Type::Int; spec.key = std::move(key); spec.label = std::move(label); spec.help = std::move(help); spec.defaultValue = static_cast(defaultValue); spec.minimum = static_cast(minimum); spec.maximum = static_cast(maximum); spec.step = static_cast(step); return spec; } ParamSpec ParamSpec::makeDouble(std::string key, std::string label, double defaultValue, double minimum, double maximum, std::string help, double step, int digits) { ParamSpec spec; spec.type = Type::Double; spec.key = std::move(key); spec.label = std::move(label); spec.help = std::move(help); spec.defaultValue = defaultValue; spec.minimum = minimum; spec.maximum = maximum; spec.step = step; spec.digits = digits; return spec; } ParamSpec ParamSpec::makeBool(std::string key, std::string label, bool defaultValue, std::string help) { ParamSpec spec; spec.type = Type::Bool; spec.key = std::move(key); spec.label = std::move(label); spec.help = std::move(help); spec.defaultValue = defaultValue ? 1.0 : 0.0; return spec; } ParamSpec ParamSpec::makeChoice(std::string key, std::string label, std::string defaultChoice, std::vector choices, std::string help) { ParamSpec spec; spec.type = Type::Choice; spec.key = std::move(key); spec.label = std::move(label); spec.help = std::move(help); spec.defaultChoice = std::move(defaultChoice); spec.choices = std::move(choices); return spec; } ParamSpec ParamSpec::makePath(std::string key, std::string label, std::string help) { ParamSpec spec; spec.type = Type::Path; spec.key = std::move(key); spec.label = std::move(label); spec.help = std::move(help); return spec; } ParamSpec ParamSpec::makeText(std::string key, std::string label, std::string defaultText, std::string help) { ParamSpec spec; spec.type = Type::Text; spec.key = std::move(key); spec.label = std::move(label); spec.help = std::move(help); spec.defaultChoice = std::move(defaultText); return spec; } ParamSpec ParamSpec::makeColor(std::string key, std::string label, std::string defaultColor, std::string help) { ParamSpec spec; spec.type = Type::Color; spec.key = std::move(key); spec.label = std::move(label); spec.help = std::move(help); spec.defaultChoice = std::move(defaultColor); return spec; } namespace { const ParamValue* find(const ParamValues& values, const std::string& key) { const auto it = values.find(key); return it == values.end() ? nullptr : &it->second; } } // namespace long paramInt(const ParamValues& values, const std::string& key, long fallback) { if (const auto* value = find(values, key)) { if (const auto* v = std::get_if(value)) return *v; if (const auto* v = std::get_if(value)) return static_cast(*v); if (const auto* v = std::get_if(value)) return *v ? 1 : 0; } return fallback; } double paramDouble(const ParamValues& values, const std::string& key, double fallback) { if (const auto* value = find(values, key)) { if (const auto* v = std::get_if(value)) return *v; if (const auto* v = std::get_if(value)) return static_cast(*v); } return fallback; } bool paramBool(const ParamValues& values, const std::string& key, bool fallback) { if (const auto* value = find(values, key)) { if (const auto* v = std::get_if(value)) return *v; if (const auto* v = std::get_if(value)) return *v != 0; } return fallback; } std::string paramChoice(const ParamValues& values, const std::string& key, const std::string& fallback) { return paramText(values, key, fallback); } std::string paramText(const ParamValues& values, const std::string& key, const std::string& fallback) { if (const auto* value = find(values, key)) { if (const auto* v = std::get_if(value)) return *v; } return fallback; } namespace { int hexDigit(char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'a' && c <= 'f') return c - 'a' + 10; if (c >= 'A' && c <= 'F') return c - 'A' + 10; return -1; } } // namespace bool parseColor(const std::string& text, std::uint8_t rgb[3]) { std::string digits = text; if (!digits.empty() && digits.front() == '#') digits.erase(digits.begin()); if (digits.size() != 3 && digits.size() != 6) return false; int parsed[6]; for (std::size_t i = 0; i < digits.size(); ++i) { parsed[i] = hexDigit(digits[i]); if (parsed[i] < 0) return false; } for (int c = 0; c < 3; ++c) { // "#abc" is the usual shorthand for "#aabbcc". const int value = digits.size() == 3 ? parsed[c] * 17 : parsed[c * 2] * 16 + parsed[c * 2 + 1]; rgb[c] = static_cast(value); } return true; } std::string formatColor(const std::uint8_t rgb[3]) { static const char* const kDigits = "0123456789abcdef"; std::string text = "#"; for (int c = 0; c < 3; ++c) { text += kDigits[rgb[c] >> 4]; text += kDigits[rgb[c] & 0x0F]; } return text; } void paramColor(const ParamValues& values, const std::string& key, const std::string& fallback, std::uint8_t rgb[3]) { if (parseColor(paramText(values, key, fallback), rgb)) return; if (parseColor(fallback, rgb)) return; rgb[0] = rgb[1] = rgb[2] = 0; } } // namespace effector