1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-10-17 15:46:43 +00:00

Merge branch openmw:master into master

This commit is contained in:
Igilq 2025-08-01 09:09:34 +00:00
commit 65b9cea9ba
12 changed files with 94 additions and 85 deletions

View file

@ -638,8 +638,9 @@ CUSTOM: customdata.lua
sol::object deserialized = LuaUtil::deserialize(lua.sol(), data2.mScripts[0].mData, &serializer1);
EXPECT_TRUE(deserialized.is<sol::table>());
sol::table table = deserialized;
for (const auto& [key, value] : table)
if (!table.empty())
{
const auto [key, value] = *table.cbegin();
EXPECT_TRUE(key.is<ESM::RefNum>());
EXPECT_TRUE(value.is<ESM::RefNum>());
EXPECT_EQ(key.as<ESM::RefNum>(), (ESM::RefNum{ 42, 34 }));

View file

@ -215,8 +215,6 @@ int main(int argc, char** argv)
std::cerr << "ERROR: " << e.what() << std::endl;
return 1;
}
return 0;
}
namespace

View file

@ -1117,8 +1117,8 @@ namespace MWRender
return keyframeController->getAsCallback();
}
return asCallback;
else
return asCallback;
}
void Animation::resetActiveGroups()

View file

@ -615,7 +615,7 @@ namespace MWScript
long key;
if (const auto k = ::Misc::StringUtils::toNumeric<long>(effect.data());
if (const auto k = ::Misc::StringUtils::toNumeric<long>(effect);
k.has_value() && *k >= 0 && *k <= 32767)
key = *k;
else

View file

@ -528,8 +528,6 @@ namespace Fx
{
return parseBool();
}
error(Misc::StringUtils::format("failed setting uniform type"));
}
template <class SrcT, class T>
@ -557,10 +555,12 @@ namespace Fx
{
if constexpr (std::is_same_v<bool, SrcT>)
error("bool arrays currently unsupported");
int size = parseInteger();
if (size > 1)
data.mArray = std::vector<SrcT>(size);
else
{
int size = parseInteger();
if (size > 1)
data.mArray = std::vector<SrcT>(size);
}
}
else if (key == "min")
{

View file

@ -220,10 +220,11 @@ namespace Fx
return osg::Uniform::FLOAT;
else if constexpr (std::is_same_v<T, int>)
return osg::Uniform::INT;
else if constexpr (std::is_same_v<T, bool>)
else
{
static_assert(std::is_same_v<T, bool>, "Non-exhaustive visitor");
return osg::Uniform::BOOL;
return std::nullopt;
}
},
mData);
}
@ -293,15 +294,14 @@ namespace Fx
return Misc::StringUtils::format("const int %s=%i;", mName, value);
}
else if constexpr (std::is_same_v<T, bool>)
else
{
static_assert(std::is_same_v<T, bool>, "Non-exhaustive visitor");
if (useUniform)
return Misc::StringUtils::format("uniform bool %s;", uname);
return Misc::StringUtils::format("const bool %s=%s;", mName, value ? "true" : "false");
}
return std::nullopt;
},
mData);
}

View file

