输入设备管理器,以及按键映射设置基本框架搭建

This commit is contained in:
ALIENJACK\alien 2025-03-12 20:09:11 +08:00
parent 374d496d67
commit 3c10873180
20 changed files with 658 additions and 477 deletions

View File

@ -1,4 +1,5 @@
using AxibugEmuOnline.Client.Manager;
using AxibugEmuOnline.Client.InputDevices;
using AxibugEmuOnline.Client.Manager;
using AxibugEmuOnline.Client.Network;
using AxibugProtobuf;
using System;
@ -23,13 +24,13 @@ namespace AxibugEmuOnline.Client.ClientCore
public static AppChat chat;
public static UserDataManager user;
public static AppInput input;
public static InputDevicesManager inputDevicesMgr;
public static AppEmu emu;
public static HttpAPI httpAPI;
public static CacheManager CacheMgr;
public static AppRoom roomMgr;
public static AppSettings settings;
public static AppShare share;
public static GamePadManager gamePadMgr;
public static SaveSlotManager SavMgr;
public static FileDownloader FileDownloader;
static bool bTest;
@ -70,15 +71,15 @@ namespace AxibugEmuOnline.Client.ClientCore
return s_romLibs[platform];
}
public static void Init(bool isTest = false,bool isUseGUIButton = false, string testSrvIP = "", bool bUseLocalWebApi = false, string mLocalWebApi = "")
public static void Init(bool isTest = false, bool isUseGUIButton = false, string testSrvIP = "", bool bUseLocalWebApi = false, string mLocalWebApi = "")
{
log = new LogManager(OnLogOut);
//其他平台必要的初始化
if (UnityEngine.Application.platform == RuntimePlatform.PSP2)
{
PSP2Init();
}
if (UnityEngine.Application.platform == RuntimePlatform.PSP2) PSP2Init();
input = new AppInput();
inputDevicesMgr = new InputDevicesManager();
FileDownloader = new FileDownloader();
settings = new AppSettings();
network = new NetworkHelper();
@ -102,7 +103,6 @@ namespace AxibugEmuOnline.Client.ClientCore
roomMgr = new AppRoom();
share = new AppShare();
SavMgr = new SaveSlotManager();
gamePadMgr = new GamePadManager();
bTest = isTest;
@ -233,7 +233,6 @@ namespace AxibugEmuOnline.Client.ClientCore
starRomLib.ExecuteFetchRomInfo();
FileDownloader.Update();
gamePadMgr.Update();
}
public static Coroutine StartCoroutine(IEnumerator itor)

View File

