109 lines
4.1 KiB
C#
109 lines
4.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using Harmony;
|
|
using MSCLoader;
|
|
using UnityEngine;
|
|
|
|
namespace MSCO
|
|
{
|
|
/// <summary>
|
|
/// Solange ein Eingabefenster offen ist (F8-Konsole, Chat, Admin-Menü): Spieler bewegt sich nicht,
|
|
/// Kamera dreht nicht mit, Mauszeiger ist frei. Danach wird genau das wieder eingeschaltet,
|
|
/// was hier ausgeschaltet wurde.
|
|
/// </summary>
|
|
public static class InputLock
|
|
{
|
|
static readonly string[] ControlScripts =
|
|
{
|
|
"CharacterMotor", "FPSInputController", "MouseLook", "SimpleSmoothMouseLook", "SmoothMouseLook", "MouseLook2", "MouseLook3"
|
|
};
|
|
|
|
static readonly List<Behaviour> disabled = new List<Behaviour>();
|
|
static bool locked;
|
|
static bool previousVisible;
|
|
static CursorLockMode previousLock;
|
|
static bool patched;
|
|
|
|
public static bool Locked { get { return locked; } }
|
|
|
|
public static void Set(bool on)
|
|
{
|
|
if (on) KeepCursorFree();
|
|
if (on == locked) return;
|
|
locked = on;
|
|
|
|
if (on)
|
|
{
|
|
PatchCursorActions();
|
|
previousVisible = Cursor.visible;
|
|
previousLock = Cursor.lockState;
|
|
GameObject player = GameObject.Find("PLAYER");
|
|
if (player != null)
|
|
{
|
|
foreach (MonoBehaviour mb in player.GetComponentsInChildren<MonoBehaviour>())
|
|
{
|
|
if (mb == null || !mb.enabled || Array.IndexOf(ControlScripts, mb.GetType().Name) < 0) continue;
|
|
mb.enabled = false;
|
|
disabled.Add(mb);
|
|
}
|
|
}
|
|
KeepCursorFree();
|
|
}
|
|
else
|
|
{
|
|
foreach (Behaviour b in disabled) if (b != null) b.enabled = true;
|
|
disabled.Clear();
|
|
PlayMakerGUI.LockCursor = previousLock != CursorLockMode.None;
|
|
PlayMakerGUI.HideCursor = !previousVisible;
|
|
Cursor.visible = previousVisible;
|
|
Cursor.lockState = previousLock;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Das Spiel sperrt den Zeiger jeden Frame wieder (PlayMakerGUI.LockCursor + "SetMouseCursor"-Aktionen),
|
|
/// dadurch springt er in die Mitte. Solange offen: überall freigeben - auch aus OnGUI/LateUpdate aufrufen.
|
|
/// </summary>
|
|
public static void KeepCursorFree()
|
|
{
|
|
if (!locked) return;
|
|
PlayMakerGUI.LockCursor = false;
|
|
PlayMakerGUI.HideCursor = false;
|
|
Cursor.visible = true;
|
|
Cursor.lockState = CursorLockMode.None;
|
|
}
|
|
|
|
/// <summary>PlayMaker-Aktionen, die den Mauszeiger setzen, überspringen, solange ein Fenster offen ist.</summary>
|
|
static void PatchCursorActions()
|
|
{
|
|
if (patched) return;
|
|
patched = true;
|
|
try
|
|
{
|
|
Type action = null;
|
|
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
|
|
{
|
|
action = asm.GetType("HutongGames.PlayMaker.Actions.SetMouseCursor");
|
|
if (action != null) break;
|
|
}
|
|
if (action == null) return;
|
|
|
|
HarmonyInstance harmony = HarmonyInstance.Create("mbm.msco.inputlock");
|
|
var prefix = new HarmonyMethod(typeof(InputLock).GetMethod("SkipWhileLocked", BindingFlags.Static | BindingFlags.NonPublic));
|
|
foreach (string name in new[] { "OnEnter", "OnUpdate", "DoSetMouseCursor" })
|
|
{
|
|
MethodInfo m = action.GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
|
if (m != null && m.DeclaringType == action) harmony.Patch(m, prefix, null);
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
ModConsole.Warning("[MSCO] Could not patch cursor actions: " + e.Message);
|
|
}
|
|
}
|
|
|
|
static bool SkipWhileLocked() { return !locked; }
|
|
}
|
|
}
|