forked from chinosk/gkms-localify-dmm
只替换普通字体,保留特殊数字字体
This commit is contained in:
parent
64809af01c
commit
95f72f6241
|
|
@ -431,35 +431,45 @@ namespace GakumasLocal::HookMain {
|
||||||
return GetBundleHandleByAssetName(utility::conversions::to_string_t(assetName));
|
return GetBundleHandleByAssetName(utility::conversions::to_string_t(assetName));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ReplaceFontHandle;
|
// 多字体支持:字体映射缓存
|
||||||
|
struct FontCacheEntry {
|
||||||
|
uint32_t handle;
|
||||||
|
std::string assetPath;
|
||||||
|
};
|
||||||
|
std::unordered_map<std::string, FontCacheEntry> g_fontCache;
|
||||||
|
uint32_t ReplaceFontHandle; // 默认字体句柄(向后兼容)
|
||||||
|
|
||||||
void* GetReplaceFont() {
|
// 字体映射配置:原字体名 -> 替换字体资源路径
|
||||||
|
// 注意:这里匹配的是 TMP_FontAsset 的 name,通常是 "XXX Atlas" 或 "XXX SDF Atlas"
|
||||||
|
std::unordered_map<std::string, std::string> g_fontMapping = {
|
||||||
|
{"ibmplexsansjp", "assets/fonts/gkamszhfontmix.otf"}, // IBMPlexSansJP Atlas -> 替换为中文字体
|
||||||
|
};
|
||||||
|
|
||||||
|
// 加载指定路径的字体
|
||||||
|
void* GetReplaceFont(const std::string& fontPath) {
|
||||||
static auto FontClass = Il2cppUtils::GetClass("UnityEngine.TextRenderingModule.dll", "UnityEngine", "Font");
|
static auto FontClass = Il2cppUtils::GetClass("UnityEngine.TextRenderingModule.dll", "UnityEngine", "Font");
|
||||||
static auto Font_Type = UnityResolve::Invoke<Il2cppUtils::Il2CppReflectionType*>("il2cpp_type_get_object",
|
static auto Font_Type = UnityResolve::Invoke<Il2cppUtils::Il2CppReflectionType*>("il2cpp_type_get_object",
|
||||||
UnityResolve::Invoke<void*>("il2cpp_class_get_type", FontClass->address));
|
UnityResolve::Invoke<void*>("il2cpp_class_get_type", FontClass->address));
|
||||||
|
|
||||||
using Il2CppString = UnityResolve::UnityType::String;
|
using Il2CppString = UnityResolve::UnityType::String;
|
||||||
const auto fontPath = "assets/fonts/gkamszhfontmix.otf";
|
|
||||||
|
|
||||||
|
// 检查缓存
|
||||||
|
auto cacheIt = g_fontCache.find(fontPath);
|
||||||
void* replaceFont{};
|
void* replaceFont{};
|
||||||
|
|
||||||
|
if (cacheIt != g_fontCache.end()) {
|
||||||
|
replaceFont = UnityResolve::Invoke<void*>("il2cpp_gchandle_get_target", cacheIt->second.handle);
|
||||||
|
if (IsNativeObjectAlive(replaceFont)) {
|
||||||
|
return replaceFont;
|
||||||
|
}
|
||||||
|
// 缓存失效,释放句柄
|
||||||
|
UnityResolve::Invoke<void>("il2cpp_gchandle_free", cacheIt->second.handle);
|
||||||
|
g_fontCache.erase(cacheIt);
|
||||||
|
}
|
||||||
|
|
||||||
const auto& bundleHandle = GetBundleHandleByAssetName(fontPath);
|
const auto& bundleHandle = GetBundleHandleByAssetName(fontPath);
|
||||||
if (bundleHandle)
|
if (bundleHandle)
|
||||||
{
|
{
|
||||||
if (ReplaceFontHandle)
|
|
||||||
{
|
|
||||||
replaceFont = UnityResolve::Invoke<void*>("il2cpp_gchandle_get_target", ReplaceFontHandle);
|
|
||||||
// 加载场景时会被 Resources.UnloadUnusedAssets 干掉,且不受 DontDestroyOnLoad 影响,暂且判断是否存活,并在必要的时候重新加载
|
|
||||||
// TODO: 考虑挂载到 GameObject 上
|
|
||||||
// AssetBundle 不会被干掉
|
|
||||||
if (IsNativeObjectAlive(replaceFont))
|
|
||||||
{
|
|
||||||
return replaceFont;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UnityResolve::Invoke<void>("il2cpp_gchandle_free", std::exchange(ReplaceFontHandle, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto extraAssetBundle = UnityResolve::Invoke<void*>("il2cpp_gchandle_get_target", bundleHandle);
|
const auto extraAssetBundle = UnityResolve::Invoke<void*>("il2cpp_gchandle_get_target", bundleHandle);
|
||||||
static auto AssetBundle_LoadAsset = reinterpret_cast<void* (*)(void* _this, Il2CppString* name, Il2cppUtils::Il2CppReflectionType* type)>(
|
static auto AssetBundle_LoadAsset = reinterpret_cast<void* (*)(void* _this, Il2CppString* name, Il2cppUtils::Il2CppReflectionType* type)>(
|
||||||
|
|
@ -469,19 +479,30 @@ namespace GakumasLocal::HookMain {
|
||||||
replaceFont = AssetBundle_LoadAsset(extraAssetBundle, Il2cppString::New(fontPath), Font_Type);
|
replaceFont = AssetBundle_LoadAsset(extraAssetBundle, Il2cppString::New(fontPath), Font_Type);
|
||||||
if (replaceFont)
|
if (replaceFont)
|
||||||
{
|
{
|
||||||
ReplaceFontHandle = UnityResolve::Invoke<uint32_t>("il2cpp_gchandle_new", replaceFont, false);
|
auto handle = UnityResolve::Invoke<uint32_t>("il2cpp_gchandle_new", replaceFont, false);
|
||||||
|
g_fontCache[fontPath] = {handle, fontPath};
|
||||||
|
|
||||||
|
// 向后兼容:如果是默认字体,也更新全局句柄
|
||||||
|
if (fontPath == "assets/fonts/gkamszhfontmix.otf") {
|
||||||
|
ReplaceFontHandle = handle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log::Error("Cannot load asset font\n");
|
Log::ErrorFmt("Cannot load asset font: %s\n", fontPath.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log::Error("Cannot find asset font\n");
|
Log::ErrorFmt("Cannot find asset font: %s\n", fontPath.c_str());
|
||||||
}
|
}
|
||||||
return replaceFont;
|
return replaceFont;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 默认字体加载(向后兼容)
|
||||||
|
void* GetReplaceFont() {
|
||||||
|
return GetReplaceFont("assets/fonts/gkamszhfontmix.otf");
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
void* fontCache = nullptr;
|
void* fontCache = nullptr;
|
||||||
void* GetReplaceFont() {
|
void* GetReplaceFont() {
|
||||||
|
|
@ -519,6 +540,8 @@ namespace GakumasLocal::HookMain {
|
||||||
"TMPro", "TMP_Text", "get_font");
|
"TMPro", "TMP_Text", "get_font");
|
||||||
static auto set_font = Il2cppUtils::GetMethod("Unity.TextMeshPro.dll",
|
static auto set_font = Il2cppUtils::GetMethod("Unity.TextMeshPro.dll",
|
||||||
"TMPro", "TMP_Text", "set_font");
|
"TMPro", "TMP_Text", "set_font");
|
||||||
|
static auto get_name = Il2cppUtils::GetMethod("UnityEngine.CoreModule.dll",
|
||||||
|
"UnityEngine", "Object", "get_name");
|
||||||
// static auto set_fontMaterial = Il2cppUtils::GetMethod("Unity.TextMeshPro.dll",
|
// static auto set_fontMaterial = Il2cppUtils::GetMethod("Unity.TextMeshPro.dll",
|
||||||
// "TMPro", "TMP_Text", "set_fontMaterial");
|
// "TMPro", "TMP_Text", "set_fontMaterial");
|
||||||
// static auto ForceMeshUpdate = Il2cppUtils::GetMethod("Unity.TextMeshPro.dll",
|
// static auto ForceMeshUpdate = Il2cppUtils::GetMethod("Unity.TextMeshPro.dll",
|
||||||
|
|
@ -532,21 +555,30 @@ namespace GakumasLocal::HookMain {
|
||||||
static auto UpdateFontAssetData = Il2cppUtils::GetMethod("Unity.TextMeshPro.dll", "TMPro",
|
static auto UpdateFontAssetData = Il2cppUtils::GetMethod("Unity.TextMeshPro.dll", "TMPro",
|
||||||
"TMP_FontAsset", "UpdateFontAssetData");
|
"TMP_FontAsset", "UpdateFontAssetData");
|
||||||
|
|
||||||
|
auto fontAsset = get_font->Invoke<void*>(TMP_Textself);
|
||||||
|
if (!fontAsset) return;
|
||||||
|
|
||||||
|
// 跳过 CampusAlphanumeric 系列字体,保持游戏原版数字字体
|
||||||
|
auto fontAssetName = get_name->Invoke<Il2cppString*>(fontAsset);
|
||||||
|
if (fontAssetName) {
|
||||||
|
std::string fontName = fontAssetName->ToString();
|
||||||
|
std::transform(fontName.begin(), fontName.end(), fontName.begin(), ::tolower);
|
||||||
|
if (fontName.find("campusalphanumeric") != std::string::npos) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 替换为中文字体
|
||||||
auto newFont = GetReplaceFont();
|
auto newFont = GetReplaceFont();
|
||||||
if (!newFont) return;
|
if (!newFont) return;
|
||||||
|
|
||||||
auto fontAsset = get_font->Invoke<void*>(TMP_Textself);
|
set_sourceFontFile->Invoke<void>(fontAsset, newFont);
|
||||||
if (fontAsset) {
|
if (!updatedFontPtrs.contains(fontAsset)) {
|
||||||
set_sourceFontFile->Invoke<void>(fontAsset, newFont);
|
updatedFontPtrs.emplace(fontAsset);
|
||||||
if (!updatedFontPtrs.contains(fontAsset)) {
|
UpdateFontAssetData->Invoke<void>(fontAsset);
|
||||||
updatedFontPtrs.emplace(fontAsset);
|
|
||||||
UpdateFontAssetData->Invoke<void>(fontAsset);
|
|
||||||
}
|
|
||||||
if (updatedFontPtrs.size() > 200) updatedFontPtrs.clear();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Log::Error("UpdateFont: fontAsset is null.");
|
|
||||||
}
|
}
|
||||||
|
if (updatedFontPtrs.size() > 200) updatedFontPtrs.clear();
|
||||||
|
|
||||||
set_font->Invoke<void>(TMP_Textself, fontAsset);
|
set_font->Invoke<void>(TMP_Textself, fontAsset);
|
||||||
|
|
||||||
// auto fontMaterial = get_material->Invoke<void*>(fontAsset);
|
// auto fontMaterial = get_material->Invoke<void*>(fontAsset);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue