Compare commits
9 Commits
ca4d33698f
...
9a66f43074
| Author | SHA1 | Date | |
|---|---|---|---|
| 9a66f43074 | |||
| 1a4ef2062e | |||
| 340a50a239 | |||
| 28c30f7ec3 | |||
| 8b57227c01 | |||
| e8bc6aea46 | |||
| f244634679 | |||
| a63324959a | |||
| 88af70ff61 |
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -7,9 +7,6 @@
|
||||
[submodule "Client/Packages/com.alicizax.unity.editor.extension"]
|
||||
path = Client/Packages/com.alicizax.unity.editor.extension
|
||||
url = http://101.34.252.46:3000/AlicizaX/com.alicizax.unity.editor.extension.git
|
||||
[submodule "Client/Packages/com.alicizax.unity.entry"]
|
||||
path = Client/Packages/com.alicizax.unity.entry
|
||||
url = http://101.34.252.46:3000/AlicizaX/com.alicizax.unity.entry.git
|
||||
[submodule "Client/Packages/com.alicizax.unity.framework"]
|
||||
path = Client/Packages/com.alicizax.unity.framework
|
||||
url = http://101.34.252.46:3000/AlicizaX/com.alicizax.unity.framework.git
|
||||
@ -22,6 +19,3 @@
|
||||
[submodule "Client/Packages/com.alicizax.unity.ui.extension"]
|
||||
path = Client/Packages/com.alicizax.unity.ui.extension
|
||||
url = http://101.34.252.46:3000/AlicizaX/com.alicizax.unity.ui.extension.git
|
||||
[submodule "Client/Packages/com.alicizax.unity.network"]
|
||||
path = Client/Packages/com.alicizax.unity.network
|
||||
url = http://101.34.252.46:3000/AlicizaX/com.alicizax.unity.network.git
|
||||
|
||||
@ -0,0 +1,301 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
/// <summary>
|
||||
/// 输入读取工具。
|
||||
/// 负责运行时输入轮询、单次触发和切换态管理,
|
||||
/// 与 InputBindingManager 的绑定/重绑定职责分离。
|
||||
/// </summary>
|
||||
public static class InputActionReader
|
||||
{
|
||||
/// <summary>
|
||||
/// 用于标识一次输入读取上下文。
|
||||
/// 同一个 Action 在不同 owner 或 key 下会拥有独立的按下状态。
|
||||
/// </summary>
|
||||
private readonly struct InputReadKey : IEquatable<InputReadKey>
|
||||
{
|
||||
public readonly string ActionName;
|
||||
public readonly int OwnerId;
|
||||
public readonly string OwnerKey;
|
||||
|
||||
/// <summary>
|
||||
/// 使用实例 ID 作为拥有者标识,适合 Unity 对象。
|
||||
/// </summary>
|
||||
public InputReadKey(string actionName, int ownerId)
|
||||
{
|
||||
ActionName = actionName ?? string.Empty;
|
||||
OwnerId = ownerId;
|
||||
OwnerKey = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用字符串作为拥有者标识,适合外部系统或手动传入的 key。
|
||||
/// </summary>
|
||||
public InputReadKey(string actionName, string ownerKey)
|
||||
{
|
||||
ActionName = actionName ?? string.Empty;
|
||||
OwnerId = 0;
|
||||
OwnerKey = ownerKey ?? string.Empty;
|
||||
}
|
||||
|
||||
public bool Equals(InputReadKey other)
|
||||
{
|
||||
return OwnerId == other.OwnerId
|
||||
&& string.Equals(ActionName, other.ActionName, StringComparison.Ordinal)
|
||||
&& string.Equals(OwnerKey, other.OwnerKey, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is InputReadKey other && Equals(other);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hashCode = 17;
|
||||
hashCode = (hashCode * 31) + OwnerId;
|
||||
hashCode = (hashCode * 31) + StringComparer.Ordinal.GetHashCode(ActionName);
|
||||
hashCode = (hashCode * 31) + StringComparer.Ordinal.GetHashCode(OwnerKey);
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 记录“本次按下已消费”的键,用于 Once 语义。
|
||||
private static readonly HashSet<InputReadKey> PressedKeys = new();
|
||||
// 记录当前处于开启状态的切换键。
|
||||
private static readonly HashSet<InputReadKey> ToggledKeys = new();
|
||||
|
||||
/// <summary>
|
||||
/// 直接读取指定 Action 的值。
|
||||
/// </summary>
|
||||
public static T ReadValue<T>(string actionName) where T : struct
|
||||
{
|
||||
return ResolveAction(actionName).ReadValue<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 以 object 形式读取指定 Action 的值。
|
||||
/// </summary>
|
||||
public static object ReadValue(string actionName)
|
||||
{
|
||||
return ResolveAction(actionName).ReadValueAsObject();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 仅在 Action 处于按下状态时读取值。
|
||||
/// </summary>
|
||||
public static bool TryReadValue<T>(string actionName, out T value) where T : struct
|
||||
{
|
||||
InputAction inputAction = ResolveAction(actionName);
|
||||
if (inputAction.IsPressed())
|
||||
{
|
||||
value = inputAction.ReadValue<T>();
|
||||
return true;
|
||||
}
|
||||
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 仅在 Action 处于按下状态时以 object 形式读取值。
|
||||
/// </summary>
|
||||
public static bool TryReadValue(string actionName, out object value)
|
||||
{
|
||||
InputAction inputAction = ResolveAction(actionName);
|
||||
if (inputAction.IsPressed())
|
||||
{
|
||||
value = inputAction.ReadValueAsObject();
|
||||
return true;
|
||||
}
|
||||
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 只在本次按下的第一帧返回 true,并输出当前值。
|
||||
/// owner 用来隔离不同对象的读取状态。
|
||||
/// </summary>
|
||||
public static bool TryReadValueOnce<T>(UnityEngine.Object owner, string actionName, out T value) where T : struct
|
||||
{
|
||||
if (owner == null)
|
||||
{
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
return TryReadValueOnceInternal(new InputReadKey(actionName, owner.GetInstanceID()), actionName, out value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取按钮型 Action。
|
||||
/// 非按钮类型会直接抛出异常,避免误用。
|
||||
/// </summary>
|
||||
public static bool ReadButton(string actionName)
|
||||
{
|
||||
InputAction inputAction = ResolveAction(actionName);
|
||||
if (inputAction.type == InputActionType.Button)
|
||||
{
|
||||
return Convert.ToBoolean(inputAction.ReadValueAsObject());
|
||||
}
|
||||
|
||||
throw new NotSupportedException("[InputActionReader] The Input Action must be a button type.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对 Unity 对象做一次性按钮读取。
|
||||
/// </summary>
|
||||
public static bool ReadButtonOnce(UnityEngine.Object owner, string actionName)
|
||||
{
|
||||
return owner != null && ReadButtonOnce(owner.GetInstanceID(), actionName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对实例 ID 做一次性按钮读取。
|
||||
/// </summary>
|
||||
public static bool ReadButtonOnce(int instanceID, string actionName)
|
||||
{
|
||||
return ReadButtonOnceInternal(new InputReadKey(actionName, instanceID), actionName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对字符串 key 做一次性按钮读取。
|
||||
/// </summary>
|
||||
public static bool ReadButtonOnce(string key, string actionName)
|
||||
{
|
||||
return ReadButtonOnceInternal(new InputReadKey(actionName, key), actionName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对 Unity 对象读取按钮切换态。
|
||||
/// 每次新的按下沿会在开/关之间切换。
|
||||
/// </summary>
|
||||
public static bool ReadButtonToggle(UnityEngine.Object owner, string actionName)
|
||||
{
|
||||
return owner != null && ReadButtonToggle(owner.GetInstanceID(), actionName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对实例 ID 读取按钮切换态。
|
||||
/// </summary>
|
||||
public static bool ReadButtonToggle(int instanceID, string actionName)
|
||||
{
|
||||
return ReadButtonToggleInternal(new InputReadKey(actionName, instanceID), actionName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对字符串 key 读取按钮切换态。
|
||||
/// </summary>
|
||||
public static bool ReadButtonToggle(string key, string actionName)
|
||||
{
|
||||
return ReadButtonToggleInternal(new InputReadKey(actionName, key), actionName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置指定 key 的切换态。
|
||||
/// </summary>
|
||||
public static void ResetToggledButton(string key, string actionName)
|
||||
{
|
||||
ToggledKeys.Remove(new InputReadKey(actionName, key));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置某个 Action 名称下的所有切换态。
|
||||
/// </summary>
|
||||
public static void ResetToggledButton(string actionName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(actionName) || ToggledKeys.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
InputReadKey[] snapshot = new InputReadKey[ToggledKeys.Count];
|
||||
ToggledKeys.CopyTo(snapshot);
|
||||
for (int i = 0; i < snapshot.Length; i++)
|
||||
{
|
||||
if (string.Equals(snapshot[i].ActionName, actionName, StringComparison.Ordinal))
|
||||
{
|
||||
ToggledKeys.Remove(snapshot[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空全部切换态缓存。
|
||||
/// </summary>
|
||||
public static void ResetToggledButtons()
|
||||
{
|
||||
ToggledKeys.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析 Action;找不到时立即抛错,避免静默失败。
|
||||
/// </summary>
|
||||
private static InputAction ResolveAction(string actionName)
|
||||
{
|
||||
return InputBindingManager.Action(actionName)
|
||||
?? throw new InvalidOperationException($"[InputActionReader] Action '{actionName}' is not available.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 内部的单次值读取逻辑。
|
||||
/// 当按键抬起时,会清理 PressedKeys 中对应状态。
|
||||
/// </summary>
|
||||
private static bool TryReadValueOnceInternal<T>(InputReadKey readKey, string actionName, out T value) where T : struct
|
||||
{
|
||||
InputAction inputAction = ResolveAction(actionName);
|
||||
if (inputAction.IsPressed())
|
||||
{
|
||||
if (PressedKeys.Add(readKey))
|
||||
{
|
||||
value = inputAction.ReadValue<T>();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PressedKeys.Remove(readKey);
|
||||
}
|
||||
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 内部的按钮单次触发逻辑。
|
||||
/// 只有第一次按下返回 true,持续按住不会重复触发。
|
||||
/// </summary>
|
||||
private static bool ReadButtonOnceInternal(InputReadKey readKey, string actionName)
|
||||
{
|
||||
if (ReadButton(actionName))
|
||||
{
|
||||
return PressedKeys.Add(readKey);
|
||||
}
|
||||
|
||||
PressedKeys.Remove(readKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 内部的按钮切换逻辑。
|
||||
/// 基于 Once 触发,在每次新的按下沿时切换状态。
|
||||
/// </summary>
|
||||
private static bool ReadButtonToggleInternal(InputReadKey readKey, string actionName)
|
||||
{
|
||||
if (ReadButtonOnceInternal(readKey, actionName))
|
||||
{
|
||||
if (!ToggledKeys.Add(readKey))
|
||||
{
|
||||
ToggledKeys.Remove(readKey);
|
||||
}
|
||||
}
|
||||
|
||||
return ToggledKeys.Contains(readKey);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9368556ed4729ae618e0a19d3a7925b
|
||||
timeCreated: 1773811724
|
||||
@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using AlicizaX;
|
||||
@ -21,19 +19,18 @@ public class InputBindingManager : MonoSingleton<InputBindingManager>
|
||||
[Tooltip("InputActionAsset to manage")]
|
||||
public InputActionAsset actions;
|
||||
|
||||
public string fileName = "input_bindings.json";
|
||||
private const string FILE_NAME = "input_bindings.json";
|
||||
public bool debugMode = false;
|
||||
|
||||
public Dictionary<string, ActionMap> actionMap = new Dictionary<string, ActionMap>();
|
||||
public HashSet<RebindContext> preparedRebinds = new HashSet<RebindContext>();
|
||||
|
||||
internal InputActionRebindingExtensions.RebindingOperation rebindOperation;
|
||||
private bool isApplyPending = false;
|
||||
private string defaultBindingsJson = string.Empty;
|
||||
private string cachedSavePath;
|
||||
private Dictionary<string, (ActionMap map, ActionMap.Action action)> actionLookup = new Dictionary<string, (ActionMap, ActionMap.Action)>();
|
||||
|
||||
// 用于替代 Rx.NET Subjects 的事件
|
||||
private readonly Dictionary<string, ActionMap> actionMap = new(StringComparer.Ordinal);
|
||||
private readonly HashSet<RebindContext> preparedRebinds = new();
|
||||
private readonly Dictionary<string, (ActionMap map, ActionMap.Action action)> actionLookup = new(StringComparer.Ordinal);
|
||||
private readonly Dictionary<Guid, (ActionMap map, ActionMap.Action action)> actionLookupById = new();
|
||||
private readonly HashSet<string> ambiguousActionNames = new(StringComparer.Ordinal);
|
||||
private event Action _onInputsInit;
|
||||
|
||||
public event Action OnInputsInit
|
||||
@ -59,6 +56,9 @@ public class InputBindingManager : MonoSingleton<InputBindingManager>
|
||||
|
||||
private bool isInputsInitialized = false;
|
||||
|
||||
public IReadOnlyDictionary<string, ActionMap> ActionMaps => actionMap;
|
||||
public IReadOnlyCollection<RebindContext> PreparedRebinds => preparedRebinds;
|
||||
|
||||
public string SavePath
|
||||
{
|
||||
get
|
||||
@ -71,7 +71,7 @@ public class InputBindingManager : MonoSingleton<InputBindingManager>
|
||||
#else
|
||||
string folder = Application.persistentDataPath;
|
||||
#endif
|
||||
cachedSavePath = Path.Combine(folder, fileName);
|
||||
cachedSavePath = Path.Combine(folder, FILE_NAME);
|
||||
return cachedSavePath;
|
||||
}
|
||||
}
|
||||
@ -160,38 +160,48 @@ public class InputBindingManager : MonoSingleton<InputBindingManager>
|
||||
|
||||
private void BuildActionMap()
|
||||
{
|
||||
// 预分配已知容量以避免调整大小
|
||||
int mapCount = actions.actionMaps.Count;
|
||||
actionMap.Clear();
|
||||
actionLookup.Clear();
|
||||
|
||||
// 估算总操作数以便更好地分配内存
|
||||
int estimatedActionCount = 0;
|
||||
foreach (var map in actions.actionMaps)
|
||||
{
|
||||
estimatedActionCount += map.actions.Count;
|
||||
}
|
||||
|
||||
// 确保容量以避免重新哈希
|
||||
if (actionMap.Count == 0)
|
||||
{
|
||||
actionMap = new Dictionary<string, ActionMap>(mapCount);
|
||||
actionLookup = new Dictionary<string, (ActionMap, ActionMap.Action)>(estimatedActionCount);
|
||||
}
|
||||
actionLookupById.Clear();
|
||||
ambiguousActionNames.Clear();
|
||||
|
||||
foreach (var map in actions.actionMaps)
|
||||
{
|
||||
var actionMapObj = new ActionMap(map);
|
||||
actionMap.Add(map.name, actionMapObj);
|
||||
|
||||
// 构建查找字典以实现 O(1) 操作访问
|
||||
foreach (var actionPair in actionMapObj.actions)
|
||||
{
|
||||
actionLookup[actionPair.Key] = (actionMapObj, actionPair.Value);
|
||||
RegisterActionLookup(map.name, actionPair.Key, actionMapObj, actionPair.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RegisterActionLookup(string mapName, string actionName, ActionMap map, ActionMap.Action action)
|
||||
{
|
||||
actionLookupById[action.action.id] = (map, action);
|
||||
actionLookup[$"{mapName}/{actionName}"] = (map, action);
|
||||
|
||||
if (ambiguousActionNames.Contains(actionName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (actionLookup.TryGetValue(actionName, out var existing))
|
||||
{
|
||||
if (existing.action.action != action.action)
|
||||
{
|
||||
actionLookup.Remove(actionName);
|
||||
ambiguousActionNames.Add(actionName);
|
||||
Debug.LogWarning($"[InputBindingManager] Duplicate action name '{actionName}' detected. Use 'MapName/{actionName}' to resolve it.");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
actionLookup[actionName] = (map, action);
|
||||
}
|
||||
|
||||
private void RefreshBindingPathsFromActions()
|
||||
{
|
||||
foreach (var mapPair in actionMap.Values)
|
||||
@ -346,16 +356,26 @@ public class InputBindingManager : MonoSingleton<InputBindingManager>
|
||||
{
|
||||
if (obj is not RebindContext other) return false;
|
||||
if (action == null || other.action == null) return false;
|
||||
return action.name == other.action.name && bindingIndex == other.bindingIndex;
|
||||
return action.id == other.action.id && bindingIndex == other.bindingIndex;
|
||||
}
|
||||
|
||||
public override int GetHashCode() => (action?.name ?? string.Empty, bindingIndex).GetHashCode();
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hashCode = 17;
|
||||
hashCode = (hashCode * 31) + (action != null ? action.id.GetHashCode() : 0);
|
||||
hashCode = (hashCode * 31) + bindingIndex;
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (cachedToString == null && action != null)
|
||||
{
|
||||
cachedToString = $"{action.name}:{bindingIndex}";
|
||||
string mapName = action.actionMap != null ? action.actionMap.name : "<no-map>";
|
||||
cachedToString = $"{mapName}/{action.name}:{bindingIndex}";
|
||||
}
|
||||
|
||||
return cachedToString ?? "<null>";
|
||||
@ -374,15 +394,40 @@ public class InputBindingManager : MonoSingleton<InputBindingManager>
|
||||
var instance = Instance;
|
||||
if (instance == null) return null;
|
||||
|
||||
if (instance.actionLookup.TryGetValue(actionName, out var result))
|
||||
if (TryGetAction(actionName, out InputAction action))
|
||||
{
|
||||
return result.action.action;
|
||||
return action;
|
||||
}
|
||||
|
||||
if (instance.ambiguousActionNames.Contains(actionName))
|
||||
{
|
||||
Debug.LogError($"[InputBindingManager] Action name '{actionName}' is ambiguous. Use 'MapName/{actionName}' instead.");
|
||||
return null;
|
||||
}
|
||||
|
||||
Debug.LogError($"[InputBindingManager] Could not find action '{actionName}'");
|
||||
return null;
|
||||
}
|
||||
|
||||
public static bool TryGetAction(string actionName, out InputAction action)
|
||||
{
|
||||
var instance = Instance;
|
||||
if (instance == null || string.IsNullOrWhiteSpace(actionName))
|
||||
{
|
||||
action = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (instance.actionLookup.TryGetValue(actionName, out var result))
|
||||
{
|
||||
action = result.action.action;
|
||||
return true;
|
||||
}
|
||||
|
||||
action = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 开始重新绑定指定的输入操作
|
||||
/// </summary>
|
||||
@ -443,7 +488,7 @@ public class InputBindingManager : MonoSingleton<InputBindingManager>
|
||||
}
|
||||
}
|
||||
|
||||
var bp = GetBindingPath(ctx.action.name, ctx.bindingIndex);
|
||||
var bp = GetBindingPath(ctx.action, ctx.bindingIndex);
|
||||
if (bp != null)
|
||||
{
|
||||
bp.EffectivePath = (ctx.overridePath == NULL_BINDING) ? string.Empty : ctx.overridePath;
|
||||
@ -607,11 +652,11 @@ public class InputBindingManager : MonoSingleton<InputBindingManager>
|
||||
|
||||
if (string.IsNullOrEmpty(context.overridePath))
|
||||
{
|
||||
var bp = GetBindingPath(context.action.name, context.bindingIndex);
|
||||
var bp = GetBindingPath(context.action, context.bindingIndex);
|
||||
if (bp != null) context.overridePath = bp.bindingPath;
|
||||
}
|
||||
|
||||
var bindingPath = GetBindingPath(context.action.name, context.bindingIndex);
|
||||
var bindingPath = GetBindingPath(context.action, context.bindingIndex);
|
||||
if (bindingPath == null) return;
|
||||
|
||||
if (bindingPath.EffectivePath != context.overridePath)
|
||||
@ -695,17 +740,45 @@ public class InputBindingManager : MonoSingleton<InputBindingManager>
|
||||
var instance = Instance;
|
||||
if (instance == null) return null;
|
||||
|
||||
if (instance.actionLookup.TryGetValue(actionName, out var result))
|
||||
if (instance.TryGetActionRecord(actionName, out var result)
|
||||
&& result.action.bindings.TryGetValue(bindingIndex, out var binding))
|
||||
{
|
||||
if (result.action.bindings.TryGetValue(bindingIndex, out var binding))
|
||||
{
|
||||
return binding.bindingPath;
|
||||
}
|
||||
return binding.bindingPath;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static BindingPath GetBindingPath(InputAction action, int bindingIndex = 0)
|
||||
{
|
||||
var instance = Instance;
|
||||
if (instance == null || action == null) return null;
|
||||
|
||||
if (instance.TryGetActionRecord(action, out var result)
|
||||
&& result.action.bindings.TryGetValue(bindingIndex, out var binding))
|
||||
{
|
||||
return binding.bindingPath;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private bool TryGetActionRecord(string actionName, out (ActionMap map, ActionMap.Action action) result)
|
||||
{
|
||||
return actionLookup.TryGetValue(actionName, out result);
|
||||
}
|
||||
|
||||
private bool TryGetActionRecord(InputAction action, out (ActionMap map, ActionMap.Action action) result)
|
||||
{
|
||||
if (action != null && actionLookupById.TryGetValue(action.id, out result))
|
||||
{
|
||||
return result.action.action == action;
|
||||
}
|
||||
|
||||
result = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// 为键盘选择最佳绑定索引;如果 compositePartName != null 则查找部分
|
||||
/// <summary>
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1 +0,0 @@
|
||||
Subproject commit 90291aa4a969a022e7a02d855748d55af03828b0
|
||||
@ -1 +1 @@
|
||||
Subproject commit b9c79e16a50080ba10b08a9b70bb513b36f51d1e
|
||||
Subproject commit a978c68586cf761c577842532dfa6af5847851a4
|
||||
@ -1 +0,0 @@
|
||||
Subproject commit 0b74d889d80ee30139bd72d390bf2558826b3a96
|
||||
@ -1 +1 @@
|
||||
Subproject commit b50ab115a91632e3501943f58fdae7181325c7ca
|
||||
Subproject commit 7b4feec0f0eb8a7af67063eda3c7a0d8d8bc2b5e
|
||||
@ -25,26 +25,12 @@
|
||||
"source": "embedded",
|
||||
"dependencies": {}
|
||||
},
|
||||
"com.alicizax.unity.entry": {
|
||||
"version": "file:com.alicizax.unity.entry",
|
||||
"depth": 0,
|
||||
"source": "embedded",
|
||||
"dependencies": {}
|
||||
},
|
||||
"com.alicizax.unity.framework": {
|
||||
"version": "file:com.alicizax.unity.framework",
|
||||
"depth": 0,
|
||||
"source": "embedded",
|
||||
"dependencies": {}
|
||||
},
|
||||
"com.alicizax.unity.network": {
|
||||
"version": "file:com.alicizax.unity.network",
|
||||
"depth": 0,
|
||||
"source": "embedded",
|
||||
"dependencies": {
|
||||
"com.unity.nuget.newtonsoft-json": "3.2.1"
|
||||
}
|
||||
},
|
||||
"com.alicizax.unity.packagemanager": {
|
||||
"version": "file:com.alicizax.unity.packagemanager",
|
||||
"depth": 0,
|
||||
@ -73,7 +59,7 @@
|
||||
"depth": 0,
|
||||
"source": "git",
|
||||
"dependencies": {},
|
||||
"hash": "fcef6dfe8ed715cc60a7618a1d2ad62bcace3a80"
|
||||
"hash": "4feac30cb2e105992986c737f7f54992b8300e1a"
|
||||
},
|
||||
"com.code-philosophy.luban": {
|
||||
"version": "http://101.34.252.46:3000/yuliuren/luban_unity.git",
|
||||
|
||||
@ -822,7 +822,7 @@ PlayerSettings:
|
||||
webGLPowerPreference: 2
|
||||
scriptingDefineSymbols:
|
||||
Android: ENABLE_HYBRIDCLR;ENABLE_LOG
|
||||
Standalone: ODIN_INSPECTOR;ODIN_INSPECTOR_3;ODIN_INSPECTOR_3_1;ODIN_VALIDATOR;ODIN_VALIDATOR_3_1;ENABLE_HYBRIDCLR;FANTASY_UNITY;ENABLE_LOG;Event_StrictCheck;ODIN_INSPECTOR_3_2;ODIN_INSPECTOR_3_3;Animora_TMP
|
||||
Standalone: ENABLE_HYBRIDCLR;FANTASY_UNITY;ENABLE_LOG;Event_StrictCheck
|
||||
WebGL: ENABLE_HYBRIDCLR;ENABLE_LOG;UNITY_WEBGL;WEIXINMINIGAME;FANTASY_UNITY;Event_StrickCheck;ODIN_VALIDATOR;ODIN_VALIDATOR_3_1;ODIN_INSPECTOR;ODIN_INSPECTOR_3;ODIN_INSPECTOR_3_1
|
||||
Windows Store Apps: ENABLE_HYBRIDCLR;ENABLE_LOG
|
||||
iPhone: ENABLE_HYBRIDCLR;ENABLE_LOG
|
||||
|
||||
@ -30,13 +30,13 @@ EditorUserSettings:
|
||||
value: 015450045700505d0f0a5f2313260a444e164b2e757b76652c2d4d32bab0313a
|
||||
flags: 0
|
||||
RecentlyUsedSceneGuid-7:
|
||||
value: 5a07065703500c59585e0e7748770d44444f4a737d2d7f35787d4f63e0b26668
|
||||
value: 0606045450065e5d55575a241522064444161c797f7b7234757c4f32e1b0353d
|
||||
flags: 0
|
||||
RecentlyUsedSceneGuid-8:
|
||||
value: 50500404540c580d0f0b5e7543725b44424f4c7a7b7c7734747e4f36e4b1676d
|
||||
value: 5a07065703500c59585e0e7748770d44444f4a737d2d7f35787d4f63e0b26668
|
||||
flags: 0
|
||||
RecentlyUsedSceneGuid-9:
|
||||
value: 0606045450065e5d55575a241522064444161c797f7b7234757c4f32e1b0353d
|
||||
value: 50500404540c580d0f0b5e7543725b44424f4c7a7b7c7734747e4f36e4b1676d
|
||||
flags: 0
|
||||
vcSharedLogLevel:
|
||||
value: 0d5e400f0650
|
||||
|
||||
@ -14,8 +14,8 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_PixelRect:
|
||||
serializedVersion: 2
|
||||
x: -4
|
||||
y: 51
|
||||
x: 0
|
||||
y: 43
|
||||
width: 1920
|
||||
height: 997
|
||||
m_ShowMode: 4
|
||||
@ -23,7 +23,7 @@ MonoBehaviour:
|
||||
m_RootView: {fileID: 4}
|
||||
m_MinSize: {x: 875, y: 300}
|
||||
m_MaxSize: {x: 10000, y: 10000}
|
||||
m_Maximized: 0
|
||||
m_Maximized: 1
|
||||
--- !u!114 &2
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
@ -34,23 +34,23 @@ MonoBehaviour:
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_Name: AnimatorControllerTool
|
||||
m_Name: GameView
|
||||
m_EditorClassIdentifier:
|
||||
m_Children: []
|
||||
m_Position:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 566
|
||||
width: 614
|
||||
width: 308
|
||||
height: 381
|
||||
m_MinSize: {x: 101, y: 121}
|
||||
m_MinSize: {x: 51, y: 71}
|
||||
m_MaxSize: {x: 4001, y: 4021}
|
||||
m_ActualView: {fileID: 15}
|
||||
m_ActualView: {fileID: 14}
|
||||
m_Panes:
|
||||
- {fileID: 14}
|
||||
- {fileID: 15}
|
||||
m_Selected: 1
|
||||
m_LastSelected: 0
|
||||
m_Selected: 0
|
||||
m_LastSelected: 1
|
||||
--- !u!114 &3
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 52
|
||||
@ -70,12 +70,12 @@ MonoBehaviour:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 614
|
||||
width: 308
|
||||
height: 947
|
||||
m_MinSize: {x: 100, y: 100}
|
||||
m_MaxSize: {x: 8096, y: 16192}
|
||||
vertical: 1
|
||||
controlID: 398
|
||||
controlID: 26
|
||||
draggingID: 0
|
||||
--- !u!114 &4
|
||||
MonoBehaviour:
|
||||
@ -193,7 +193,7 @@ MonoBehaviour:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 614
|
||||
width: 308
|
||||
height: 566
|
||||
m_MinSize: {x: 201, y: 221}
|
||||
m_MaxSize: {x: 4001, y: 4021}
|
||||
@ -219,9 +219,9 @@ MonoBehaviour:
|
||||
- {fileID: 11}
|
||||
m_Position:
|
||||
serializedVersion: 2
|
||||
x: 614
|
||||
x: 308
|
||||
y: 0
|
||||
width: 363
|
||||
width: 387
|
||||
height: 947
|
||||
m_MinSize: {x: 100, y: 100}
|
||||
m_MaxSize: {x: 8096, y: 16192}
|
||||
@ -245,7 +245,7 @@ MonoBehaviour:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 363
|
||||
width: 387
|
||||
height: 409
|
||||
m_MinSize: {x: 202, y: 221}
|
||||
m_MaxSize: {x: 4002, y: 4021}
|
||||
@ -271,7 +271,7 @@ MonoBehaviour:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 409
|
||||
width: 363
|
||||
width: 387
|
||||
height: 538
|
||||
m_MinSize: {x: 102, y: 121}
|
||||
m_MaxSize: {x: 4002, y: 4021}
|
||||
@ -295,9 +295,9 @@ MonoBehaviour:
|
||||
m_Children: []
|
||||
m_Position:
|
||||
serializedVersion: 2
|
||||
x: 977
|
||||
x: 695
|
||||
y: 0
|
||||
width: 369
|
||||
width: 607
|
||||
height: 947
|
||||
m_MinSize: {x: 232, y: 271}
|
||||
m_MaxSize: {x: 10002, y: 10021}
|
||||
@ -321,9 +321,9 @@ MonoBehaviour:
|
||||
m_Children: []
|
||||
m_Position:
|
||||
serializedVersion: 2
|
||||
x: 1346
|
||||
x: 1302
|
||||
y: 0
|
||||
width: 574
|
||||
width: 618
|
||||
height: 947
|
||||
m_MinSize: {x: 276, y: 71}
|
||||
m_MaxSize: {x: 4001, y: 4021}
|
||||
@ -354,7 +354,7 @@ MonoBehaviour:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 639
|
||||
width: 496
|
||||
width: 307
|
||||
height: 360
|
||||
m_SerializedDataModeController:
|
||||
m_DataMode: 0
|
||||
@ -372,7 +372,7 @@ MonoBehaviour:
|
||||
m_ShowGizmos: 0
|
||||
m_TargetDisplay: 0
|
||||
m_ClearColor: {r: 0, g: 0, b: 0, a: 0}
|
||||
m_TargetSize: {x: 2560, y: 1440}
|
||||
m_TargetSize: {x: 1920, y: 1080}
|
||||
m_TextureFilterMode: 0
|
||||
m_TextureHideFlags: 61
|
||||
m_RenderIMGUI: 1
|
||||
@ -381,16 +381,16 @@ MonoBehaviour:
|
||||
m_VSyncEnabled: 0
|
||||
m_Gizmos: 0
|
||||
m_Stats: 1
|
||||
m_SelectedSizes: 05000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
m_SelectedSizes: 03000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
m_ZoomArea:
|
||||
m_HRangeLocked: 0
|
||||
m_VRangeLocked: 0
|
||||
hZoomLockedByDefault: 0
|
||||
vZoomLockedByDefault: 0
|
||||
m_HBaseRangeMin: -1280
|
||||
m_HBaseRangeMax: 1280
|
||||
m_VBaseRangeMin: -720
|
||||
m_VBaseRangeMax: 720
|
||||
m_HBaseRangeMin: -960
|
||||
m_HBaseRangeMax: 960
|
||||
m_VBaseRangeMin: -540
|
||||
m_VBaseRangeMax: 540
|
||||
m_HAllowExceedBaseRangeMin: 1
|
||||
m_HAllowExceedBaseRangeMax: 1
|
||||
m_VAllowExceedBaseRangeMin: 1
|
||||
@ -408,23 +408,23 @@ MonoBehaviour:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 21
|
||||
width: 496
|
||||
width: 307
|
||||
height: 339
|
||||
m_Scale: {x: 0.19375, y: 0.19375}
|
||||
m_Translation: {x: 248, y: 169.5}
|
||||
m_Scale: {x: 0.15989584, y: 0.15989585}
|
||||
m_Translation: {x: 153.5, y: 169.5}
|
||||
m_MarginLeft: 0
|
||||
m_MarginRight: 0
|
||||
m_MarginTop: 0
|
||||
m_MarginBottom: 0
|
||||
m_LastShownAreaInsideMargins:
|
||||
serializedVersion: 2
|
||||
x: -1280
|
||||
y: -874.83875
|
||||
width: 2560
|
||||
height: 1749.6775
|
||||
x: -960
|
||||
y: -1060.0651
|
||||
width: 1920
|
||||
height: 2120.1301
|
||||
m_MinimalGUI: 1
|
||||
m_defaultScale: 0.19375
|
||||
m_LastWindowPixelSize: {x: 496, y: 360}
|
||||
m_defaultScale: 0.15989584
|
||||
m_LastWindowPixelSize: {x: 307, y: 360}
|
||||
m_ClearInEditMode: 1
|
||||
m_NoCameraWarning: 1
|
||||
m_LowResolutionForAspectRatios: 01000000000000000000
|
||||
@ -450,9 +450,9 @@ MonoBehaviour:
|
||||
m_Tooltip:
|
||||
m_Pos:
|
||||
serializedVersion: 2
|
||||
x: -4
|
||||
y: 647
|
||||
width: 613
|
||||
x: 0
|
||||
y: 639
|
||||
width: 491
|
||||
height: 360
|
||||
m_SerializedDataModeController:
|
||||
m_DataMode: 0
|
||||
@ -520,9 +520,9 @@ MonoBehaviour:
|
||||
m_Tooltip:
|
||||
m_Pos:
|
||||
serializedVersion: 2
|
||||
x: -4
|
||||
y: 81
|
||||
width: 613
|
||||
x: 0
|
||||
y: 73
|
||||
width: 307
|
||||
height: 545
|
||||
m_SerializedDataModeController:
|
||||
m_DataMode: 0
|
||||
@ -1064,9 +1064,9 @@ MonoBehaviour:
|
||||
m_PlayAudio: 0
|
||||
m_AudioPlay: 0
|
||||
m_Position:
|
||||
m_Target: {x: 23.557358, y: 5.6186223, z: -2.729362}
|
||||
m_Target: {x: 1000, y: 1000, z: 100}
|
||||
speed: 2
|
||||
m_Value: {x: 23.557358, y: 5.6186223, z: -2.729362}
|
||||
m_Value: {x: 1000, y: 1000, z: 100}
|
||||
m_RenderMode: 0
|
||||
m_CameraMode:
|
||||
drawMode: 0
|
||||
@ -1077,7 +1077,7 @@ MonoBehaviour:
|
||||
m_SceneViewState:
|
||||
m_AlwaysRefresh: 0
|
||||
showFog: 1
|
||||
showSkybox: 1
|
||||
showSkybox: 0
|
||||
showFlares: 1
|
||||
showImageEffects: 1
|
||||
showParticleSystems: 1
|
||||
@ -1114,11 +1114,11 @@ MonoBehaviour:
|
||||
m_Rotation:
|
||||
m_Target: {x: -0.21037178, y: -0.10913931, z: 0.02363893, w: -0.97122556}
|
||||
speed: 2
|
||||
m_Value: {x: -0.21037178, y: -0.10913931, z: 0.023638932, w: -0.9712256}
|
||||
m_Value: {x: -0.2103712, y: -0.10913901, z: 0.023638865, w: -0.9712229}
|
||||
m_Size:
|
||||
m_Target: 1.0281526
|
||||
m_Target: 0.7536363
|
||||
speed: 2
|
||||
m_Value: 1.0281526
|
||||
m_Value: 0.7536363
|
||||
m_Ortho:
|
||||
m_Target: 0
|
||||
speed: 2
|
||||
@ -1136,7 +1136,7 @@ MonoBehaviour:
|
||||
m_FarClip: 10000
|
||||
m_DynamicClip: 1
|
||||
m_OcclusionCulling: 0
|
||||
m_LastSceneViewRotation: {x: -0.08717229, y: 0.89959055, z: -0.21045254, w: -0.3726226}
|
||||
m_LastSceneViewRotation: {x: -0.21037178, y: -0.10913931, z: 0.02363893, w: -0.97122556}
|
||||
m_LastSceneViewOrtho: 0
|
||||
m_ReplacementShader: {fileID: 0}
|
||||
m_ReplacementString:
|
||||
@ -1163,9 +1163,9 @@ MonoBehaviour:
|
||||
m_Tooltip:
|
||||
m_Pos:
|
||||
serializedVersion: 2
|
||||
x: 610
|
||||
y: 81
|
||||
width: 361
|
||||
x: 308
|
||||
y: 73
|
||||
width: 385
|
||||
height: 388
|
||||
m_SerializedDataModeController:
|
||||
m_DataMode: 0
|
||||
@ -1180,9 +1180,9 @@ MonoBehaviour:
|
||||
m_SceneHierarchy:
|
||||
m_TreeViewState:
|
||||
scrollPos: {x: 0, y: 0}
|
||||
m_SelectedIDs: d6700000
|
||||
m_SelectedIDs: 02200000
|
||||
m_LastClickedID: 0
|
||||
m_ExpandedIDs: 28fbffff
|
||||
m_ExpandedIDs: aebbfffff2d0fffffad0fffffcd0ffff26fbffff28fbffff
|
||||
m_RenameOverlay:
|
||||
m_UserAcceptedRename: 0
|
||||
m_Name:
|
||||
@ -1198,7 +1198,7 @@ MonoBehaviour:
|
||||
m_IsRenaming: 0
|
||||
m_OriginalEventType: 11
|
||||
m_IsRenamingFilename: 0
|
||||
m_ClientGUIView: {fileID: 10}
|
||||
m_ClientGUIView: {fileID: 8}
|
||||
m_SearchString:
|
||||
m_ExpandedScenes: []
|
||||
m_CurrenRootInstanceID: 0
|
||||
@ -1226,9 +1226,9 @@ MonoBehaviour:
|
||||
m_Tooltip:
|
||||
m_Pos:
|
||||
serializedVersion: 2
|
||||
x: 610
|
||||
y: 490
|
||||
width: 361
|
||||
x: 308
|
||||
y: 482
|
||||
width: 385
|
||||
height: 517
|
||||
m_SerializedDataModeController:
|
||||
m_DataMode: 0
|
||||
@ -1260,9 +1260,9 @@ MonoBehaviour:
|
||||
m_Tooltip:
|
||||
m_Pos:
|
||||
serializedVersion: 2
|
||||
x: 973
|
||||
y: 81
|
||||
width: 367
|
||||
x: 695
|
||||
y: 73
|
||||
width: 605
|
||||
height: 926
|
||||
m_SerializedDataModeController:
|
||||
m_DataMode: 0
|
||||
@ -1285,7 +1285,7 @@ MonoBehaviour:
|
||||
m_SkipHidden: 0
|
||||
m_SearchArea: 2
|
||||
m_Folders:
|
||||
- Assets/Plugins/UnityEditorDarkMode
|
||||
- Assets/Scripts/Hotfix/GameLogic
|
||||
m_Globs: []
|
||||
m_OriginalText:
|
||||
m_ImportLogFlags: 0
|
||||
@ -1301,7 +1301,7 @@ MonoBehaviour:
|
||||
scrollPos: {x: 0, y: 0}
|
||||
m_SelectedIDs: e48c0000
|
||||
m_LastClickedID: 36068
|
||||
m_ExpandedIDs: 000000007e0200008a0d0000786d00007a6d00007c6d00007e6d0000806d0000826d0000846d0000866d0000886d00008a6d00008c6d00008e6d0000906d0000926d0000946d0000966d0000986d00009a6d00009c6d00009e6d0000a06d0000a26d0000a46d0000a66d0000a86d0000aa6d0000ac6d0000ae6d0000b06d0000b26d0000b46d0000b66d0000b86d0000ba6d0000bc6d0000be6d0000c06d0000c26d0000c46d0000c66d0000c86d0000ca6d0000cc6d0000ce6d0000d06d0000d26d0000d46d0000d66d0000d86d0000da6d0000dc6d0000de6d0000e06d0000e26d0000e46d0000e66d0000e86d0000ea6d0000ec6d0000ee6d0000f06d0000f26d0000f46d0000
|
||||
m_ExpandedIDs: 000000007e0200008c0d0000246c00008a6d00008c6d00008e6d0000906d0000926d0000946d0000966d0000986d00009a6d00009c6d00009e6d0000a06d0000a26d0000a46d0000a66d0000a86d0000aa6d0000ac6d0000ae6d0000b06d0000b26d0000b46d0000b66d0000b86d0000ba6d0000bc6d0000be6d0000c06d0000c26d0000c46d0000c66d0000c86d0000ca6d0000cc6d0000ce6d0000d06d0000d26d0000d46d0000d66d0000d86d0000da6d0000dc6d0000de6d0000e06d0000e26d0000e46d0000e66d0000e86d0000ea6d0000ec6d0000ee6d0000f06d0000f26d0000f46d0000f66d0000f86d0000fa6d0000fc6d0000fe6d0000006e0000
|
||||
m_RenameOverlay:
|
||||
m_UserAcceptedRename: 0
|
||||
m_Name:
|
||||
@ -1329,7 +1329,7 @@ MonoBehaviour:
|
||||
scrollPos: {x: 0, y: 0}
|
||||
m_SelectedIDs:
|
||||
m_LastClickedID: 0
|
||||
m_ExpandedIDs: ffffffff000000007e020000786d00007a6d00007c6d00007e6d0000806d0000826d0000846d0000866d0000886d00008a6d00008c6d00008e6d0000906d0000926d0000946d0000966d0000986d00009a6d00009c6d00009e6d0000a06d0000a26d0000a46d0000a66d0000a86d0000aa6d0000ac6d0000ae6d0000b06d0000b46d0000b66d0000b86d0000ba6d0000bc6d0000be6d0000c06d0000c26d0000c46d0000c66d0000c86d0000ca6d0000cc6d0000ce6d0000d06d0000d46d0000d66d0000d86d0000da6d0000dc6d0000de6d0000e06d0000e26d0000e66d0000e86d0000ea6d0000ec6d0000ee6d0000f06d0000f26d0000f46d0000f06f000008700000cc700000
|
||||
m_ExpandedIDs: ffffffff000000007e0200008c0d00008a6d00008c6d00008e6d0000906d0000926d0000966d0000986d00009a6d00009c6d00009e6d0000a06d0000a26d0000a46d0000a66d0000a86d0000aa6d0000ac6d0000ae6d0000b06d0000b26d0000b46d0000b66d0000ba6d0000bc6d0000be6d0000c06d0000c26d0000c46d0000c66d0000c86d0000ca6d0000cc6d0000ce6d0000d06d0000d26d0000d46d0000d66d0000d86d0000da6d0000e46d0000e66d0000e86d0000ea6d0000ec6d0000ee6d0000f06d0000f26d0000f66d0000f86d0000fc6d0000fe6d0000006e0000be6f0000c06f0000187000001a7000001c7000006a700000207100003c7100007a7100007c7100007e71000080710000b2710000c472000060730000267400004a750000dc75000032770000
|
||||
m_RenameOverlay:
|
||||
m_UserAcceptedRename: 0
|
||||
m_Name:
|
||||
@ -1405,9 +1405,9 @@ MonoBehaviour:
|
||||
m_Tooltip:
|
||||
m_Pos:
|
||||
serializedVersion: 2
|
||||
x: 1342
|
||||
y: 81
|
||||
width: 573
|
||||
x: 1302
|
||||
y: 73
|
||||
width: 617
|
||||
height: 926
|
||||
m_SerializedDataModeController:
|
||||
m_DataMode: 0
|
||||
|
||||
Loading…
Reference in New Issue
Block a user