[+] Configurable mod key map manager

This commit is contained in:
Clansty
2024-11-01 17:03:57 +08:00
parent ac4db91df4
commit fb96e93184
14 changed files with 331 additions and 136 deletions

View File

@@ -24,17 +24,6 @@ public class Config
zh: "触摸屏延迟,单位为毫秒,一秒 = 1000 毫秒。必须是整数")]
public int TouchDelay { get; set; }
[ConfigComment(
en: """
Practice mode, activated by pressing Test in the game
Must be used together with TestProof
""",
zh: """
练习模式,在游戏中按 Test 打开
必须和 TestProof 一起用
""")]
public bool PractiseMode { get; set; }
[ConfigComment(
en: "Show detail of selected song in music selection screen",
zh: "选歌界面显示选择的歌曲的详情")]

View File

@@ -1,249 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using AquaMai.Fix;
using AquaMai.Helpers;
using AquaMai.Resources;
using HarmonyLib;
using Manager;
using Monitor;
using Monitor.Game;
using Process;
using UnityEngine;
namespace AquaMai.Utils;
public class PractiseMode
{
public static double repeatStart = -1;
public static double repeatEnd = -1;
public static float speed = 1;
private static CriAtomExPlayer player;
private static MovieMaterialMai2 movie;
public static GameCtrl gameCtrl;
public static bool keepNoteSpeed = false;
public static void SetRepeatEnd(double time)
{
if (repeatStart == -1)
{
MessageHelper.ShowMessage(Locale.RepeatStartTimeNotSet);
return;
}
if (time < repeatStart)
{
MessageHelper.ShowMessage(Locale.RepeatEndTimeLessThenStartTime);
return;
}
repeatEnd = time;
}
public static void ClearRepeat()
{
repeatStart = -1;
repeatEnd = -1;
}
public static void SetSpeed()
{
player.SetPitch((float)(1200 * Math.Log(speed, 2)));
// player.SetDspTimeStretchRatio(1 / speed);
player.UpdateAll();
movie.player.SetSpeed(speed);
gameCtrl?.ResetOptionSpeed();
}
private static IEnumerator SetSpeedCoroutineInner()
{
yield return null;
SetSpeed();
}
public static void SetSpeedCoroutine()
{
SharedInstances.GameMainObject.StartCoroutine(SetSpeedCoroutineInner());
}
public static void SpeedUp()
{
speed += .05f;
if (speed > 2)
{
speed = 2;
}
SetSpeed();
}
public static void SpeedDown()
{
speed -= .05f;
if (speed < 0.05)
{
speed = 0.05f;
}
SetSpeed();
}
public static void SpeedReset()
{
speed = 1;
SetSpeed();
}
public static void Seek(int addMsec)
{
// Debug feature 里面那个 timer 不能感知变速
// 为了和魔改版本统一polyfill 里面不修这个
// 这里重新实现一个能感知变速的 Seek
var msec = CurrentPlayMsec + addMsec;
if (msec < 0)
{
msec = 0;
}
CurrentPlayMsec = msec;
}
public static double CurrentPlayMsec
{
get => NotesManager.GetCurrentMsec() - 91;
set
{
DebugFeature.CurrentPlayMsec = value;
SetSpeedCoroutine();
}
}
public static PractiseModeUI ui;
[HarmonyPatch]
public class PatchNoteSpeed
{
public static IEnumerable<MethodBase> TargetMethods()
{
yield return AccessTools.Method(typeof(GameManager), "GetNoteSpeed");
yield return AccessTools.Method(typeof(GameManager), "GetTouchSpeed");
}
public static void Postfix(ref float __result)
{
if (!keepNoteSpeed) return;
__result /= speed;
}
}
[HarmonyPatch(typeof(GameProcess), "OnStart")]
[HarmonyPostfix]
public static void GameProcessPostStart()
{
repeatStart = -1;
repeatEnd = -1;
speed = 1;
ui = null;
}
[HarmonyPatch(typeof(GameCtrl), "Initialize")]
[HarmonyPostfix]
public static void GameCtrlPostInitialize(GameCtrl __instance)
{
gameCtrl = __instance;
}
# if DEBUG
[HarmonyPrefix]
[HarmonyPatch(typeof(GenericProcess), "OnUpdate")]
public static void OnGenericProcessUpdate(GenericMonitor[] ____monitors)
{
if (Input.GetKeyDown(KeyCode.F11))
{
____monitors[0].gameObject.AddComponent<PractiseModeUI>();
}
}
# endif
[HarmonyPatch(typeof(GameProcess), "OnUpdate")]
[HarmonyPostfix]
public static void GameProcessPostUpdate(GameProcess __instance, GameMonitor[] ____monitors)
{
if (InputManager.GetSystemInputPush(InputManager.SystemButtonSetting.ButtonTest) && ui is null)
{
ui = ____monitors[0].gameObject.AddComponent<PractiseModeUI>();
}
if (repeatStart >= 0 && repeatEnd >= 0)
{
if (CurrentPlayMsec >= repeatEnd)
{
CurrentPlayMsec = repeatStart;
}
}
}
private static float startGap = -1f;
[HarmonyPatch(typeof(NotesManager), "StartPlay")]
[HarmonyPostfix]
public static void NotesManagerPostUpdateTimer(float msecStartGap)
{
startGap = msecStartGap;
}
[HarmonyPatch(typeof(NotesManager), "UpdateTimer")]
[HarmonyPrefix]
public static bool NotesManagerPostUpdateTimer(bool ____isPlaying, Stopwatch ____stopwatch, ref float ____curMSec, ref float ____curMSecPre, float ____msecStartGap)
{
if (startGap != -1f)
{
____curMSec = startGap;
____curMSecPre = startGap;
____stopwatch?.Reset();
startGap = -1f;
}
else
{
____curMSecPre = ____curMSec;
if (____isPlaying && ____stopwatch != null && !DebugFeature.Pause)
{
var num = (double)____stopwatch.ElapsedTicks / Stopwatch.Frequency * 1000.0 * speed;
____curMSec += (float)num;
____stopwatch.Reset();
____stopwatch.Start();
}
}
return false;
}
[HarmonyPatch(typeof(SoundCtrl), "Initialize")]
[HarmonyPostfix]
public static void SoundCtrlPostInitialize(SoundCtrl.InitParam param, Dictionary<int, object> ____players)
{
var wrapper = ____players[2];
player = (CriAtomExPlayer)wrapper.GetType().GetField("Player").GetValue(wrapper);
// var pool = new CriAtomExStandardVoicePool(1, 8, 96000, true, 2);
// pool.AttachDspTimeStretch();
// player.SetVoicePoolIdentifier(pool.identifier);
// debug
// var wrapper1 = ____players[7];
// var player1 = (CriAtomExPlayer)wrapper1.GetType().GetField("Player").GetValue(wrapper1);
// var pool = new CriAtomExStandardVoicePool(1, 8, 96000, true, 2);
// pool.AttachDspTimeStretch();
// player1.SetVoicePoolIdentifier(pool.identifier);
// player1.SetDspTimeStretchRatio(2);
}
[HarmonyPatch(typeof(MovieController), "Awake")]
[HarmonyPostfix]
public static void MovieControllerPostAwake(MovieMaterialMai2 ____moviePlayers)
{
movie = ____moviePlayers;
}
}

