using System.Collections.Generic;
using System.Reflection;
using AquaMai.Config.Attributes;
using AquaMai.Config.Types;
using AquaMai.Core;
using AquaMai.Core.Helpers;
using AquaMai.Core.Resources;
using AquaMai.Mods.GameSystem;
using HarmonyLib;
using MelonLoader;
using UnityEngine;
using UnityEngine.UI;
namespace AquaMai.Mods.Utils;
[ConfigSection(
zh: """
屏幕位置调整。适用于手台对不齐的情况,可以分别调整每个屏幕区域的位置
在游戏中按键开启调整模式
此功能会对性能产生一定影响
必须同时开启 ExteraMouseInput 才能使用鼠标模拟触摸
""",
en: """
Screen position adjustment. Suitable for cases where the screen are not aligned, allowing separate adjustments for each screen area.
Enter adjustment mode by pressing the key in-game.
This feature may have a slight performance impact.
ExteraMouseInput must be enabled to use mouse simulation for touch input.
"""
)]
public class ScreenPositionAdjust
{
[ConfigEntry(zh: "上屏紧贴着下屏", en: "Top screen is tightly attached to the bottom screen")]
public static readonly bool compactMode = false;
[ConfigEntry(zh: "进入调整模式的按键", en: "Key to enter adjustment mode")]
public static readonly KeyCodeOrName adjustKey = KeyCodeOrName.F10;
private static GameObject root;
// main1P sub1P main2P sub2P
private static Transform[] images = new Transform[4];
private static Camera[] cameras = new Camera[4];
private static RenderTexture[] renderTextures = new RenderTexture[4];
private static Transform[] mouseTouchPanels = new Transform[2];
private static readonly Vector3 mouseTouchPanelsDelta = new Vector3(0, (1920 - 1080) / 2f, 0);
///
/// 避免一帧延迟
///
private class CameraUpdater : MonoBehaviour
{
void OnPreRender()
{
foreach (var camera in cameras)
{
if (camera == null)
{
continue;
}
camera.Render();
}
}
}
private static float GetSizeFactor()
{
return Screen.height / (compactMode ? 1080f + 450f : 1920f);
}
///
/// 调整大小时重新调整 texture 大小,让显示质量最好
///
private class DynamicRenderTextureResizer : MonoBehaviour
{
private int lastHeight;
void Start()
{
lastHeight = Screen.height;
}
void Update()
{
if (Screen.height == lastHeight) return;
#if DEBUG
MelonLogger.Msg("[ScreenPositionAdjust] Screen height changed, resizing render textures.");
#endif
lastHeight = Screen.height;
for (int i = 0; i < renderTextures.Length; i++)
{
if (renderTextures[i] != null)
{
renderTextures[i].Release();
renderTextures[i].width = (int)(1080 * GetSizeFactor());
renderTextures[i].height = (int)(((i % 2 == 0) ? 1080 : 450) * GetSizeFactor());
renderTextures[i].Create();
}
}
}
}
private static float[] offsetX = new float[4];
private static float[] offsetY = new float[4];
private class AdjustController : MonoBehaviour
{
private int index = -1;
private float speed = 1f;
private void OnGUI()
{
if (index == -1) return;
var rect = new Rect(0, 0, GuiSizes.FontSize * 50, GuiSizes.FontSize * 15);
var player = index < 2 ? "1P" : "2P";
var sub = index % 2 == 0 ? "Main" : "Sub";
var labelStyle = GUI.skin.GetStyle("label");
labelStyle.fontSize = GuiSizes.FontSize * 2;
labelStyle.alignment = TextAnchor.MiddleLeft;
GUI.Box(rect, "");
GUI.Label(rect, string.Format(Locale.ScreenPositionAdjustTip, $"{player} {sub}", speed, adjustKey));
}
private void Update()
{
if (KeyListener.GetKeyDown(adjustKey))
{
index++;
if (index > 3)
{
index = -1;
}
if (index == -1)
{
for (int i = 0; i < 4; i++)
{
PlayerPrefs.SetFloat($"AquaMaiScreenPositionAdjust-x:{i}", offsetX[i]);
PlayerPrefs.SetFloat($"AquaMaiScreenPositionAdjust-y:{i}", offsetY[i]);
}
PlayerPrefs.Save();
mouseTouchPanels[0].position = images[0].position + mouseTouchPanelsDelta;
mouseTouchPanels[1].position = images[2].position + mouseTouchPanelsDelta;
return;
}
}
if (index == -1) return;
if (Input.GetKeyDown(KeyCode.LeftArrow))
{
offsetX[index] -= speed;
images[index].localPosition -= new Vector3(speed, 0, 0);
}
else if (Input.GetKeyDown(KeyCode.RightArrow))
{
offsetX[index] += speed;
images[index].localPosition += new Vector3(speed, 0, 0);
}
else if (Input.GetKeyDown(KeyCode.UpArrow))
{
offsetY[index] += speed;
images[index].localPosition += new Vector3(0, speed, 0);
}
else if (Input.GetKeyDown(KeyCode.DownArrow))
{
offsetY[index] -= speed;
images[index].localPosition -= new Vector3(0, speed, 0);
}
else if (Input.GetKeyDown(KeyCode.LeftBracket))
{
speed /= 2f;
}
else if (Input.GetKeyDown(KeyCode.RightBracket))
{
speed *= 2f;
}
}
}
[HarmonyPatch]
public class Init
{
public static IEnumerable TargetMethods()
{
return SinglePlayer.WhateverInitialize.TargetMethods();
}
public static void Prefix(Transform left, Transform right)
{
root = new GameObject("[AquaMai] ScreenPositionAdjust Display", [typeof(Canvas)]);
root.transform.position = new Vector3(11451, 19198, 0);
var canvas = root.GetComponent