@ -2,6 +2,7 @@
using AxibugEmuOnline.Client.Common;
using AxibugEmuOnline.Client.Event;
using NUnit.Framework.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
@ -98,16 +99,7 @@ namespace AxibugEmuOnline.Client
case 3: targetController = Controller3; break;
default:
throw new System.Exception($"Not Allowed conIndex Range: {conIndex}");
break;
}
//var targetController = conIndex switch
//{
// 0 => Controller0,
// 1 => Controller1,
// 2 => Controller2,
// 3 => Controller3,
// _ => throw new System.Exception($"Not Allowed conIndex Range: {conIndex}")
//};
if (targetController.ConnectSlot.HasValue) return;
@ -121,6 +113,7 @@ namespace AxibugEmuOnline.Client
/// </summary>
public class Controller : IController
{
static Lazy<NesKeyBinding> s_keyBinder = new Lazy<NesKeyBinding>(() => App.settings.KeyMapper.GetBinder<NesKeyBinding>());
/// <summary>
/// 控制器编号
/// <para><c>此编号并非对应游戏中的player1,player2,player3,player4,仅仅作为本地4个手柄的实例</c></para>
@ -135,260 +128,32 @@ namespace AxibugEmuOnline.Client
/// </summary>
public uint? ConnectSlot { get; set; }
//public Button UP { get; }
//public Button DOWN { get; }
//public Button LEFT { get; }
//public Button RIGHT { get; }
//public Button A { get; }
//public Button B { get; }
//public Button SELECT { get; }
//public Button START { get; }
//public Button MIC { get; }
public Controller(int controllerIndex)
{
ControllerIndex = controllerIndex;
//UP = new Button(this, EnumButtonType.UP);
//DOWN = new Button(this, EnumButtonType.DOWN);
//LEFT = new Button(this, EnumButtonType.LEFT);
//RIGHT = new Button(this, EnumButtonType.RIGHT);
//A = new Button(this, EnumButtonType.A);
//B = new Button(this, EnumButtonType.B);
//SELECT = new Button(this, EnumButtonType.SELECT);
//START = new Button(this, EnumButtonType.START);
//MIC = new Button(this, EnumButtonType.MIC);
}
public EnumButtonType GetButtons()
{
EnumButtonType res = 0;
if(App.input.nes.controllers[ControllerIndex].GetKey((ulong)EnumButtonType.UP)) res |= EnumButtonType.UP;
if(App.input.nes.controllers[ControllerIndex].GetKey((ulong)EnumButtonType.DOWN)) res |= EnumButtonType.DOWN;
if(App.input.nes.controllers[ControllerIndex].GetKey((ulong)EnumButtonType.LEFT)) res |= EnumButtonType.LEFT;
if(App.input.nes.controllers[ControllerIndex].GetKey((ulong)EnumButtonType.RIGHT)) res |= EnumButtonType.RIGHT;
if(App.input.nes.controllers[ControllerIndex].GetKey((ulong)EnumButtonType.A)) res |= EnumButtonType.A;
if(App.input.nes.controllers[ControllerIndex].GetKey((ulong)EnumButtonType.B)) res |= EnumButtonType.B;
if(App.input.nes.controllers[ControllerIndex].GetKey((ulong)EnumButtonType.SELECT)) res |= EnumButtonType.SELECT;
if(App.input.nes.controllers[ControllerIndex].GetKey((ulong)EnumButtonType.START)) res |= EnumButtonType.START;
if(App.input.nes.controllers[ControllerIndex].GetKey((ulong)EnumButtonType.MIC)) res |= EnumButtonType.MIC;
//res |= UP.SampleKey();
//res |= DOWN.SampleKey();
//res |= LEFT.SampleKey();
//res |= RIGHT.SampleKey();
//res |= A.SampleKey();
//res |= B.SampleKey();
//res |= SELECT.SampleKey();
//res |= START.SampleKey();
//res |= MIC.SampleKey();
if (s_keyBinder.Value.GetKey(EnumButtonType.UP, ControllerIndex)) res |= EnumButtonType.UP;
if (s_keyBinder.Value.GetKey(EnumButtonType.DOWN, ControllerIndex)) res |= EnumButtonType.DOWN;
if (s_keyBinder.Value.GetKey(EnumButtonType.LEFT, ControllerIndex)) res |= EnumButtonType.LEFT;
if (s_keyBinder.Value.GetKey(EnumButtonType.RIGHT, ControllerIndex)) res |= EnumButtonType.RIGHT;
if (s_keyBinder.Value.GetKey(EnumButtonType.A, ControllerIndex)) res |= EnumButtonType.A;
if (s_keyBinder.Value.GetKey(EnumButtonType.B, ControllerIndex)) res |= EnumButtonType.B;
if (s_keyBinder.Value.GetKey(EnumButtonType.SELECT, ControllerIndex)) res |= EnumButtonType.SELECT;
if (s_keyBinder.Value.GetKey(EnumButtonType.START, ControllerIndex)) res |= EnumButtonType.START;
if (s_keyBinder.Value.GetKey(EnumButtonType.MIC, ControllerIndex)) res |= EnumButtonType.MIC;
return res;
}
public bool AnyButtonDown()
{
return App.input.nes.controllers[ControllerIndex].HadAnyKeyDown();
//return
// UP.IsDown ||
// DOWN.IsDown ||
// LEFT.IsDown ||
// RIGHT.IsDown ||
// A.IsDown ||
// B.IsDown ||
// SELECT.IsDown ||
// START.IsDown ||
// MIC.IsDown;
return s_keyBinder.Value.AnyKeyDown(ControllerIndex);
}
//public static KeyListener GetKey(int controllerInput, EnumButtonType nesConBtnType)
//{
// string configKey = $"NES_{controllerInput}_{nesConBtnType}";
// //PSV平台固定键值
// if (UnityEngine.Application.platform == RuntimePlatform.PSP2)
// {
// return KeyListener.GetPSVitaKey(controllerInput, nesConBtnType);
// }
// if (PlayerPrefs.HasKey(configKey))
// {
// return new KeyListener(PlayerPrefs.GetString(configKey));
// }
// else
// {
// var defaultKeyCode = KeyListener.GetDefaultKey(controllerInput, nesConBtnType);
// PlayerPrefs.SetString(configKey, defaultKeyCode.ToString());
// return defaultKeyCode;
// }
//}
}
///// <summary>
///// NES控制器按键类
///// </summary>
//public class Button
//{
// /// <summary> 所属控制器 </summary>
// readonly Controller m_hostController;
// /// <summary> 按键 </summary>
// readonly EnumButtonType m_buttonType;
// /// <summary> 按键监听器 </summary>
// KeyListener m_keyListener;
// /// <summary> 指示按钮是否正在按下状态 </summary>
// public bool IsPressing => m_keyListener.IsPressing();
// /// <summary> 指示按钮是否被按下 </summary>
// public bool IsDown => m_keyListener.IsDown();
// public Button(Controller controller, EnumButtonType buttonType)
// {
// m_hostController = controller;
// m_buttonType = buttonType;
// CreateListener();
// }
// /// <summary>
// /// 采集按钮按下状态
// /// </summary>
// /// <returns></returns>
// public EnumButtonType SampleKey()
// {
// return IsPressing ? m_buttonType : 0;
// }
// private void CreateListener()
// {
// m_keyListener = Controller.GetKey(m_hostController.ControllerIndex, m_buttonType);
// }
//}
//low C# readonly
//public readonly struct KeyListener
//public struct KeyListener
//{
// private readonly KeyCode m_key;
// public KeyListener(KeyCode key)
// {
// m_key = key;
// }
// /// <summary> 从配置字符串构建 </summary>
// public KeyListener(string confStr)
// {
// m_key = KeyCode.None;
// int result;
// if (int.TryParse(confStr, out result))
// m_key = (KeyCode)result;
// }
// public bool IsPressing()
// {
// return Input.GetKey(m_key);
// }
// public bool IsDown()
// {
// return Input.GetKeyDown(m_key);
// }
// public override string ToString()
// {
// return ((int)(m_key)).ToString();
// }
// public static KeyListener GetDefaultKey(int controllerIndex, EnumButtonType nesConBtnType)
// {
// switch (controllerIndex)
// {
// case 0:
// switch (nesConBtnType)
// {
// case EnumButtonType.LEFT:
// return new KeyListener(KeyCode.A);
// case EnumButtonType.RIGHT:
// return new KeyListener(KeyCode.D);
// case EnumButtonType.UP:
// return new KeyListener(KeyCode.W);
// case EnumButtonType.DOWN:
// return new KeyListener(KeyCode.S);
// case EnumButtonType.START:
// return new KeyListener(KeyCode.B);
// case EnumButtonType.SELECT:
// return new KeyListener(KeyCode.V);
// case EnumButtonType.A:
// return new KeyListener(KeyCode.K);
// case EnumButtonType.B:
// return new KeyListener(KeyCode.J);
// case EnumButtonType.MIC:
// return new KeyListener(KeyCode.M);
// }
// break;
// case 1:
// switch (nesConBtnType)
// {
// case EnumButtonType.LEFT:
// return new KeyListener(KeyCode.Delete);
// case EnumButtonType.RIGHT:
// return new KeyListener(KeyCode.PageDown);
// case EnumButtonType.UP:
// return new KeyListener(KeyCode.Home);
// case EnumButtonType.DOWN:
// return new KeyListener(KeyCode.End);
// case EnumButtonType.START:
// return new KeyListener(KeyCode.PageUp);
// case EnumButtonType.SELECT:
// return new KeyListener(KeyCode.Insert);
// case EnumButtonType.A:
// return new KeyListener(KeyCode.Keypad5);
// case EnumButtonType.B:
// return new KeyListener(KeyCode.Keypad4);
// case EnumButtonType.MIC:
// return new KeyListener(KeyCode.KeypadPeriod);
// }
// break;
// }
// return default(KeyListener);
// }
// //public static KeyListener GetPSVitaKey(int controllerIndex, EnumButtonType nesConBtnType)
// //{
// // switch (controllerIndex)
// // {
// // case 0:
// // switch (nesConBtnType)
// // {
// // case EnumButtonType.LEFT:
// // return new KeyListener(PSVitaKey.Left);
// // case EnumButtonType.RIGHT:
// // return new KeyListener(PSVitaKey.Right);
// // case EnumButtonType.UP:
// // return new KeyListener(PSVitaKey.Up);
// // case EnumButtonType.DOWN:
// // return new KeyListener(PSVitaKey.Down);
// // case EnumButtonType.START:
// // return new KeyListener(PSVitaKey.Start);
// // case EnumButtonType.SELECT:
// // return new KeyListener(PSVitaKey.Select);
// // case EnumButtonType.A:
// // return new KeyListener(PSVitaKey.Circle);
// // case EnumButtonType.B:
// // return new KeyListener(PSVitaKey.Cross);
// // case EnumButtonType.MIC:
// // return new KeyListener(PSVitaKey.Block);
// // }
// // break;
// // }
// // return default(KeyListener);
// //}
//}
}
}