@ -14,7 +14,7 @@ namespace L10n
mPreferredLocales.clear();
if (gmstHasPriority)
mPreferredLocales.push_back(icu::Locale("gmst"));
std::set<std::string> langSet;
std::set<std::string_view, std::less<>> langSet;
for (const auto& lang : langs)
{
if (langSet.contains(lang))
@ -31,10 +31,10 @@ namespace L10n
msg << " " << l.getName();
}
for (auto& [key, context] : mCache)
updateContext(key.first, *context);
updateContext(std::get<0>(key), *context);
}
void Manager::readLangData(const std::string& name, MessageBundles& ctx, const icu::Locale& lang)
void Manager::readLangData(std::string_view name, MessageBundles& ctx, const icu::Locale& lang)
{
std::string langName(lang.getName());
langName += ".yaml";
@ -58,7 +58,7 @@ namespace L10n
}
}
void Manager::updateContext(const std::string& name, MessageBundles& ctx)
void Manager::updateContext(std::string_view name, MessageBundles& ctx)
{
icu::Locale fallbackLocale = ctx.getFallbackLocale();
ctx.setPreferredLocales(mPreferredLocales);
@ -89,9 +89,9 @@ namespace L10n
}
std::shared_ptr<const MessageBundles> Manager::getContext(
const std::string& contextName, const std::string& fallbackLocaleName)
std::string_view contextName, const std::string& fallbackLocaleName)
{
std::pair<std::string, std::string> key(contextName, fallbackLocaleName);
std::tuple<std::string_view, std::string_view> key(contextName, fallbackLocaleName);
auto it = mCache.find(key);
if (it != mCache.end())
return it->second;
@ -102,7 +102,7 @@ namespace L10n
for (char c : contextName)
valid = valid && allowedChar(c);
if (!valid)
throw std::runtime_error(std::string("Invalid l10n context name: ") + contextName);
throw std::runtime_error("Invalid l10n context name: " + std::string(contextName));
icu::Locale fallbackLocale(fallbackLocaleName.c_str());
std::shared_ptr<MessageBundles> ctx = std::make_shared<MessageBundles>(mPreferredLocales, fallbackLocale);
ctx->setGmstLoader(mGmstLoader);

View file

@ -27,20 +27,20 @@ namespace L10n
void setGmstLoader(std::function<std::string(std::string_view)> fn) { mGmstLoader = std::move(fn); }
std::shared_ptr<const MessageBundles> getContext(
const std::string& contextName, const std::string& fallbackLocale = "en");
std::string_view contextName, const std::string& fallbackLocale = "en");
std::string getMessage(const std::string& contextName, std::string_view key)
std::string getMessage(std::string_view contextName, std::string_view key)
{
return getContext(contextName)->formatMessage(key, {}, {});
}
private:
void readLangData(const std::string& name, MessageBundles& ctx, const icu::Locale& lang);
void updateContext(const std::string& name, MessageBundles& ctx);
void readLangData(std::string_view name, MessageBundles& ctx, const icu::Locale& lang);
void updateContext(std::string_view name, MessageBundles& ctx);
const VFS::Manager* mVFS;
std::vector<icu::Locale> mPreferredLocales;
std::map<std::pair<std::string, std::string>, std::shared_ptr<MessageBundles>> mCache;
std::map<std::tuple<std::string, std::string>, std::shared_ptr<MessageBundles>, std::less<>> mCache;
std::function<std::string(std::string_view)> mGmstLoader;
};

View file

@ -9,6 +9,50 @@
namespace L10n
{
namespace
{
std::string getErrorText(const UParseError& parseError)
{
icu::UnicodeString preContext(parseError.preContext), postContext(parseError.postContext);
std::string parseErrorString;
preContext.toUTF8String(parseErrorString);
postContext.toUTF8String(parseErrorString);
return parseErrorString;
}
template <class... Args>
bool checkSuccess(const icu::ErrorCode& status, const UParseError& parseError, Args const&... message)
{
if (status.isFailure())
{
std::string errorText = getErrorText(parseError);
if (!errorText.empty())
{
(Log(Debug::Error) << ... << message)
<< ": " << status.errorName() << " in \"" << errorText << "\"";
}
else
{
(Log(Debug::Error) << ... << message) << ": " << status.errorName();
}
}
return status.isSuccess();
}
std::string loadGmst(
const std::function<std::string(std::string_view)>& gmstLoader, const icu::MessageFormat* message)
{
icu::UnicodeString gmstNameUnicode;
std::string gmstName;
icu::ErrorCode success;
message->format(nullptr, nullptr, 0, gmstNameUnicode, success);
gmstNameUnicode.toUTF8String(gmstName);
if (gmstLoader)
return gmstLoader(gmstName);
return "GMST:" + gmstName;
}
}
MessageBundles::MessageBundles(const std::vector<icu::Locale>& preferredLocales, icu::Locale& fallbackLocale)
: mFallbackLocale(fallbackLocale)
{
@ -39,33 +83,6 @@ namespace L10n
}
}
std::string getErrorText(const UParseError& parseError)
{
icu::UnicodeString preContext(parseError.preContext), postContext(parseError.postContext);
std::string parseErrorString;
preContext.toUTF8String(parseErrorString);
postContext.toUTF8String(parseErrorString);
return parseErrorString;
}
static bool checkSuccess(
const icu::ErrorCode& status, const std::string& message, const UParseError parseError = UParseError())
{
if (status.isFailure())
{
std::string errorText = getErrorText(parseError);
if (!errorText.empty())
{
Log(Debug::Error) << message << ": " << status.errorName() << " in \"" << errorText << "\"";
}
else
{
Log(Debug::Error) << message << ": " << status.errorName();
}
}
return status.isSuccess();
}
void MessageBundles::load(std::istream& input, const icu::Locale& lang)
{
YAML::Node data = YAML::Load(input);
@ -80,20 +97,19 @@ namespace L10n
icu::ErrorCode status;
UParseError parseError;
icu::MessageFormat message(pattern, langOrEn, parseError, status);
if (checkSuccess(status, std::string("Failed to create message ") + key + " for locale " + lang.getName(),
parseError))
if (checkSuccess(status, parseError, "Failed to create message ", key, " for locale ", lang.getName()))
{
mBundles[localeName].insert(std::make_pair(key, message));
mBundles[localeName].emplace(key, message);
}
}
}
const icu::MessageFormat* MessageBundles::findMessage(std::string_view key, const std::string& localeName) const
const icu::MessageFormat* MessageBundles::findMessage(std::string_view key, std::string_view localeName) const
{
auto iter = mBundles.find(localeName);
if (iter != mBundles.end())
{
auto message = iter->second.find(key.data());
auto message = iter->second.find(key);
if (message != iter->second.end())
{
return &(message->second);
@ -116,20 +132,6 @@ namespace L10n
return formatMessage(key, argNames, argValues);
}
static std::string loadGmst(
const std::function<std::string(std::string_view)> gmstLoader, const icu::MessageFormat* message)
{
icu::UnicodeString gmstNameUnicode;
std::string gmstName;
icu::ErrorCode success;
message->format(nullptr, nullptr, 0, gmstNameUnicode, success);
gmstNameUnicode.toUTF8String(gmstName);
if (gmstLoader)
return gmstLoader(gmstName);
else
return "GMST:" + gmstName;
}
std::string MessageBundles::formatMessage(std::string_view key, const std::vector<icu::UnicodeString>& argNames,
const std::vector<icu::Formattable>& args) const
{
@ -158,7 +160,7 @@ namespace L10n
message->format(argNames.data(), args.data(), static_cast<std::int32_t>(args.size()), result, success);
else
message->format(nullptr, nullptr, static_cast<std::int32_t>(args.size()), result, success);
checkSuccess(success, std::string("Failed to format message ") + key.data());
checkSuccess(success, {}, "Failed to format message ", key);
result.toUTF8String(resultString);
return resultString;
}
@ -171,7 +173,7 @@ namespace L10n
icu::MessageFormat defaultMessage(
icu::UnicodeString::fromUTF8(icu::StringPiece(key.data(), static_cast<std::int32_t>(key.size()))),
defaultLocale, parseError, success);
if (!checkSuccess(success, std::string("Failed to create message ") + key.data(), parseError))
if (!checkSuccess(success, parseError, "Failed to create message ", key))
// If we can't parse the key as a pattern, just return the key
return std::string(key);
@ -180,7 +182,7 @@ namespace L10n
argNames.data(), args.data(), static_cast<std::int32_t>(args.size()), result, success);
else
defaultMessage.format(nullptr, nullptr, static_cast<std::int32_t>(args.size()), result, success);
checkSuccess(success, std::string("Failed to format message ") + key.data());
checkSuccess(success, {}, "Failed to format message ", key);
result.toUTF8String(resultString);
return resultString;
}