View File

@@ -1,151 +0,0 @@
using System;
using AquaMai.Fix;
using AquaMai.Helpers;
using AquaMai.Resources;
using Manager;
using UnityEngine;
namespace AquaMai.Utils;
public class PractiseModeUI : MonoBehaviour
{
private static float windowTop => Screen.height - GuiSizes.PlayerWidth + GuiSizes.PlayerWidth * .22f;
private static float controlHeight => GuiSizes.PlayerWidth * .13f;
private static float sideButtonWidth => GuiSizes.PlayerWidth * .1f;
private static float centerButtonWidth => GuiSizes.PlayerWidth * .28f;
private static int fontSize => (int)(GuiSizes.PlayerWidth * .02f);
private static Rect GetButtonRect(int pos, int row)
{
float x;
float width;
switch (pos)
{
case 0:
x = GuiSizes.PlayerCenter - centerButtonWidth / 2 - sideButtonWidth - GuiSizes.Margin;
width = sideButtonWidth;
break;
case 1:
x = GuiSizes.PlayerCenter - centerButtonWidth / 2;
width = centerButtonWidth;
break;
case 2:
x = GuiSizes.PlayerCenter + centerButtonWidth / 2 + GuiSizes.Margin;
width = sideButtonWidth;
break;
default:
throw new ArgumentOutOfRangeException(nameof(pos), pos, null);
}
return new Rect(x, windowTop + (GuiSizes.Margin + controlHeight) * row + GuiSizes.Margin, width, controlHeight);
}
public void OnGUI()
{
var labelStyle = GUI.skin.GetStyle("label");
labelStyle.fontSize = fontSize;
labelStyle.alignment = TextAnchor.MiddleCenter;
var buttonStyle = GUI.skin.GetStyle("button");
buttonStyle.fontSize = fontSize;
GUI.Box(new Rect(
GuiSizes.PlayerCenter - centerButtonWidth / 2 - sideButtonWidth - GuiSizes.Margin * 2,
windowTop,
centerButtonWidth + sideButtonWidth * 2 + GuiSizes.Margin * 4,
controlHeight * 4 + GuiSizes.Margin * 5
), "");
GUI.Button(GetButtonRect(0, 0), Locale.SeekBackward);
GUI.Button(GetButtonRect(1, 0), Locale.Pause);
GUI.Button(GetButtonRect(2, 0), Locale.SeekForward);
if (PractiseMode.repeatStart == -1)
{
GUI.Button(GetButtonRect(0, 1), Locale.MarkRepeatStart);
GUI.Label(GetButtonRect(1, 1), Locale.RepeatNotSet);
}
else if (PractiseMode.repeatEnd == -1)
{
GUI.Button(GetButtonRect(0, 1), Locale.MarkRepeatEnd);
GUI.Label(GetButtonRect(1, 1), Locale.RepeatStartSet);
GUI.Button(GetButtonRect(2, 1), Locale.RepeatReset);
}
else
{
GUI.Label(GetButtonRect(1, 1), Locale.RepeatStartEndSet);
GUI.Button(GetButtonRect(2, 1), Locale.RepeatReset);
}
GUI.Button(GetButtonRect(0, 2), Locale.SpeedDown);
GUI.Label(GetButtonRect(1, 2), $"{Locale.Speed} {PractiseMode.speed * 100:000}%");
GUI.Button(GetButtonRect(2, 2), Locale.SpeedUp);
GUI.Button(GetButtonRect(1, 3), Locale.SpeedReset);
GUI.Label(GetButtonRect(0, 3), $"{TimeSpan.FromMilliseconds(PractiseMode.CurrentPlayMsec):mm\\:ss\\.fff}\n{TimeSpan.FromMilliseconds(NotesManager.Instance().getPlayFinalMsec()):mm\\:ss\\.fff}");
GUI.Button(GetButtonRect(2, 3), $"保持流速\n{(PractiseMode.keepNoteSpeed ? "ON" : "OFF")}");
}
public void Update()
{
if (InputManager.GetTouchPanelAreaDown(InputManager.TouchPanelArea.E8))
{
PractiseMode.Seek(-1000);
}
else if (InputManager.GetTouchPanelAreaDown(InputManager.TouchPanelArea.E2))
{
PractiseMode.Seek(1000);
}
else if (InputManager.GetTouchPanelAreaDown(InputManager.TouchPanelArea.B8) || InputManager.GetTouchPanelAreaDown(InputManager.TouchPanelArea.B1))
{
DebugFeature.Pause = !DebugFeature.Pause;
if (!DebugFeature.Pause)
{
PractiseMode.Seek(0);
}
}
else if (InputManager.GetTouchPanelAreaDown(InputManager.TouchPanelArea.B7) && PractiseMode.repeatStart == -1)
{
PractiseMode.repeatStart = PractiseMode.CurrentPlayMsec;
}
else if (InputManager.GetTouchPanelAreaDown(InputManager.TouchPanelArea.B7) && PractiseMode.repeatEnd == -1)
{
PractiseMode.SetRepeatEnd(PractiseMode.CurrentPlayMsec);
}
else if (InputManager.GetTouchPanelAreaDown(InputManager.TouchPanelArea.B2))
{
PractiseMode.ClearRepeat();
}
else if (InputManager.GetTouchPanelAreaDown(InputManager.TouchPanelArea.B6))
{
PractiseMode.SpeedDown();
}
else if (InputManager.GetTouchPanelAreaDown(InputManager.TouchPanelArea.B3))
{
PractiseMode.SpeedUp();
}
else if (InputManager.GetTouchPanelAreaDown(InputManager.TouchPanelArea.B5) || InputManager.GetTouchPanelAreaDown(InputManager.TouchPanelArea.B4))
{
PractiseMode.SpeedReset();
}
else if (InputManager.GetTouchPanelAreaDown(InputManager.TouchPanelArea.E4))
{
PractiseMode.keepNoteSpeed = !PractiseMode.keepNoteSpeed;
PractiseMode.gameCtrl?.ResetOptionSpeed();
}
else if (
InputManager.GetTouchPanelAreaDown(InputManager.TouchPanelArea.A1) ||
InputManager.GetTouchPanelAreaDown(InputManager.TouchPanelArea.A2) ||
InputManager.GetTouchPanelAreaDown(InputManager.TouchPanelArea.A3) ||
InputManager.GetTouchPanelAreaDown(InputManager.TouchPanelArea.A4) ||
InputManager.GetTouchPanelAreaDown(InputManager.TouchPanelArea.A5) ||
InputManager.GetTouchPanelAreaDown(InputManager.TouchPanelArea.A6) ||
InputManager.GetTouchPanelAreaDown(InputManager.TouchPanelArea.A7) ||
InputManager.GetTouchPanelAreaDown(InputManager.TouchPanelArea.A8)
)
{
PractiseMode.ui = null;
Destroy(this);
}
}
}