支持解锁 Live, 支持自定义角色, 支持换头, 支持 FOV 调整
This commit is contained in:
parent
fb65a34684
commit
acac544183
@ -16,7 +16,7 @@
|
|||||||
- [ ] 卡片信息、TIP等部分的文本 hook
|
- [ ] 卡片信息、TIP等部分的文本 hook
|
||||||
- [x] 自定义配置
|
- [x] 自定义配置
|
||||||
- [ ] 更多类型的文件替换
|
- [ ] 更多类型的文件替换
|
||||||
- [ ] 自由视角 FOV 调整
|
- [x] 自由视角 FOV 调整
|
||||||
|
|
||||||
... and more
|
... and more
|
||||||
|
|
||||||
|
@ -75,13 +75,14 @@ namespace GakumasLocal::HookMain {
|
|||||||
|
|
||||||
DEFINE_HOOK(void, Internal_LogException, (void* ex, void* obj)) {
|
DEFINE_HOOK(void, Internal_LogException, (void* ex, void* obj)) {
|
||||||
Internal_LogException_Orig(ex, obj);
|
Internal_LogException_Orig(ex, obj);
|
||||||
// Log::LogFmt(ANDROID_LOG_VERBOSE, "UnityLog - Internal_LogException");
|
static auto Exception_ToString = Il2cppUtils::GetMethod("mscorlib.dll", "System", "Exception", "ToString");
|
||||||
|
Log::LogUnityLog(ANDROID_LOG_ERROR, "UnityLog - Internal_LogException:\n%s", Exception_ToString->Invoke<Il2cppString*>(ex)->ToString().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_HOOK(void, Internal_Log, (int logType, int logOption, UnityResolve::UnityType::String* content, void* context)) {
|
DEFINE_HOOK(void, Internal_Log, (int logType, int logOption, UnityResolve::UnityType::String* content, void* context)) {
|
||||||
Internal_Log_Orig(logType, logOption, content, context);
|
Internal_Log_Orig(logType, logOption, content, context);
|
||||||
// 2022.3.21f1
|
// 2022.3.21f1
|
||||||
// Log::LogFmt(ANDROID_LOG_VERBOSE, "UnityLog - Internal_Log: %s", content->ToString().c_str());
|
Log::LogUnityLog(ANDROID_LOG_VERBOSE, "Internal_Log:\n%s", content->ToString().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
UnityResolve::UnityType::Camera* mainCameraCache = nullptr;
|
UnityResolve::UnityType::Camera* mainCameraCache = nullptr;
|
||||||
@ -97,6 +98,39 @@ namespace GakumasLocal::HookMain {
|
|||||||
cameraTransformCache = mainCameraCache->GetTransform();
|
cameraTransformCache = mainCameraCache->GetTransform();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_HOOK(void, Unity_set_fieldOfView, (UnityResolve::UnityType::Camera* _this, float value)) {
|
||||||
|
if (Config::enableFreeCamera) {
|
||||||
|
if (_this == mainCameraCache) {
|
||||||
|
value = GKCamera::baseCamera.fov;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Unity_set_fieldOfView_Orig(_this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_HOOK(float, Unity_get_fieldOfView, (UnityResolve::UnityType::Camera* _this)) {
|
||||||
|
if (Config::enableFreeCamera) {
|
||||||
|
if (_this == mainCameraCache) {
|
||||||
|
static auto get_orthographic = reinterpret_cast<bool (*)(void*)>(Il2cppUtils::il2cpp_resolve_icall(
|
||||||
|
"UnityEngine.Camera::get_orthographic()"
|
||||||
|
));
|
||||||
|
static auto set_orthographic = reinterpret_cast<bool (*)(void*, bool)>(Il2cppUtils::il2cpp_resolve_icall(
|
||||||
|
"UnityEngine.Camera::set_orthographic(System.Boolean)"
|
||||||
|
));
|
||||||
|
|
||||||
|
for (const auto& i : UnityResolve::UnityType::Camera::GetAllCamera()) {
|
||||||
|
// Log::DebugFmt("get_orthographic: %d", get_orthographic(i));
|
||||||
|
// set_orthographic(i, false);
|
||||||
|
Unity_set_fieldOfView_Orig(i, GKCamera::baseCamera.fov);
|
||||||
|
}
|
||||||
|
Unity_set_fieldOfView_Orig(_this, GKCamera::baseCamera.fov);
|
||||||
|
|
||||||
|
// Log::DebugFmt("main - get_orthographic: %d", get_orthographic(_this));
|
||||||
|
return GKCamera::baseCamera.fov;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Unity_get_fieldOfView_Orig(_this);
|
||||||
|
}
|
||||||
|
|
||||||
DEFINE_HOOK(void, Unity_set_position_Injected, (UnityResolve::UnityType::Transform* _this, UnityResolve::UnityType::Vector3* data)) {
|
DEFINE_HOOK(void, Unity_set_position_Injected, (UnityResolve::UnityType::Transform* _this, UnityResolve::UnityType::Vector3* data)) {
|
||||||
if (Config::enableFreeCamera) {
|
if (Config::enableFreeCamera) {
|
||||||
CheckAndUpdateMainCamera();
|
CheckAndUpdateMainCamera();
|
||||||
@ -123,13 +157,21 @@ namespace GakumasLocal::HookMain {
|
|||||||
"UnityEngine.Transform::Internal_LookAt_Injected(UnityEngine.Vector3&,UnityEngine.Vector3&)"));
|
"UnityEngine.Transform::Internal_LookAt_Injected(UnityEngine.Vector3&,UnityEngine.Vector3&)"));
|
||||||
static auto worldUp = UnityResolve::UnityType::Vector3(0, 1, 0);
|
static auto worldUp = UnityResolve::UnityType::Vector3(0, 1, 0);
|
||||||
lookat_injected(_this, &origCameraLookat, &worldUp);
|
lookat_injected(_this, &origCameraLookat, &worldUp);
|
||||||
// TODO 相机 FOV
|
// Log::DebugFmt("fov: %f, target: %f", Unity_get_fieldOfView_Orig(mainCameraCache), GKCamera::baseCamera.fov);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Unity_set_rotation_Injected_Orig(_this, value);
|
return Unity_set_rotation_Injected_Orig(_this, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_HOOK(void, EndCameraRendering, (void* ctx, void* camera, void* method)) {
|
||||||
|
EndCameraRendering_Orig(ctx, camera, method);
|
||||||
|
|
||||||
|
if (Config::enableFreeCamera && mainCameraCache) {
|
||||||
|
Unity_set_fieldOfView_Orig(mainCameraCache, GKCamera::baseCamera.fov);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DEFINE_HOOK(void, Unity_set_targetFrameRate, (int value)) {
|
DEFINE_HOOK(void, Unity_set_targetFrameRate, (int value)) {
|
||||||
const auto configFps = Config::targetFrameRate;
|
const auto configFps = Config::targetFrameRate;
|
||||||
return Unity_set_targetFrameRate_Orig(configFps == 0 ? value: configFps);
|
return Unity_set_targetFrameRate_Orig(configFps == 0 ? value: configFps);
|
||||||
@ -321,6 +363,76 @@ namespace GakumasLocal::HookMain {
|
|||||||
// return UnityResolve::UnityType::String::New("[I18]" + ret->ToString());
|
// return UnityResolve::UnityType::String::New("[I18]" + ret->ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_HOOK(void, PictureBookLiveThumbnailView_SetData, (void* _this, void* liveData, bool isUnlocked, bool isNew)) {
|
||||||
|
// Log::DebugFmt("PictureBookLiveThumbnailView_SetData: isUnlocked: %d, isNew: %d", isUnlocked, isNew);
|
||||||
|
if (Config::unlockAllLive) {
|
||||||
|
isUnlocked = true;
|
||||||
|
}
|
||||||
|
PictureBookLiveThumbnailView_SetData_Orig(_this, liveData, isUnlocked, isNew);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DEFINE_HOOK(void*, PictureBookLiveSelectScreenPresenter_MoveLiveScene, (void* _this, void* produceLive,
|
||||||
|
Il2cppString* characterId, Il2cppString* costumeId, Il2cppString* costumeHeadId)) {
|
||||||
|
|
||||||
|
Log::InfoFmt("MoveLiveScene: characterId: %s, costumeId: %s, costumeHeadId: %s,",
|
||||||
|
characterId->ToString().c_str(), costumeId->ToString().c_str(), costumeHeadId->ToString().c_str());
|
||||||
|
|
||||||
|
/*
|
||||||
|
characterId: hski, costumeId: hski-cstm-0002, costumeHeadId: costume_head_hski-cstm-0002,
|
||||||
|
characterId: shro, costumeId: shro-cstm-0006, costumeHeadId: costume_head_shro-cstm-0006,
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (Config::enableLiveCustomeDress) {
|
||||||
|
// 修改 LiveFixedData_GetCharacter 可以更改 Loading 角色和演唱者名字,而不变更实际登台人
|
||||||
|
return PictureBookLiveSelectScreenPresenter_MoveLiveScene_Orig(_this, produceLive, characterId,
|
||||||
|
Config::liveCustomeCostumeId.empty() ? costumeId : Il2cppString::New(Config::liveCustomeCostumeId),
|
||||||
|
Config::liveCustomeHeadId.empty() ? costumeHeadId : Il2cppString::New(Config::liveCustomeHeadId));
|
||||||
|
}
|
||||||
|
|
||||||
|
return PictureBookLiveSelectScreenPresenter_MoveLiveScene_Orig(_this, produceLive, characterId, costumeId, costumeHeadId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::string lastMusicId;
|
||||||
|
DEFINE_HOOK(void, PictureBookLiveSelectScreenPresenter_OnSelectMusic, (void* _this, void* itemModel, bool isFirst, void* mtd)) {
|
||||||
|
/* // 修改角色后,Live 结束返回时, itemModel 为 null
|
||||||
|
Log::DebugFmt("OnSelectMusic itemModel at %p", itemModel);
|
||||||
|
|
||||||
|
static auto GetMusic = Il2cppUtils::GetMethod("Assembly-CSharp.dll", "Campus.OutGame",
|
||||||
|
"PlaylistMusicContext", "GetMusic");
|
||||||
|
static auto GetCurrMusic = Il2cppUtils::GetMethod("Assembly-CSharp.dll", "Campus.OutGame.PictureBook",
|
||||||
|
"PictureBookLiveSelectMusicListItemModel", "get_Music");
|
||||||
|
static auto GetMusicId = Il2cppUtils::GetMethod("Assembly-CSharp.dll", "Campus.Common.Proto.Client.Master",
|
||||||
|
"Music", "get_Id");
|
||||||
|
|
||||||
|
static auto PictureBookLiveSelectMusicListItemModel_klass = Il2cppUtils::GetClass("Assembly-CSharp.dll", "Campus.OutGame.PictureBook",
|
||||||
|
"PictureBookLiveSelectMusicListItemModel");
|
||||||
|
static auto PictureBookLiveSelectMusicListItemModel_ctor = Il2cppUtils::GetMethod("Assembly-CSharp.dll", "Campus.OutGame.PictureBook",
|
||||||
|
"PictureBookLiveSelectMusicListItemModel", ".ctor", {"*", "*"});
|
||||||
|
|
||||||
|
if (!itemModel) {
|
||||||
|
Log::DebugFmt("OnSelectMusic block", itemModel);
|
||||||
|
auto music = GetMusic->Invoke<void*>(lastMusicId);
|
||||||
|
auto newItemModel = PictureBookLiveSelectMusicListItemModel_klass->New<void*>();
|
||||||
|
PictureBookLiveSelectMusicListItemModel_ctor->Invoke<void>(newItemModel, music, false);
|
||||||
|
|
||||||
|
return PictureBookLiveSelectScreenPresenter_OnSelectMusic_Orig(_this, newItemModel, isFirst, mtd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemModel) {
|
||||||
|
auto currMusic = GetCurrMusic->Invoke<void*>(itemModel);
|
||||||
|
auto musicId = GetMusicId->Invoke<Il2cppString*>(currMusic);
|
||||||
|
lastMusicId = musicId->ToString();
|
||||||
|
}*/
|
||||||
|
if (!itemModel) return;
|
||||||
|
return PictureBookLiveSelectScreenPresenter_OnSelectMusic_Orig(_this, itemModel, isFirst, mtd);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_HOOK(bool, VLDOF_IsActive, (void* _this)) {
|
||||||
|
if (Config::enableFreeCamera) return false;
|
||||||
|
return VLDOF_IsActive_Orig(_this);
|
||||||
|
}
|
||||||
|
|
||||||
void StartInjectFunctions() {
|
void StartInjectFunctions() {
|
||||||
const auto hookInstaller = Plugin::GetInstance().GetHookInstaller();
|
const auto hookInstaller = Plugin::GetInstance().GetHookInstaller();
|
||||||
UnityResolve::Init(xdl_open(hookInstaller->m_il2cppLibraryPath.c_str(), RTLD_NOW), UnityResolve::Mode::Il2Cpp);
|
UnityResolve::Init(xdl_open(hookInstaller->m_il2cppLibraryPath.c_str(), RTLD_NOW), UnityResolve::Mode::Il2Cpp);
|
||||||
@ -361,6 +473,21 @@ namespace GakumasLocal::HookMain {
|
|||||||
Il2cppUtils::GetMethodPointer("Octo.dll", "Octo",
|
Il2cppUtils::GetMethodPointer("Octo.dll", "Octo",
|
||||||
"OnDownloadProgress", "Invoke"));
|
"OnDownloadProgress", "Invoke"));
|
||||||
|
|
||||||
|
ADD_HOOK(PictureBookLiveThumbnailView_SetData,
|
||||||
|
Il2cppUtils::GetMethodPointer("Assembly-CSharp.dll", "Campus.OutGame.PictureBook",
|
||||||
|
"PictureBookLiveThumbnailView", "SetData"));
|
||||||
|
|
||||||
|
ADD_HOOK(PictureBookLiveSelectScreenPresenter_MoveLiveScene,
|
||||||
|
Il2cppUtils::GetMethodPointer("Assembly-CSharp.dll", "Campus.OutGame",
|
||||||
|
"PictureBookLiveSelectScreenPresenter", "MoveLiveScene"));
|
||||||
|
ADD_HOOK(PictureBookLiveSelectScreenPresenter_OnSelectMusic,
|
||||||
|
Il2cppUtils::GetMethodPointer("Assembly-CSharp.dll", "Campus.OutGame",
|
||||||
|
"PictureBookLiveSelectScreenPresenter", "OnSelectMusic"));
|
||||||
|
|
||||||
|
ADD_HOOK(VLDOF_IsActive,
|
||||||
|
Il2cppUtils::GetMethodPointer("Unity.RenderPipelines.Universal.Runtime.dll", "VL.Rendering",
|
||||||
|
"VLDOF", "IsActive"));
|
||||||
|
|
||||||
ADD_HOOK(Internal_LogException, Il2cppUtils::il2cpp_resolve_icall(
|
ADD_HOOK(Internal_LogException, Il2cppUtils::il2cpp_resolve_icall(
|
||||||
"UnityEngine.DebugLogHandler::Internal_LogException(System.Exception,UnityEngine.Object)"));
|
"UnityEngine.DebugLogHandler::Internal_LogException(System.Exception,UnityEngine.Object)"));
|
||||||
ADD_HOOK(Internal_Log, Il2cppUtils::il2cpp_resolve_icall(
|
ADD_HOOK(Internal_Log, Il2cppUtils::il2cpp_resolve_icall(
|
||||||
@ -370,8 +497,14 @@ namespace GakumasLocal::HookMain {
|
|||||||
"UnityEngine.Transform::set_position_Injected(UnityEngine.Vector3&)"));
|
"UnityEngine.Transform::set_position_Injected(UnityEngine.Vector3&)"));
|
||||||
ADD_HOOK(Unity_set_rotation_Injected, Il2cppUtils::il2cpp_resolve_icall(
|
ADD_HOOK(Unity_set_rotation_Injected, Il2cppUtils::il2cpp_resolve_icall(
|
||||||
"UnityEngine.Transform::set_rotation_Injected(UnityEngine.Quaternion&)"));
|
"UnityEngine.Transform::set_rotation_Injected(UnityEngine.Quaternion&)"));
|
||||||
|
ADD_HOOK(Unity_get_fieldOfView, Il2cppUtils::GetMethodPointer("UnityEngine.CoreModule.dll", "UnityEngine",
|
||||||
|
"Camera", "get_fieldOfView"));
|
||||||
|
ADD_HOOK(Unity_set_fieldOfView, Il2cppUtils::GetMethodPointer("UnityEngine.CoreModule.dll", "UnityEngine",
|
||||||
|
"Camera", "set_fieldOfView"));
|
||||||
ADD_HOOK(Unity_set_targetFrameRate, Il2cppUtils::il2cpp_resolve_icall(
|
ADD_HOOK(Unity_set_targetFrameRate, Il2cppUtils::il2cpp_resolve_icall(
|
||||||
"UnityEngine.Application::set_targetFrameRate(System.Int32)"));
|
"UnityEngine.Application::set_targetFrameRate(System.Int32)"));
|
||||||
|
ADD_HOOK(EndCameraRendering, Il2cppUtils::GetMethodPointer("UnityEngine.CoreModule.dll", "UnityEngine.Rendering",
|
||||||
|
"RenderPipeline", "EndCameraRendering"));
|
||||||
}
|
}
|
||||||
// 77 2640 5000
|
// 77 2640 5000
|
||||||
|
|
||||||
|
@ -139,4 +139,28 @@ namespace GakumasLocal::Log {
|
|||||||
|
|
||||||
Debug(result.c_str());
|
Debug(result.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LogUnityLog(int prio, const char* fmt, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
va_list args_copy;
|
||||||
|
va_copy(args_copy, args);
|
||||||
|
|
||||||
|
// 计算格式化后的字符串长度
|
||||||
|
int size = vsnprintf(nullptr, 0, fmt, args_copy) + 1; // 加上额外的终止符空间
|
||||||
|
va_end(args_copy);
|
||||||
|
|
||||||
|
// 动态分配缓冲区
|
||||||
|
char* buffer = new char[size];
|
||||||
|
|
||||||
|
// 格式化字符串
|
||||||
|
vsnprintf(buffer, size, fmt, args);
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
std::string result(buffer);
|
||||||
|
delete[] buffer; // 释放缓冲区
|
||||||
|
|
||||||
|
__android_log_write(prio, "GakumasLog", result.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define GAKUMAS_LOCALIFY_LOG_H
|
#define GAKUMAS_LOCALIFY_LOG_H
|
||||||
|
|
||||||
namespace GakumasLocal::Log {
|
namespace GakumasLocal::Log {
|
||||||
|
void LogUnityLog(int prio, const char* fmt, ...);
|
||||||
void LogFmt(int prio, const char* fmt, ...);
|
void LogFmt(int prio, const char* fmt, ...);
|
||||||
void Info(const char* msg);
|
void Info(const char* msg);
|
||||||
void InfoFmt(const char* fmt, ...);
|
void InfoFmt(const char* fmt, ...);
|
||||||
|
@ -8,14 +8,25 @@ namespace GakumasLocal::Config {
|
|||||||
bool enabled = true;
|
bool enabled = true;
|
||||||
bool enableFreeCamera = false;
|
bool enableFreeCamera = false;
|
||||||
int targetFrameRate = 0;
|
int targetFrameRate = 0;
|
||||||
|
bool unlockAllLive = false;
|
||||||
|
|
||||||
|
bool enableLiveCustomeDress = false;
|
||||||
|
std::string liveCustomeHeadId = "";
|
||||||
|
std::string liveCustomeCostumeId = "";
|
||||||
|
|
||||||
void LoadConfig(const std::string& configStr) {
|
void LoadConfig(const std::string& configStr) {
|
||||||
try {
|
try {
|
||||||
const auto config = nlohmann::json::parse(configStr);
|
const auto config = nlohmann::json::parse(configStr);
|
||||||
|
|
||||||
enabled = config["enabled"];
|
#define GetConfigItem(name) if (config.contains(#name)) name = config[#name]
|
||||||
targetFrameRate = config["targetFrameRate"];
|
|
||||||
enableFreeCamera = config["enableFreeCamera"];
|
GetConfigItem(enabled);
|
||||||
|
GetConfigItem(targetFrameRate);
|
||||||
|
GetConfigItem(enableFreeCamera);
|
||||||
|
GetConfigItem(unlockAllLive);
|
||||||
|
GetConfigItem(enableLiveCustomeDress);
|
||||||
|
GetConfigItem(liveCustomeHeadId);
|
||||||
|
GetConfigItem(liveCustomeCostumeId);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (std::exception& e) {
|
catch (std::exception& e) {
|
||||||
|
@ -8,6 +8,11 @@ namespace GakumasLocal::Config {
|
|||||||
extern bool enabled;
|
extern bool enabled;
|
||||||
extern bool enableFreeCamera;
|
extern bool enableFreeCamera;
|
||||||
extern int targetFrameRate;
|
extern int targetFrameRate;
|
||||||
|
extern bool unlockAllLive;
|
||||||
|
|
||||||
|
extern bool enableLiveCustomeDress;
|
||||||
|
extern std::string liveCustomeHeadId;
|
||||||
|
extern std::string liveCustomeCostumeId;
|
||||||
|
|
||||||
void LoadConfig(const std::string& configStr);
|
void LoadConfig(const std::string& configStr);
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,10 @@ interface ConfigListener {
|
|||||||
fun onEnabledChanged(value: Boolean)
|
fun onEnabledChanged(value: Boolean)
|
||||||
fun onEnableFreeCameraChanged(value: Boolean)
|
fun onEnableFreeCameraChanged(value: Boolean)
|
||||||
fun onTargetFpsChanged(s: CharSequence, start: Int, before: Int, count: Int)
|
fun onTargetFpsChanged(s: CharSequence, start: Int, before: Int, count: Int)
|
||||||
|
fun onUnlockAllLiveChanged(value: Boolean)
|
||||||
|
fun onLiveCustomeDressChanged(value: Boolean)
|
||||||
|
fun onLiveCustomeHeadIdChanged(s: CharSequence, start: Int, before: Int, count: Int)
|
||||||
|
fun onLiveCustomeCostumeIdChanged(s: CharSequence, start: Int, before: Int, count: Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity(), ConfigListener {
|
class MainActivity : AppCompatActivity(), ConfigListener {
|
||||||
@ -85,6 +89,11 @@ class MainActivity : AppCompatActivity(), ConfigListener {
|
|||||||
saveConfig()
|
saveConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onUnlockAllLiveChanged(value: Boolean) {
|
||||||
|
config.unlockAllLive = value
|
||||||
|
saveConfig()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onTargetFpsChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
override fun onTargetFpsChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||||
try {
|
try {
|
||||||
val valueStr = s.toString()
|
val valueStr = s.toString()
|
||||||
@ -102,6 +111,21 @@ class MainActivity : AppCompatActivity(), ConfigListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onLiveCustomeDressChanged(value: Boolean) {
|
||||||
|
config.enableLiveCustomeDress = value
|
||||||
|
saveConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLiveCustomeCostumeIdChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||||
|
config.liveCustomeCostumeId = s.toString()
|
||||||
|
saveConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLiveCustomeHeadIdChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||||
|
config.liveCustomeHeadId = s.toString()
|
||||||
|
saveConfig()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onClickStartGame() {
|
override fun onClickStartGame() {
|
||||||
val intent = Intent().apply {
|
val intent = Intent().apply {
|
||||||
setClassName("com.bandainamcoent.idolmaster_gakuen", "com.google.firebase.MessagingUnityPlayerActivity")
|
setClassName("com.bandainamcoent.idolmaster_gakuen", "com.google.firebase.MessagingUnityPlayerActivity")
|
||||||
|
@ -3,6 +3,10 @@ package io.github.chinosk.gakumas.localify.models
|
|||||||
data class GakumasConfig(
|
data class GakumasConfig(
|
||||||
var enabled: Boolean = true,
|
var enabled: Boolean = true,
|
||||||
var enableFreeCamera: Boolean = false,
|
var enableFreeCamera: Boolean = false,
|
||||||
var targetFrameRate: Int = 0
|
var targetFrameRate: Int = 0,
|
||||||
|
var unlockAllLive: Boolean = false,
|
||||||
|
var enableLiveCustomeDress: Boolean = false,
|
||||||
|
var liveCustomeHeadId: String = "",
|
||||||
|
var liveCustomeCostumeId: String = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -96,6 +96,81 @@
|
|||||||
android:text="@string/enable_free_camera" />
|
android:text="@string/enable_free_camera" />
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
|
<TableRow
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||||
|
android:id="@+id/SwitchUnlockAllLive"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:checked="@={config.unlockAllLive}"
|
||||||
|
android:onCheckedChanged="@{(view, value) -> listener.onUnlockAllLiveChanged(value)}"
|
||||||
|
android:text="@string/unlockAllLive" />
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
|
<TableRow
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||||
|
android:id="@+id/SwitchLiveUseCustomeDress"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:checked="@={config.enableLiveCustomeDress}"
|
||||||
|
android:onCheckedChanged="@{(view, value) -> listener.onLiveCustomeDressChanged(value)}"
|
||||||
|
android:text="@string/liveUseCustomeDress" />
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
|
<TableRow
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
app:boxBackgroundColor="@android:color/transparent"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:hint="@string/live_costume_head_id" >
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/editTextLiveCustomeCharaId"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:ems="10"
|
||||||
|
android:paddingStart="0dp"
|
||||||
|
android:paddingEnd="0dp"
|
||||||
|
android:paddingBottom="0dp"
|
||||||
|
android:text="@={config.liveCustomeHeadId}"
|
||||||
|
android:onTextChanged="@{(s, st, b, a) -> listener.onLiveCustomeHeadIdChanged(s, st, b, a)}"/>
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
|
<TableRow
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
app:boxBackgroundColor="@android:color/transparent"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:hint="@string/live_custome_dress_id" >
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/editTextLiveCustomeCostumeId"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:ems="10"
|
||||||
|
android:paddingStart="0dp"
|
||||||
|
android:paddingEnd="0dp"
|
||||||
|
android:paddingBottom="0dp"
|
||||||
|
android:text="@={config.liveCustomeCostumeId}"
|
||||||
|
android:onTextChanged="@{(s, st, b, a) -> listener.onLiveCustomeCostumeIdChanged(s, st, b, a)}"/>
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
|
|
||||||
<TableRow
|
<TableRow
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
@ -5,4 +5,8 @@
|
|||||||
<string name="enable_free_camera">启用自由视角(可热重载; 需使用实体键盘)</string>
|
<string name="enable_free_camera">启用自由视角(可热重载; 需使用实体键盘)</string>
|
||||||
<string name="start_game">以上述配置启动游戏/重载配置</string>
|
<string name="start_game">以上述配置启动游戏/重载配置</string>
|
||||||
<string name="setFpsTitle">最大 FPS (0 为保持游戏原设置)</string>
|
<string name="setFpsTitle">最大 FPS (0 为保持游戏原设置)</string>
|
||||||
|
<string name="unlockAllLive">解锁所有 Live</string>
|
||||||
|
<string name="liveUseCustomeDress">Live 使用自定义角色</string>
|
||||||
|
<string name="live_costume_head_id">Live 自定义头部 ID (例: costume_head_hski-cstm-0002)</string>
|
||||||
|
<string name="live_custome_dress_id">Live 自定义服装 ID (例: hski-cstm-0002)</string>
|
||||||
</resources>
|
</resources>
|
Loading…
x
Reference in New Issue
Block a user