View file

@ -10,6 +10,8 @@
#include <unicode/locid.h>
#include <unicode/msgfmt.h>
#include <components/misc/strings/algorithm.hpp>
namespace L10n
{
/**
@ -41,18 +43,23 @@ namespace L10n
void setPreferredLocales(const std::vector<icu::Locale>& preferredLocales);
const std::vector<icu::Locale>& getPreferredLocales() const { return mPreferredLocales; }
void load(std::istream& input, const icu::Locale& lang);
bool isLoaded(const icu::Locale& loc) const { return mBundles.find(loc.getName()) != mBundles.end(); }
bool isLoaded(const icu::Locale& loc) const
{
return mBundles.find(std::string_view(loc.getName())) != mBundles.end();
}
const icu::Locale& getFallbackLocale() const { return mFallbackLocale; }
void setGmstLoader(std::function<std::string(std::string_view)> fn) { mGmstLoader = std::move(fn); }
private:
template <class T>
using StringMap = std::unordered_map<std::string, T, Misc::StringUtils::StringHash, std::equal_to<>>;
// icu::Locale isn't hashable (or comparable), so we use the string form instead, which is canonicalized
std::unordered_map<std::string, std::unordered_map<std::string, icu::MessageFormat>> mBundles;
StringMap<StringMap<icu::MessageFormat>> mBundles;
const icu::Locale mFallbackLocale;
std::vector<std::string> mPreferredLocaleStrings;
std::vector<icu::Locale> mPreferredLocales;
std::function<std::string(std::string_view)> mGmstLoader;
const icu::MessageFormat* findMessage(std::string_view key, const std::string& localeName) const;
const icu::MessageFormat* findMessage(std::string_view key, std::string_view localeName) const;
};
}

View file

@ -66,7 +66,7 @@ namespace LuaUtil
};
return sol::make_object(
lua, [manager](const std::string& contextName, sol::optional<std::string> fallbackLocale) {
lua, [manager](std::string_view contextName, sol::optional<std::string> fallbackLocale) {
if (fallbackLocale)
return L10nContext{ manager->getContext(contextName, *fallbackLocale) };
else

View file

@ -215,12 +215,13 @@ namespace LuaUtil
return true;
}
}
return false;
}
else if constexpr (std::is_same_v<T, LoadedData>)
else
{
static_assert(std::is_same_v<T, LoadedData>, "Non-exhaustive visitor");
return variant.mScripts.count(scriptId) != 0;
}
return false;
},
mData);
}