备份,准备做双端

This commit is contained in:
FloatGaming
2026-07-30 23:15:58 +08:00
parent add675e45d
commit ec4ec53545
88 changed files with 4050 additions and 872 deletions
+81 -16
View File
@@ -3,6 +3,7 @@ using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.UI;
public class controllerSettings : MonoBehaviour
@@ -34,7 +35,7 @@ public class controllerSettings : MonoBehaviour
private const int SecondaryTrack3Slot = 5;
private const float NoteSpeedMin = 1f;
private const float NoteSpeedMax = 3f;
private const float NoteSpeedMax = 3.25f;
private const string NoteSpeedPrefKey = "noteSpeedMultiplier";
private const string NoteSpeedDefaultVersionKey = "noteSpeedMultiplierDefaultVersion";
private const int NoteSpeedDefaultVersion = 2;
@@ -51,6 +52,12 @@ public class controllerSettings : MonoBehaviour
private Coroutine messageCoroutine;
private Coroutine continuousChangeCoroutine;
// Input System interactive rebind: a throwaway InputAction listens for the next keyboard
// press and reports the bound control's path, which we convert back to KeyCode so the
// existing KeyCode-based storage and conflict-swap logic stay unchanged.
private InputAction rebindAction;
private InputActionRebindingExtensions.RebindingOperation rebindOperation;
private void Start()
{
RefreshButtonLabels();
@@ -77,26 +84,17 @@ public class controllerSettings : MonoBehaviour
if (noteSpeed_IncreaseButton != null) noteSpeed_IncreaseButton.onClick.RemoveAllListeners();
if (noteSpeed_ResetButton != null) noteSpeed_ResetButton.onClick.RemoveAllListeners();
if (launch_delayTapper != null) launch_delayTapper.onClick.RemoveAllListeners();
CleanupRebindOperation();
}
private void Update()
{
if (isRebinding && Input.GetMouseButtonDown(0) && !IsPointerOverAnyKeyButton())
// Clicking away from the key buttons cancels an in-progress rebind. Key capture itself
// is handled by the Input System RebindingOperation started in OnKeyButtonClicked.
if (isRebinding && Mouse.current != null && Mouse.current.leftButton.wasPressedThisFrame && !IsPointerOverAnyKeyButton())
{
CancelRebind();
return;
}
if (!isRebinding) return;
foreach (KeyCode kc in Enum.GetValues(typeof(KeyCode)))
{
if (kc >= KeyCode.Mouse0 && kc <= KeyCode.Mouse6) continue;
if (kc >= KeyCode.JoystickButton0 && kc <= KeyCode.Joystick8Button19) continue;
if (!Input.GetKeyDown(kc)) continue;
HandleRebindKey(kc);
break;
}
}
@@ -210,7 +208,8 @@ public class controllerSettings : MonoBehaviour
{
if (EventSystem.current == null) return false;
PointerEventData pointerData = new PointerEventData(EventSystem.current) { position = Input.mousePosition };
Vector2 mousePos = Mouse.current != null ? Mouse.current.position.ReadValue() : Vector2.zero;
PointerEventData pointerData = new PointerEventData(EventSystem.current) { position = mousePos };
List<RaycastResult> results = new List<RaycastResult>();
EventSystem.current.RaycastAll(pointerData, results);
if (results.Count == 0) return false;
@@ -246,6 +245,68 @@ public class controllerSettings : MonoBehaviour
blinkCoroutine = StartCoroutine(BlinkUnderscore(index));
ShowPersistentMessage("按下新按键", messageErrorColor);
StartInteractiveRebind();
}
/// <summary>
/// Start an Input System interactive rebind that waits for the next keyboard press.
/// The captured control path is mapped back to KeyCode and fed into the existing
/// HandleRebindKey conflict-swap logic, keeping storage and behavior equivalent.
/// </summary>
private void StartInteractiveRebind()
{
CleanupRebindOperation();
rebindAction = new InputAction("Rebind", InputActionType.Button, expectedControlType: "Button");
// PerformInteractiveRebinding needs an existing binding (index 0) to override.
rebindAction.AddBinding("<Keyboard>/space");
rebindOperation = rebindAction.PerformInteractiveRebinding(0)
.WithControlsExcluding("<Mouse>/leftButton")
.WithControlsExcluding("<Mouse>/rightButton")
.WithControlsExcluding("<Mouse>/middleButton")
.WithControlsExcluding("<Mouse>/position")
.WithControlsExcluding("<Mouse>/delta")
.WithCancelingThrough("<Keyboard>/escape")
.OnCancel(_ => { CleanupRebindOperation(); CancelRebind(); })
.OnComplete(op =>
{
// selectedControl.name is the control name (e.g. "d", "space"); map to KeyCode.
KeyCode captured = ResolveKeyCodeFromControl(op.selectedControl);
CleanupRebindOperation();
if (captured == KeyCode.None)
{
// Unmappable key: treat like a cancel so we don't clobber the binding.
CancelRebind();
return;
}
HandleRebindKey(captured);
})
.Start();
}
private static KeyCode ResolveKeyCodeFromControl(InputControl control)
{
if (control == null) return KeyCode.None;
// control.path -> "/Keyboard/d"; the last segment is the control name.
string name = control.name; // e.g. "d", "space", "leftShift"
return InputSystemKeyMap.PathToKeyCode("<Keyboard>/" + name);
}
private void CleanupRebindOperation()
{
if (rebindOperation != null)
{
rebindOperation.Dispose();
rebindOperation = null;
}
if (rebindAction != null)
{
rebindAction.Dispose();
rebindAction = null;
}
}
private IEnumerator BlinkUnderscore(int index)
@@ -297,6 +358,7 @@ public class controllerSettings : MonoBehaviour
previousKey = KeyCode.None;
RefreshButtonLabels();
InputManager.Instance?.RefreshKeyLabels();
GameplayInputActions.Instance?.RefreshBindings();
StopRebind();
}
@@ -402,10 +464,13 @@ public class controllerSettings : MonoBehaviour
private void CancelRebind()
{
CleanupRebindOperation();
if (previousKeyValid && IsValidBindingSlot(rebindingIndex))
{
SetKeyForSlot(rebindingIndex, previousKey);
InputManager.Instance?.RefreshKeyLabels();
GameplayInputActions.Instance?.RefreshBindings();
ClearMessage();
ShowMessage("按键设置已保存", messageSuccessColor, 2f);
}
+19 -2
View File
@@ -48,7 +48,11 @@ public class graphicSettings : MonoBehaviour
}
#endif
int screenMode = PlayerPrefs.GetInt(PrefKeyScreenMode, 0);
// 无存档(首次运行)时,跟随 Player Settings 里的启动全屏模式,而不是硬编码窗口化(0)。
// 否则会把 ProjectSettings 的独占全屏强切成窗口化,且窗口化分支无兜底分辨率,
// 导致 Unity 回落到内建默认窗口尺寸 1280x720。
int defaultScreenMode = MapFullScreenModeToIndex(Screen.fullScreenMode);
int screenMode = PlayerPrefs.GetInt(PrefKeyScreenMode, defaultScreenMode);
screenMode = Mathf.Clamp(screenMode, 0, 2);
try
@@ -141,7 +145,7 @@ public class graphicSettings : MonoBehaviour
screenMode_Dropdown.onValueChanged.AddListener(OnScreenModeChanged);
}
private int MapFullScreenModeToIndex(FullScreenMode mode)
private static int MapFullScreenModeToIndex(FullScreenMode mode)
{
switch (mode)
{
@@ -492,6 +496,19 @@ public class graphicSettings : MonoBehaviour
if (savedResIndex < 0)
{
// 无任何分辨率存档(首次运行,savedResIndex == -2)。
// 全屏模式下 ApplyScreenModeStatic 已用显示器原生分辨率铺满,无需处理。
// 但窗口模式下 ApplyScreenModeStatic 只是沿用启动瞬间的窗口尺寸(常为引擎默认 1280x720),
// 这里兜底到 1920x1080(受当前显示器上限约束),避免默认落到 720p。
if (Screen.fullScreenMode == FullScreenMode.Windowed)
{
const int FallbackW = 1920;
const int FallbackH = 1080;
Resolution cur = Screen.currentResolution;
int w = Mathf.Min(FallbackW, cur.width);
int h = Mathf.Min(FallbackH, cur.height);
Screen.SetResolution(w, h, FullScreenMode.Windowed, cur.refreshRateRatio);
}
return;
}