View File

@ -7,13 +7,16 @@
/// <summary> 滤镜设置 </summary>
public FilterManager Filter { get; private set; }
/// <summary> 画面比例设置 </summary>
public ScreenScaler ScreenScaler { get; private set; }
public ScreenScaler ScreenScaler { get; private set; }
/// <summary> 键位设置 </summary>
public KeyMapperSetting KeyMapper { get; private set; }
public AppSettings()
{
BgColor = new BgColorSettings();
Filter = new FilterManager();
ScreenScaler = new ScreenScaler();
KeyMapper = new KeyMapperSetting();
}
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 5fe26f58ab822c44888b86305c5326e0
guid: 7c4a24e114240814a8587e2f90a2f6f0
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@ -0,0 +1,210 @@
using AxibugEmuOnline.Client.InputDevices;
using AxibugProtobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace AxibugEmuOnline.Client
{
/// <summary>
/// 管理键位映射设置
/// </summary>
public class KeyMapperSetting
{
Dictionary<RomPlatformType, EmuCoreControllerKeyBinding> m_binders = new Dictionary<RomPlatformType, EmuCoreControllerKeyBinding>();
Dictionary<Type, EmuCoreControllerKeyBinding> m_bindersByType = new Dictionary<Type, EmuCoreControllerKeyBinding>();
public KeyMapperSetting()
{
var baseType = typeof(EmuCoreControllerKeyBinding);
foreach (var t in baseType.Assembly.ExportedTypes)
{
if (t.IsAbstract) continue;
if (!baseType.IsAssignableFrom(t)) continue;
var binderIns = Activator.CreateInstance(t) as EmuCoreControllerKeyBinding;
m_binders.Add(binderIns.Platform, binderIns);
m_bindersByType.Add(binderIns.GetType(), binderIns);
}
}
public T GetBinder<T>() where T : EmuCoreControllerKeyBinding
{
m_bindersByType.TryGetValue(typeof(T), out var binder);
return binder as T;
}
}
/// <summary>
/// 此类为内部继承, 请勿继承此类
/// </summary>
public abstract class EmuCoreControllerKeyBinding
{
/// <summary> 所属核心 </summary>
public abstract RomPlatformType Platform { get; }
/// <summary> 控制器数量 </summary>
public abstract int ControllerCount { get; }
}
/// <summary>
/// 模拟器核心控制器键位绑定器
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class EmuCoreControllerKeyBinding<T> : EmuCoreControllerKeyBinding
where T : Enum
{
List<BindingPage> m_bindingPages = new List<BindingPage>();
public EmuCoreControllerKeyBinding()
{
for (int i = 0; i < ControllerCount; i++)
{
m_bindingPages.Add(new BindingPage(i, this));
}
LoadDefaultMapper();
}
IEnumerable<T> DefineKeys()
{
return Enum.GetValues(typeof(T)).Cast<T>();
}
/// <summary>
/// 加载默认映射
/// </summary>
public void LoadDefaultMapper()
{
foreach (var binding in m_bindingPages)
{
binding.ClearBinding();
OnLoadDefaultMapper(binding);
}
}
protected abstract void OnLoadDefaultMapper(BindingPage binding);
/// <summary>
/// 获取指定按键是否处于按下状态
/// </summary>
/// <param name="emuBtn"></param>
/// <param name="controllerIndex"></param>
/// <returns></returns>
public bool GetKey(T emuBtn, int controllerIndex)
{
var binding = m_bindingPages[controllerIndex];
foreach (var key in binding.GetBinding(emuBtn))
{
if (key.IsPressing()) return true;
}
return false;
}
/// <summary>
/// 获取调用帧是否有任意按键触发了按下操作
/// </summary>
/// <param name="controllerIndex"></param>
/// <returns></returns>
public bool AnyKeyDown(int controllerIndex)
{
var binding = m_bindingPages[controllerIndex];
return binding.AnyKeyDown();
}
/// <summary>
/// 获取指定按键的值
/// </summary>
/// <param name="emuBtn">模拟器平台的具体键枚举</param>
/// <param name="controllerIndex">模拟器平台的控制器序号</param>
/// <returns></returns>
public Vector2 GetVector2(T emuBtn, int controllerIndex)
{
var binding = m_bindingPages[controllerIndex];
foreach (var key in binding.GetBinding(emuBtn))
{
if (!key.IsPressing()) continue;
return key.GetVector2();
}
return default(Vector2);
}
/// <summary>
/// 获取指定按键的值
/// </summary>
/// <param name="emuBtn">模拟器平台的具体键枚举</param>
/// <param name="controllerIndex">模拟器平台的控制器序号</param>
/// <returns></returns>
public float GetFloat(T emuBtn, int controllerIndex)
{
var binding = m_bindingPages[controllerIndex];
foreach (var key in binding.GetBinding(emuBtn))
{
if (!key.IsPressing()) continue;
return key.GetFlaot();
}
return default(float);
}
public class BindingPage
{
Dictionary<T, List<InputDevice.KeyBase>> m_mapSetting = new Dictionary<T, List<InputDevice.KeyBase>>();
public int ControllerIndex { get; }
public EmuCoreControllerKeyBinding<T> Host { get; }
internal BindingPage(int controllerIndex, EmuCoreControllerKeyBinding<T> host)
{
ControllerIndex = controllerIndex;
Host = host;
foreach (var emuBtn in host.DefineKeys())
m_mapSetting[emuBtn] = new List<InputDevice.KeyBase>();
}
public void ClearBinding()
{
foreach (var list in m_mapSetting.Values) list.Clear();
}
public void SetBinding(T emuBtn, InputDevice.KeyBase key, int settingSlot)
{
var settingList = m_mapSetting[emuBtn];
int needFixCount = settingSlot - settingList.Count + 1;
if (needFixCount > 0) for (int i = 0; i < needFixCount; i++) settingList.Add(null);
settingList[settingSlot] = key;
}
public InputDevice.KeyBase GetBinding(T emuBtn, int settingSlot)
{
var settingList = m_mapSetting[emuBtn];
if (settingSlot >= settingList.Count) return null;
return settingList[settingSlot];
}
public List<InputDevice.KeyBase> GetBinding(T emuBtn)
{
return m_mapSetting[emuBtn];
}
public bool AnyKeyDown()
{
foreach (var item in m_mapSetting)
{
foreach (var key in item.Value)
{
if (key.GetButtonDown()) return true;
}
}
return false;
}
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 59504da02f065ec4e8e6905ab357badc

View File

@ -0,0 +1,41 @@
using AxibugEmuOnline.Client.ClientCore;
using AxibugProtobuf;
using VirtualNes.Core;
namespace AxibugEmuOnline.Client
{
public class NesKeyBinding : EmuCoreControllerKeyBinding<EnumButtonType>
{
public override RomPlatformType Platform => RomPlatformType.Nes;
public override int ControllerCount => 4;
protected override void OnLoadDefaultMapper(BindingPage binding)
{
var keyboard = App.inputDevicesMgr.GetKeyboard();
switch (binding.ControllerIndex)
{
case 0:
binding.SetBinding(EnumButtonType.LEFT, keyboard.A, 0);
binding.SetBinding(EnumButtonType.RIGHT, keyboard.D, 0);
binding.SetBinding(EnumButtonType.UP, keyboard.W, 0);
binding.SetBinding(EnumButtonType.DOWN, keyboard.S, 0);
binding.SetBinding(EnumButtonType.A, keyboard.K, 0);
binding.SetBinding(EnumButtonType.B, keyboard.J, 0);
binding.SetBinding(EnumButtonType.SELECT, keyboard.V, 0);
binding.SetBinding(EnumButtonType.START, keyboard.B, 0);
binding.SetBinding(EnumButtonType.MIC, keyboard.M, 0);
break;
case 1:
binding.SetBinding(EnumButtonType.UP, keyboard.UpArrow, 0);
binding.SetBinding(EnumButtonType.DOWN, keyboard.DownArrow, 0);
binding.SetBinding(EnumButtonType.LEFT, keyboard.LeftArrow, 0);
binding.SetBinding(EnumButtonType.RIGHT, keyboard.RightArrow, 0);
binding.SetBinding(EnumButtonType.A, keyboard.Keypad2, 0);
binding.SetBinding(EnumButtonType.B, keyboard.Keypad1, 0);
binding.SetBinding(EnumButtonType.SELECT, keyboard.Keypad0, 0);
binding.SetBinding(EnumButtonType.START, keyboard.KeypadPeriod, 0);
break;
}
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 65743da1d10d08d4d8a6485eb7fd7188

View File

@ -1,26 +0,0 @@
namespace AxibugEmuOnline.Client.Manager
{
public partial class GamePadManager
{
/// <summary>
/// 被Unity所识别的通用GamePad类
/// </summary>
public class GamePad
{
internal GamePadInfo m_info;
public int Index => m_info.Index;
public string Name => m_info.Name;
public bool Offline { get; internal set; }
internal GamePad(GamePadInfo info)
{
m_info = info;
}
public override string ToString()
{
return $"{Index}:{Name}{(Offline ? "(Offline)" : string.Empty)}";
}
}
}
}

View File

@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: c2c0a06020f65a747af5490a6112361b

View File

@ -1,121 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace AxibugEmuOnline.Client.Manager
{
public partial class GamePadManager
{
#region Events
public delegate void GamePadConnectedHandle(GamePad newConnectGamePad);
/// <summary> 当一个手柄连接时触发 </summary>
public event GamePadConnectedHandle OnGamePadConnected;
public delegate void GamePadDisConnectedHandle(GamePad disConnectGamePad);
/// <summary> 当一个手柄断开时触发 </summary>
public event GamePadDisConnectedHandle OnGamePadDisConnected;
#endregion
Dictionary<GamePadInfo, GamePad> m_gamePads = new Dictionary<GamePadInfo, GamePad>();
HashSet<GamePadInfo> m_temp = new HashSet<GamePadInfo>();
public void Update()
{
m_temp.Clear();
foreach (var info in m_gamePads.Keys)
m_temp.Add(info); //记录需要被移除的手柄
var devices = Input.GetJoystickNames();
for (int i = 0; i < devices.Length; i++)
{
var info = new GamePadInfo { Index = i, Name = devices[i] };
m_temp.Remove(info);
if (!m_gamePads.ContainsKey(info))
{
m_gamePads[info] = new GamePad(info);
OnGamePadConnected?.Invoke(m_gamePads[info]);
};
}
foreach (var info in m_temp)
{
if (m_gamePads.TryGetValue(info, out GamePad gp))
{
m_gamePads.Remove(info);
gp.Offline = true;
OnGamePadDisConnected?.Invoke(gp);
}
}
}
/// <summary>
/// 获取所有已连接的手柄,返回的结果顺序与手柄序号无关
/// </summary>
/// <returns></returns>
public GamePad[] GetGamePads()
{
return m_gamePads.Values.ToArray();
}
internal struct GamePadInfo : IEquatable<GamePadInfo>, IComparable<GamePadInfo>
{
internal int Index;
internal string Name;
public override bool Equals(object obj)
{
if (obj is GamePadInfo)
{
return Equals((GamePadInfo)obj);
}
return false;
}
public bool Equals(GamePadInfo other)
{
return Index == other.Index && Name == other.Name;
}
public override int GetHashCode()
{
// Custom hash code implementation without HashCombine
int hash = 17;
hash = hash * 31 + Index.GetHashCode();
hash = hash * 31 + (Name != null ? Name.GetHashCode() : 0);
return hash;
}
public int CompareTo(GamePadInfo other)
{
int indexComparison = Index.CompareTo(other.Index);
if (indexComparison != 0)
{
return indexComparison;
}
return string.Compare(Name, other.Name, StringComparison.Ordinal);
}
public static bool operator ==(GamePadInfo left, GamePadInfo right)
{
return left.Equals(right);
}
public static bool operator !=(GamePadInfo left, GamePadInfo right)
{
return !(left == right);
}
public static bool operator <(GamePadInfo left, GamePadInfo right)
{
return left.CompareTo(right) < 0;
}
public static bool operator >(GamePadInfo left, GamePadInfo right)
{
return left.CompareTo(right) > 0;
}
}
}
}

View File

@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: ce4d215abea527e4a8cf1103cbfecf6b

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7c141dadb47c8624c80c092e415ab621
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,140 @@
using System.Collections.Generic;
using UnityEngine;
namespace AxibugEmuOnline.Client.InputDevices
{
public class InputDevicesManager
{
Dictionary<string, InputDevice> m_devices = new Dictionary<string, InputDevice>();
public InputDevicesManager()
{
AddDevice(new KeyBoard());
}
public void AddDevice(InputDevice device)
{
m_devices[device.UniqueName] = device;
}
public void RemoveDevice(InputDevice device)
{
m_devices.Remove(device.UniqueName);
}
public InputDevice.KeyBase GetKeyByPath(string path)
{
var temp = path.Split("/");
Debug.Assert(temp.Length == 2, "Invalid Path Format");
var deviceName = temp[0];
var keyName = temp[1];
var targetDevice = FindDeviceByName(deviceName);
if (targetDevice == null) return null;
var key = targetDevice.FindKeyByKeyName(keyName);
return key;
}
public InputDevice FindDeviceByName(string deviceName)
{
m_devices.TryGetValue(deviceName, out var device);
return device;
}
/// <summary>
/// 获得键盘设备
/// <para>键盘设备被设计为有且仅有一个,所以这里应该总是能获得键盘设备</para>
/// </summary>
public KeyBoard GetKeyboard()
{
foreach (var d in m_devices.Values)
{
if (d is KeyBoard kb) return kb;
}
return null;
}
/// <summary> 由外部驱动的逻辑更新入口 </summary>
public void Update()
{
foreach (var device in m_devices.Values) device.Update();
}
}
public abstract class InputDevice
{
public abstract string UniqueName { get; }
public delegate void OnKeyStateChangedHandle(KeyBase sender);
public event OnKeyStateChangedHandle OnKeyStateChanged;
/// <summary> 指示该设备是否在线 </summary>
public abstract bool Online { get; }
/// <summary> 指示该设备当前帧是否有任意键被按下 </summary>
public bool AnyKeyDown { get; private set; }
protected Dictionary<string, KeyBase> m_keyMapper = new Dictionary<string, KeyBase>();
public InputDevice()
{
foreach (var key in DefineKeys())
{
m_keyMapper[key.KeyName] = key;
}
}
public void Update()
{
AnyKeyDown = false;
foreach (var key in m_keyMapper.Values)
{
if (key.GetButtonDown())
{
AnyKeyDown = true;
RaiseKeyEvent(key);
}
}
}
protected abstract IEnumerable<KeyBase> DefineKeys();
protected void RaiseKeyEvent(KeyBase sender)
{
OnKeyStateChanged?.Invoke(sender);
}
public KeyBase FindKeyByKeyName(string keyName)
{
m_keyMapper.TryGetValue(keyName, out var key);
return key;
}
/// <summary>
/// 输入设备的键接口
/// </summary>
public abstract class KeyBase
{
public InputDevice HostDevice { get; internal set; }
/// <summary> 获取该键是否在当前调用帧被按下 </summary>
public abstract bool GetButtonDown();
/// <summary> 获取该键是否在当前调用帧被抬起 </summary>
public abstract bool GetButtonUp();
/// <summary> 获取该键是否在当前调用帧是否处于按下状态 </summary>
public abstract bool IsPressing();
public virtual Vector2 GetVector2() { throw new System.NotImplementedException(); }
public virtual float GetFlaot() { throw new System.NotImplementedException(); }
/// <summary> 键名 </summary>
public abstract string KeyName { get; }
public string GetPath()
{
return $"{HostDevice.UniqueName}/{KeyName}";
}
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 81cfc80679d76514d801eed124ffc356

View File

@ -0,0 +1,215 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace AxibugEmuOnline.Client.InputDevices
{
public class KeyBoard : InputDevice
{
#region HardCodeForKeyboard
static readonly List<KeyCode> s_keyboardKeys = new List<KeyCode>
{
// 字母键 A-Z
KeyCode.A, KeyCode.B, KeyCode.C, KeyCode.D, KeyCode.E, KeyCode.F, KeyCode.G,
KeyCode.H, KeyCode.I, KeyCode.J, KeyCode.K, KeyCode.L, KeyCode.M, KeyCode.N,
KeyCode.O, KeyCode.P, KeyCode.Q, KeyCode.R, KeyCode.S, KeyCode.T, KeyCode.U,
KeyCode.V, KeyCode.W, KeyCode.X, KeyCode.Y, KeyCode.Z,
// 数字键 0-9
KeyCode.Alpha0, KeyCode.Alpha1, KeyCode.Alpha2, KeyCode.Alpha3, KeyCode.Alpha4,
KeyCode.Alpha5, KeyCode.Alpha6, KeyCode.Alpha7, KeyCode.Alpha8, KeyCode.Alpha9,
// 功能键 F1-F15
KeyCode.F1, KeyCode.F2, KeyCode.F3, KeyCode.F4, KeyCode.F5, KeyCode.F6,
KeyCode.F7, KeyCode.F8, KeyCode.F9, KeyCode.F10, KeyCode.F11, KeyCode.F12,
KeyCode.F13, KeyCode.F14, KeyCode.F15,
// 方向键
KeyCode.UpArrow, KeyCode.DownArrow, KeyCode.LeftArrow, KeyCode.RightArrow,
// 控制键
KeyCode.Space, KeyCode.Return, KeyCode.Escape, KeyCode.Tab, KeyCode.Backspace,
KeyCode.CapsLock, KeyCode.LeftShift, KeyCode.RightShift, KeyCode.LeftControl,
KeyCode.RightControl, KeyCode.LeftAlt, KeyCode.RightAlt, KeyCode.LeftCommand,
KeyCode.RightCommand, KeyCode.Menu,
// 符号键
KeyCode.Comma, KeyCode.Period, KeyCode.Slash, KeyCode.BackQuote, KeyCode.Quote,
KeyCode.Semicolon, KeyCode.LeftBracket, KeyCode.RightBracket, KeyCode.Backslash,
KeyCode.Minus, KeyCode.Equals, KeyCode.Tilde,
// 小键盘
KeyCode.Keypad0, KeyCode.Keypad1, KeyCode.Keypad2, KeyCode.Keypad3, KeyCode.Keypad4,
KeyCode.Keypad5, KeyCode.Keypad6, KeyCode.Keypad7, KeyCode.Keypad8, KeyCode.Keypad9,
KeyCode.KeypadPeriod, KeyCode.KeypadDivide, KeyCode.KeypadMultiply,
KeyCode.KeypadMinus, KeyCode.KeypadPlus, KeyCode.KeypadEnter, KeyCode.Numlock,
// 其他标准键
KeyCode.Print, KeyCode.Insert, KeyCode.Delete, KeyCode.Home,
KeyCode.End, KeyCode.PageUp, KeyCode.PageDown, KeyCode.Pause, KeyCode.ScrollLock,
KeyCode.Clear
};
// 字母键 A-Z
public KeyboardKey A { get; private set; } = new KeyboardKey(KeyCode.A);
public KeyboardKey B { get; private set; } = new KeyboardKey(KeyCode.B);
public KeyboardKey C { get; private set; } = new KeyboardKey(KeyCode.C);
public KeyboardKey D { get; private set; } = new KeyboardKey(KeyCode.D);
public KeyboardKey E { get; private set; } = new KeyboardKey(KeyCode.E);
public KeyboardKey F { get; private set; } = new KeyboardKey(KeyCode.F);
public KeyboardKey G { get; private set; } = new KeyboardKey(KeyCode.G);
public KeyboardKey H { get; private set; } = new KeyboardKey(KeyCode.H);
public KeyboardKey I { get; private set; } = new KeyboardKey(KeyCode.I);
public KeyboardKey J { get; private set; } = new KeyboardKey(KeyCode.J);
public KeyboardKey K { get; private set; } = new KeyboardKey(KeyCode.K);
public KeyboardKey L { get; private set; } = new KeyboardKey(KeyCode.L);
public KeyboardKey M { get; private set; } = new KeyboardKey(KeyCode.M);
public KeyboardKey N { get; private set; } = new KeyboardKey(KeyCode.N);
public KeyboardKey O { get; private set; } = new KeyboardKey(KeyCode.O);
public KeyboardKey P { get; private set; } = new KeyboardKey(KeyCode.P);
public KeyboardKey Q { get; private set; } = new KeyboardKey(KeyCode.Q);
public KeyboardKey R { get; private set; } = new KeyboardKey(KeyCode.R);
public KeyboardKey S { get; private set; } = new KeyboardKey(KeyCode.S);
public KeyboardKey T { get; private set; } = new KeyboardKey(KeyCode.T);
public KeyboardKey U { get; private set; } = new KeyboardKey(KeyCode.U);
public KeyboardKey V { get; private set; } = new KeyboardKey(KeyCode.V);
public KeyboardKey W { get; private set; } = new KeyboardKey(KeyCode.W);
public KeyboardKey X { get; private set; } = new KeyboardKey(KeyCode.X);
public KeyboardKey Y { get; private set; } = new KeyboardKey(KeyCode.Y);
public KeyboardKey Z { get; private set; } = new KeyboardKey(KeyCode.Z);
// 数字键 0-9
public KeyboardKey Alpha0 { get; private set; } = new KeyboardKey(KeyCode.Alpha0);
public KeyboardKey Alpha1 { get; private set; } = new KeyboardKey(KeyCode.Alpha1);
public KeyboardKey Alpha2 { get; private set; } = new KeyboardKey(KeyCode.Alpha2);
public KeyboardKey Alpha3 { get; private set; } = new KeyboardKey(KeyCode.Alpha3);
public KeyboardKey Alpha4 { get; private set; } = new KeyboardKey(KeyCode.Alpha4);
public KeyboardKey Alpha5 { get; private set; } = new KeyboardKey(KeyCode.Alpha5);
public KeyboardKey Alpha6 { get; private set; } = new KeyboardKey(KeyCode.Alpha6);
public KeyboardKey Alpha7 { get; private set; } = new KeyboardKey(KeyCode.Alpha7);
public KeyboardKey Alpha8 { get; private set; } = new KeyboardKey(KeyCode.Alpha8);
public KeyboardKey Alpha9 { get; private set; } = new KeyboardKey(KeyCode.Alpha9);
// 功能键 F1-F15
public KeyboardKey F1 { get; private set; } = new KeyboardKey(KeyCode.F1);
public KeyboardKey F2 { get; private set; } = new KeyboardKey(KeyCode.F2);
public KeyboardKey F3 { get; private set; } = new KeyboardKey(KeyCode.F3);
public KeyboardKey F4 { get; private set; } = new KeyboardKey(KeyCode.F4);
public KeyboardKey F5 { get; private set; } = new KeyboardKey(KeyCode.F5);
public KeyboardKey F6 { get; private set; } = new KeyboardKey(KeyCode.F6);
public KeyboardKey F7 { get; private set; } = new KeyboardKey(KeyCode.F7);
public KeyboardKey F8 { get; private set; } = new KeyboardKey(KeyCode.F8);
public KeyboardKey F9 { get; private set; } = new KeyboardKey(KeyCode.F9);
public KeyboardKey F10 { get; private set; } = new KeyboardKey(KeyCode.F10);
public KeyboardKey F11 { get; private set; } = new KeyboardKey(KeyCode.F11);
public KeyboardKey F12 { get; private set; } = new KeyboardKey(KeyCode.F12);
public KeyboardKey F13 { get; private set; } = new KeyboardKey(KeyCode.F13);
public KeyboardKey F14 { get; private set; } = new KeyboardKey(KeyCode.F14);
public KeyboardKey F15 { get; private set; } = new KeyboardKey(KeyCode.F15);
// 方向键
public KeyboardKey UpArrow { get; private set; } = new KeyboardKey(KeyCode.UpArrow);
public KeyboardKey DownArrow { get; private set; } = new KeyboardKey(KeyCode.DownArrow);
public KeyboardKey LeftArrow { get; private set; } = new KeyboardKey(KeyCode.LeftArrow);
public KeyboardKey RightArrow { get; private set; } = new KeyboardKey(KeyCode.RightArrow);
// 控制键
public KeyboardKey Space { get; private set; } = new KeyboardKey(KeyCode.Space);
public KeyboardKey Return { get; private set; } = new KeyboardKey(KeyCode.Return);
public KeyboardKey Escape { get; private set; } = new KeyboardKey(KeyCode.Escape);
public KeyboardKey Tab { get; private set; } = new KeyboardKey(KeyCode.Tab);
public KeyboardKey Backspace { get; private set; } = new KeyboardKey(KeyCode.Backspace);
public KeyboardKey CapsLock { get; private set; } = new KeyboardKey(KeyCode.CapsLock);
public KeyboardKey LeftShift { get; private set; } = new KeyboardKey(KeyCode.LeftShift);
public KeyboardKey RightShift { get; private set; } = new KeyboardKey(KeyCode.RightShift);
public KeyboardKey LeftControl { get; private set; } = new KeyboardKey(KeyCode.LeftControl);
public KeyboardKey RightControl { get; private set; } = new KeyboardKey(KeyCode.RightControl);
public KeyboardKey LeftAlt { get; private set; } = new KeyboardKey(KeyCode.LeftAlt);
public KeyboardKey RightAlt { get; private set; } = new KeyboardKey(KeyCode.RightAlt);
public KeyboardKey LeftCommand { get; private set; } = new KeyboardKey(KeyCode.LeftCommand);
public KeyboardKey RightCommand { get; private set; } = new KeyboardKey(KeyCode.RightCommand);
public KeyboardKey Menu { get; private set; } = new KeyboardKey(KeyCode.Menu);
// 符号键
public KeyboardKey Comma { get; private set; } = new KeyboardKey(KeyCode.Comma);
public KeyboardKey Period { get; private set; } = new KeyboardKey(KeyCode.Period);
public KeyboardKey Slash { get; private set; } = new KeyboardKey(KeyCode.Slash);
public KeyboardKey BackQuote { get; private set; } = new KeyboardKey(KeyCode.BackQuote);
public KeyboardKey Quote { get; private set; } = new KeyboardKey(KeyCode.Quote);
public KeyboardKey Semicolon { get; private set; } = new KeyboardKey(KeyCode.Semicolon);
public KeyboardKey LeftBracket { get; private set; } = new KeyboardKey(KeyCode.LeftBracket);
public KeyboardKey RightBracket { get; private set; } = new KeyboardKey(KeyCode.RightBracket);
public KeyboardKey Backslash { get; private set; } = new KeyboardKey(KeyCode.Backslash);
public KeyboardKey Minus { get; private set; } = new KeyboardKey(KeyCode.Minus);
public KeyboardKey Equals_k { get; private set; } = new KeyboardKey(KeyCode.Equals);
public KeyboardKey Tilde { get; private set; } = new KeyboardKey(KeyCode.Tilde);
// 小键盘
public KeyboardKey Keypad0 { get; private set; } = new KeyboardKey(KeyCode.Keypad0);
public KeyboardKey Keypad1 { get; private set; } = new KeyboardKey(KeyCode.Keypad1);
public KeyboardKey Keypad2 { get; private set; } = new KeyboardKey(KeyCode.Keypad2);
public KeyboardKey Keypad3 { get; private set; } = new KeyboardKey(KeyCode.Keypad3);
public KeyboardKey Keypad4 { get; private set; } = new KeyboardKey(KeyCode.Keypad4);
public KeyboardKey Keypad5 { get; private set; } = new KeyboardKey(KeyCode.Keypad5);
public KeyboardKey Keypad6 { get; private set; } = new KeyboardKey(KeyCode.Keypad6);
public KeyboardKey Keypad7 { get; private set; } = new KeyboardKey(KeyCode.Keypad7);
public KeyboardKey Keypad8 { get; private set; } = new KeyboardKey(KeyCode.Keypad8);
public KeyboardKey Keypad9 { get; private set; } = new KeyboardKey(KeyCode.Keypad9);
public KeyboardKey KeypadPeriod { get; private set; } = new KeyboardKey(KeyCode.KeypadPeriod);
public KeyboardKey KeypadDivide { get; private set; } = new KeyboardKey(KeyCode.KeypadDivide);
public KeyboardKey KeypadMultiply { get; private set; } = new KeyboardKey(KeyCode.KeypadMultiply);
public KeyboardKey KeypadMinus { get; private set; } = new KeyboardKey(KeyCode.KeypadMinus);
public KeyboardKey KeypadPlus { get; private set; } = new KeyboardKey(KeyCode.KeypadPlus);
public KeyboardKey KeypadEnter { get; private set; } = new KeyboardKey(KeyCode.KeypadEnter);
public KeyboardKey Numlock { get; private set; } = new KeyboardKey(KeyCode.Numlock);
// 其他标准键
public KeyboardKey Print { get; private set; } = new KeyboardKey(KeyCode.Print);
public KeyboardKey Insert { get; private set; } = new KeyboardKey(KeyCode.Insert);
public KeyboardKey Delete { get; private set; } = new KeyboardKey(KeyCode.Delete);
public KeyboardKey Home { get; private set; } = new KeyboardKey(KeyCode.Home);
public KeyboardKey End { get; private set; } = new KeyboardKey(KeyCode.End);
public KeyboardKey PageUp { get; private set; } = new KeyboardKey(KeyCode.PageUp);
public KeyboardKey PageDown { get; private set; } = new KeyboardKey(KeyCode.PageDown);
public KeyboardKey Pause { get; private set; } = new KeyboardKey(KeyCode.Pause);
public KeyboardKey ScrollLock { get; private set; } = new KeyboardKey(KeyCode.ScrollLock);
public KeyboardKey Clear { get; private set; } = new KeyboardKey(KeyCode.Clear);
#endregion
public override string UniqueName => nameof(KeyBoard);
public override bool Online => true;
protected override IEnumerable<KeyBase> DefineKeys()
{
var keys = s_keyboardKeys.Select(kc => new KeyboardKey(kc) as KeyBase);
return keys;
}
public class KeyboardKey : KeyBase
{
internal KeyCode m_listenKey;
public KeyboardKey(KeyCode listenKey)
{
m_listenKey = listenKey;
}
public override bool GetButtonDown()
{
return Input.GetKeyDown(m_listenKey);
}
public override bool GetButtonUp()
{
return Input.GetKeyUp(m_listenKey);
}
public override bool IsPressing()
{
return Input.GetKey(m_listenKey);
}
public override string KeyName => m_listenKey.ToString();
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e75cd67769afcad4890be3acf0ac1330

View File

@ -2,25 +2,19 @@
"dependencies": {
"com.unity.2d.sprite": "1.0.0",
"com.unity.ide.visualstudio": "2.0.22",
"com.unity.test-framework": "1.4.5",
"com.unity.ugui": "2.0.0",
"com.unity.modules.accessibility": "1.0.0",
"com.unity.modules.ai": "1.0.0",
"com.unity.modules.androidjni": "1.0.0",
"com.unity.modules.animation": "1.0.0",
"com.unity.modules.assetbundle": "1.0.0",
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.cloth": "1.0.0",
"com.unity.modules.director": "1.0.0",
"com.unity.modules.imageconversion": "1.0.0",
"com.unity.modules.imgui": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.particlesystem": "1.0.0",
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.physics2d": "1.0.0",
"com.unity.modules.screencapture": "1.0.0",
"com.unity.modules.terrain": "1.0.0",
"com.unity.modules.terrainphysics": "1.0.0",
"com.unity.modules.tilemap": "1.0.0",
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.uielements": "1.0.0",
"com.unity.modules.umbra": "1.0.0",

View File

@ -8,10 +8,10 @@
},
"com.unity.ext.nunit": {
"version": "2.0.5",
"depth": 2,
"depth": 1,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.cn"
"url": "https://packages.unity.com"
},
"com.unity.ide.visualstudio": {
"version": "2.0.22",
@ -20,18 +20,18 @@
"dependencies": {
"com.unity.test-framework": "1.1.9"
},
"url": "https://packages.unity.cn"
"url": "https://packages.unity.com"
},
"com.unity.test-framework": {
"version": "1.4.5",
"depth": 1,
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.ext.nunit": "2.0.3",
"com.unity.modules.imgui": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0"
},
"url": "https://packages.unity.cn"
"url": "https://packages.unity.com"
},
"com.unity.ugui": {
"version": "2.0.0",
@ -48,12 +48,6 @@
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.ai": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.androidjni": {
"version": "1.0.0",
"depth": 0,
@ -78,23 +72,6 @@
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.cloth": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics": "1.0.0"
}
},
"com.unity.modules.director": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.animation": "1.0.0"
}
},
"com.unity.modules.hierarchycore": {
"version": "1.0.0",
"depth": 1,
@ -119,12 +96,6 @@
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.particlesystem": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.physics": {
"version": "1.0.0",
"depth": 0,
@ -153,29 +124,6 @@
"com.unity.modules.jsonserialize": "1.0.0"
}
},
"com.unity.modules.terrain": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.terrainphysics": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.terrain": "1.0.0"
}
},
"com.unity.modules.tilemap": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics2d": "1.0.0"
}
},
"com.unity.modules.ui": {
"version": "1.0.0",
"depth": 0,

View File

@ -18,10 +18,11 @@ MonoBehaviour:
m_SeeAllPackageVersions: 0
m_DismissPreviewPackagesInUse: 0
oneTimeWarningShown: 0
oneTimeDeprecatedPopUpShown: 0
m_Registries:
- m_Id: main
m_Name:
m_Url: https://packages.unity.cn
m_Url: https://packages.unity.com
m_Scopes: []
m_IsDefault: 1
m_Capabilities: 7
@ -31,6 +32,6 @@ MonoBehaviour:
m_RegistryInfoDraft:
m_Modified: 0
m_ErrorMessage:
m_UserModificationsInstanceId: -892
m_OriginalInstanceId: -894
m_UserModificationsInstanceId: -882
m_OriginalInstanceId: -884
m_LoadAssets: 0