diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/App.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/App.cs index 47909e9d..aa5ba5a8 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/App.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/App.cs @@ -90,9 +90,14 @@ namespace AxibugEmuOnline.Client.ClientCore 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 UNITY_PSP2 + PSP2Init(); +#endif + +#if UNITY_SWITCH + SwitchInit(); +#endif input = new InputDevicesManager(); FileDownloader = new FileDownloader(); @@ -153,11 +158,18 @@ namespace AxibugEmuOnline.Client.ClientCore sonyVitaCommonDialog = new GameObject().AddComponent(); #endif -#if UNITY_SWITCH - //创建创建Switch - switchCommon = new GameObject().AddComponent(); -#endif + } + private static void SwitchInit() + { +#if UNITY_SWITCH + AxiNS.instance.Init(); + if (!AxiIO.Directory.Exists(App.PersistentDataRootPath())) + AxiIO.Directory.CreateDirectory(App.PersistentDataRootPath()); + switchCommon = new GameObject().AddComponent(); + switchCommon.gameObject.name = "[SwitchCommon]"; + GameObject.DontDestroyOnLoad(switchCommon); +#endif } diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInputSP/UGUI/AxiScreenGamepad.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInputSP/UGUI/AxiScreenGamepad.cs index e9ae262f..a1e566cc 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInputSP/UGUI/AxiScreenGamepad.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/AxiInputSP/UGUI/AxiScreenGamepad.cs @@ -1,9 +1,9 @@ -using System.Collections.Generic; -using UnityEngine; - -namespace AxiInputSP.UGUI -{ - public class AxiScreenGamepad : MonoBehaviour +using System.Collections.Generic; +using UnityEngine; + +namespace AxiInputSP.UGUI +{ + public class AxiScreenGamepad : MonoBehaviour { public delegate void OnAxiScreenGamepadActiveHandle(AxiScreenGamepad sender); public delegate void OnAxiScreenGamepadDisactiveHandle(AxiScreenGamepad sender); @@ -58,5 +58,5 @@ namespace AxiInputSP.UGUI { OnGamepadDisactive?.Invoke(this); } - } -} + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/DebuggerByGUI.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/DebuggerByGUI.cs index 9affce45..0853c920 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/DebuggerByGUI.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/DebuggerByGUI.cs @@ -24,7 +24,7 @@ public class DebuggerByGUI : MonoBehaviour private Vector2 _scrollLogView = Vector2.zero; private Vector2 _scrollCurrentLogView = Vector2.zero; private Vector2 _scrollSystemView = Vector2.zero; - private bool _expansion = false; + private bool _expansion = false; private Rect _windowRect = new Rect(0, 0, 100, 60); private int _fps = 0; @@ -32,9 +32,26 @@ public class DebuggerByGUI : MonoBehaviour private int _frameNumber = 0; private float _lastShowFPSTime = 0f; - private void Start() + public bool OpenHubOnStart = false; + public bool AutoShowLastLogLine = false; + public bool OnlyShowErrOnStart = false; + + private void Start() { - DontDestroyOnLoad(this.gameObject); + if (OpenHubOnStart) + { + _expansion = true; + _windowRect.width = 1000; + _windowRect.height = 600; + } + + if (OnlyShowErrOnStart) + { + _showInfoLog = false; + _showWarningLog = false; + } + + DontDestroyOnLoad(this.gameObject); if (AllowDebugging) { Application.logMessageReceived += LogHandler; @@ -237,16 +254,22 @@ public class DebuggerByGUI : MonoBehaviour GUILayout.Label(_logInformations[i].message); GUILayout.FlexibleSpace(); GUI.contentColor = Color.white; - GUILayout.EndHorizontal(); + GUILayout.EndHorizontal(); } } GUILayout.EndScrollView(); _scrollCurrentLogView = GUILayout.BeginScrollView(_scrollCurrentLogView, "Box", GUILayout.Height(100)); - if (_currentLogIndex != -1) + + if (AutoShowLastLogLine) + { + _scrollLogView.y = Mathf.Lerp(_scrollLogView.y, float.MaxValue, 0.1f); + } + + if (_currentLogIndex != -1) { GUILayout.Label(_logInformations[_currentLogIndex].message + "\r\n\r\n" + _logInformations[_currentLogIndex].stackTrace); - } + } GUILayout.EndScrollView(); } #endregion diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/EmuCore.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/EmuCore.cs index 01db3815..dfaebcec 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/EmuCore.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/EmuCore.cs @@ -1,69 +1,69 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugProtobuf; -using AxiReplay; -using System; -using UnityEngine; -using UnityEngine.UI; - -namespace AxibugEmuOnline.Client +using AxibugEmuOnline.Client.ClientCore; +using AxibugProtobuf; +using AxiReplay; +using System; +using UnityEngine; +using UnityEngine.UI; + +namespace AxibugEmuOnline.Client { - public abstract class EmuCore : MonoBehaviour - { + public abstract class EmuCore : MonoBehaviour + { /// 获得模拟器核心中的状态快照对象 - public abstract object GetState(); + public abstract object GetState(); /// 获得模拟器核心中的状态快照字节数据 - public abstract byte[] GetStateBytes(); + public abstract byte[] GetStateBytes(); /// 加载状态快照 - /// 该对象应该来自核心的方法的返回值,或是从返回的byte数组构建 - public abstract void LoadState(object state); + /// 该对象应该来自核心的方法的返回值,或是从返回的byte数组构建 + public abstract void LoadState(object state); /// 加载状态快照 - /// 该对象应该来自核心的返回的byte数组 - public abstract void LoadStateFromBytes(byte[] data); - /// 暂停核心推帧 - public abstract void Pause(); - /// 恢复核心推帧(从Pause状态恢复) - public abstract void Resume(); - /// 启动模拟器逻辑 - public abstract MsgBool StartGame(RomFile romFile); - /// 释放模拟器核心 - public abstract void Dispose(); - /// 重置核心,通常由模拟器核心提供的功能 + /// 该对象应该来自核心的返回的byte数组 + public abstract void LoadStateFromBytes(byte[] data); + /// 暂停核心推帧 + public abstract void Pause(); + /// 恢复核心推帧(从Pause状态恢复) + public abstract void Resume(); + /// 启动模拟器逻辑 + public abstract MsgBool StartGame(RomFile romFile); + /// 释放模拟器核心 + public abstract void Dispose(); + /// 重置核心,通常由模拟器核心提供的功能 public abstract void DoReset(); /// 获得模拟器核心的控制器设置器 /// public abstract IControllerSetuper GetControllerSetuper(); /// 核心所属平台 - public abstract RomPlatformType Platform { get; } + public abstract RomPlatformType Platform { get; } /// 获取当前模拟器帧序号,在加载快照和Reset后,应当重置为0 - public abstract uint Frame { get; } - - public abstract void PushEmulatorFrame(); + public abstract uint Frame { get; } + + public abstract void PushEmulatorFrame(); /// 模拟器核心推帧结束 protected abstract void AfterPushFrame(); - public abstract void GetAudioParams(out int frequency, out int channels); - public abstract Texture OutputPixel { get; } + public abstract void GetAudioParams(out int frequency, out int channels); + public abstract Texture OutputPixel { get; } public abstract RawImage DrawCanvas { get; } - /// 指示该游戏实例是否处于联机模式 - public bool IsNetPlay - { - get - { - if (!App.user.IsLoggedIn) return false; - if (App.roomMgr.mineRoomMiniInfo == null) return false; - if (App.roomMgr.RoomState <= RoomGameState.OnlyHost) return false; - - return true; - } - } + /// 指示该游戏实例是否处于联机模式 + public bool IsNetPlay + { + get + { + if (!App.user.IsLoggedIn) return false; + if (App.roomMgr.mineRoomMiniInfo == null) return false; + if (App.roomMgr.RoomState <= RoomGameState.OnlyHost) return false; + + return true; + } + } } /// 输入数据类型 public abstract class EmuCore : EmuCore - { - protected virtual bool EnableRollbackNetCode => false; - + { + protected virtual bool EnableRollbackNetCode => false; + public sealed override void PushEmulatorFrame() { if (!TryPushEmulatorFrame()) return; @@ -115,28 +115,28 @@ namespace AxibugEmuOnline.Client bool result = false; inputData = default(INPUTDATA); - if (IsNetPlay) - { - if (App.roomMgr.netReplay.TryGetNextFrame((int)Frame, EnableRollbackNetCode ? true : false, out m_replayData, out m_frameDiff, out m_inputDiff)) + if (IsNetPlay) + { + if (App.roomMgr.netReplay.TryGetNextFrame((int)Frame, EnableRollbackNetCode ? true : false, out m_replayData, out m_frameDiff, out m_inputDiff)) { if (m_inputDiff) { App.log.Debug($"{DateTime.Now.ToString("hh:mm:ss.fff")} TryGetNextFrame remoteFrame->{App.roomMgr.netReplay.mRemoteFrameIdx} diff->{m_frameDiff} " + $"frame=>{m_replayData.FrameStartID} InPut=>{m_replayData.InPut}"); - } - - inputData = ConvertInputDataFromNet(m_replayData); - result = true; - } + } + + inputData = ConvertInputDataFromNet(m_replayData); + result = true; + } else { result = false; } } - else//单机模式 - { - inputData = GetLocalInput(); - result = true; + else//单机模式 + { + inputData = GetLocalInput(); + result = true; } return result; @@ -147,5 +147,5 @@ namespace AxibugEmuOnline.Client protected abstract ulong InputDataToNet(INPUTDATA inputData); /// 模拟器核心推帧 protected abstract bool OnPushEmulatorFrame(INPUTDATA InputData); - } -} + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/EssgeeEmulator/UEssgee.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/EssgeeEmulator/UEssgee.cs index 4945f129..f21a7735 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/EssgeeEmulator/UEssgee.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/EssgeeEmulator/UEssgee.cs @@ -1,157 +1,157 @@ -using AxibugEmuOnline.Client; -using AxibugEmuOnline.Client.ClientCore; -using AxibugProtobuf; -using AxiReplay; -using Essgee; -using Essgee.Emulation; -using Essgee.Emulation.Configuration; -using Essgee.EventArguments; -using Essgee.Exceptions; -using Essgee.Extensions; -using Essgee.Metadata; -using Essgee.Utilities; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using UnityEngine; -using UnityEngine.UI; - -public class UEssgee : EmuCore -{ - public static UEssgee instance; - public static System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew(); - public static bool bInGame => instance?.emulatorHandler?.IsRunning == true ? true : false; - - public override RomPlatformType Platform => mPlatform; - - public override uint Frame => (uint)emulatorHandler.AxiEmuRunFrame; - - public override Texture OutputPixel => graphicsHandler.rawBufferWarper; - - public override RawImage DrawCanvas => graphicsHandler.DrawCanvas; - - public static bool bLogicUpdatePause { get; private set; } - #region - - public UEGVideoPlayer graphicsHandler; - UEGSoundPlayer soundHandler; - GameMetadataHandler gameMetadataHandler; - GameMetadata lastGameMetadata; - Essgee.Emulation.EmulatorHandler emulatorHandler; - UEGResources uegResources; - UEGIO uegIO; - UEGLog uegLog; - UEGSaveByteConvert uegSaveByteConvert; - private Canvas mCanvas; - bool lastUserPauseState; - double currentPixelAspectRatio; - private UEGKeyboard mUniKeyboard; - private RomPlatformType mPlatform = RomPlatformType.MasterSystem; - - #endregion - - void Awake() - { - App.tick.SetFrameRate(60); - instance = this; - uegResources = new UEGResources(); - uegIO = new UEGIO(); - uegLog = new UEGLog(); - uegSaveByteConvert = new UEGSaveByteConvert(); - mCanvas = GameObject.Find("Canvas").GetComponent(); - mCanvas.worldCamera = Camera.main; - //InitAll(uegResources, App.PersistentDataPath(mPlatform)); - } - - void OnDisable() - { - SaveConfiguration(); - Dispose(false); - } - - - #region EmuCore接入实现 - - public override object GetState() - { - return emulatorHandler.GetStateData(); - } - - public override byte[] GetStateBytes() - { - return emulatorHandler.GetStateData(); - } - - public override void LoadState(object state) - { - emulatorHandler.SetStateData((byte[])state); - } - - public override void LoadStateFromBytes(byte[] data) - { - emulatorHandler.SetStateData(data); - } - - public override void Pause() - { - bLogicUpdatePause = false; - } - public override void Resume() - { - bLogicUpdatePause = true; - } - - public override MsgBool StartGame(RomFile romFile) - { - mPlatform = romFile.Platform; - - InitAll(uegResources, uegIO, App.PersistentDataPath(mPlatform)); - - bLogicUpdatePause = true; - - //保存当前正在进行的游戏存档 - if (emulatorHandler != null && !emulatorHandler.IsRunning) - { - emulatorHandler.SaveCartridge(); - } - - if (LoadAndRunCartridge(romFile.LocalFilePath)) - return true; - else - return "Rom加载失败"; - } - - public override void Dispose() - { - if (!emulatorHandler.IsRunning) +using AxibugEmuOnline.Client; +using AxibugEmuOnline.Client.ClientCore; +using AxibugProtobuf; +using AxiReplay; +using Essgee; +using Essgee.Emulation; +using Essgee.Emulation.Configuration; +using Essgee.EventArguments; +using Essgee.Exceptions; +using Essgee.Extensions; +using Essgee.Metadata; +using Essgee.Utilities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; +using UnityEngine.UI; + +public class UEssgee : EmuCore +{ + public static UEssgee instance; + public static System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew(); + public static bool bInGame => instance?.emulatorHandler?.IsRunning == true ? true : false; + + public override RomPlatformType Platform => mPlatform; + + public override uint Frame => (uint)emulatorHandler.AxiEmuRunFrame; + + public override Texture OutputPixel => graphicsHandler.rawBufferWarper; + + public override RawImage DrawCanvas => graphicsHandler.DrawCanvas; + + public static bool bLogicUpdatePause { get; private set; } + #region + + public UEGVideoPlayer graphicsHandler; + UEGSoundPlayer soundHandler; + GameMetadataHandler gameMetadataHandler; + GameMetadata lastGameMetadata; + Essgee.Emulation.EmulatorHandler emulatorHandler; + UEGResources uegResources; + UEGIO uegIO; + UEGLog uegLog; + UEGSaveByteConvert uegSaveByteConvert; + private Canvas mCanvas; + bool lastUserPauseState; + double currentPixelAspectRatio; + private UEGKeyboard mUniKeyboard; + private RomPlatformType mPlatform = RomPlatformType.MasterSystem; + + #endregion + + void Awake() + { + App.tick.SetFrameRate(60); + instance = this; + uegResources = new UEGResources(); + uegIO = new UEGIO(); + uegLog = new UEGLog(); + uegSaveByteConvert = new UEGSaveByteConvert(); + mCanvas = GameObject.Find("Canvas").GetComponent(); + mCanvas.worldCamera = Camera.main; + //InitAll(uegResources, App.PersistentDataPath(mPlatform)); + } + + void OnDisable() + { + SaveConfiguration(); + Dispose(false); + } + + + #region EmuCore接入实现 + + public override object GetState() + { + return emulatorHandler.GetStateData(); + } + + public override byte[] GetStateBytes() + { + return emulatorHandler.GetStateData(); + } + + public override void LoadState(object state) + { + emulatorHandler.SetStateData((byte[])state); + } + + public override void LoadStateFromBytes(byte[] data) + { + emulatorHandler.SetStateData(data); + } + + public override void Pause() + { + bLogicUpdatePause = false; + } + public override void Resume() + { + bLogicUpdatePause = true; + } + + public override MsgBool StartGame(RomFile romFile) + { + mPlatform = romFile.Platform; + + InitAll(uegResources, uegIO, App.PersistentDataPath(mPlatform)); + + bLogicUpdatePause = true; + + //保存当前正在进行的游戏存档 + if (emulatorHandler != null && !emulatorHandler.IsRunning) { - emulatorHandler.SaveCartridge(); - } - ShutdownEmulation(); - } - - public override void DoReset() - { - emulatorHandler.SaveCartridge(); - emulatorHandler.Reset(); - } - - public override IControllerSetuper GetControllerSetuper() - { - return mUniKeyboard.ControllerMapper; - } + emulatorHandler.SaveCartridge(); + } + + if (LoadAndRunCartridge(romFile.LocalFilePath)) + return true; + else + return "Rom加载失败"; + } + + public override void Dispose() + { + if (!emulatorHandler.IsRunning) + { + emulatorHandler.SaveCartridge(); + } + ShutdownEmulation(); + } + + public override void DoReset() + { + emulatorHandler.SaveCartridge(); + emulatorHandler.Reset(); + } + + public override IControllerSetuper GetControllerSetuper() + { + return mUniKeyboard.ControllerMapper; + } protected override bool OnPushEmulatorFrame(ulong InputData) { - if (!emulatorHandler.IsRunning) return false; + if (!emulatorHandler.IsRunning) return false; if (!bLogicUpdatePause) return false; mUniKeyboard.SetCurrKeyArr(InputData); emulatorHandler.Update_Frame(); return true; - } - + } + protected override ulong ConvertInputDataFromNet(ReplayStep step) { return step.InPut; @@ -166,682 +166,682 @@ public class UEssgee : EmuCore { return mUniKeyboard.DoLocalPressedKeys(); } - - protected override void AfterPushFrame() - { - } - - public override void GetAudioParams(out int frequency, out int channels) - { - frequency = soundHandler.sampleRate; - channels = soundHandler.channle; - } - #endregion - - void InitAll(IGameMetaReources metaresources, IEssgeeIOSupport uegIO, string CustonDataDir) - { - //初始化配置 - InitAppEnvironment(CustonDataDir, uegIO); - InitEmu(); - //细节初始化 - InitializeHandlers(metaresources); - } - - private void InitAppEnvironment(string CustonDataDir, IEssgeeIOSupport uegIO) - { - Essgee.Emulation.EmulatorHandler.io = uegIO; - EssgeeLogger.Init(uegLog); - - //EmuStandInfo.datDirectoryPath = Path.Combine(BaseDataDir, "EssgeeAssets", "No-Intro"); - //EmuStandInfo.metadataDatabaseFilePath = Path.Combine(BaseDataDir, "EssgeeAssets", "MetadataDatabase.json"); - - EmuStandInfo.jsonConfigFileName = "Config.json"; - EmuStandInfo.saveDataDirectoryName = "Saves"; - EmuStandInfo.screenshotDirectoryName = "Screenshots"; - EmuStandInfo.saveStateDirectoryName = "Savestates"; - EmuStandInfo.extraDataDirectoryName = "Extras"; - EmuStandInfo.ProductName = "AxibugEmu"; - EmuStandInfo.ProductVersion = ""; - - EmuStandInfo.programDataDirectory = System.IO.Path.Combine(CustonDataDir, EmuStandInfo.ProductName); - EmuStandInfo.programConfigPath = System.IO.Path.Combine(EmuStandInfo.programDataDirectory, EmuStandInfo.jsonConfigFileName); - - EmuStandInfo.ShaderPath = System.IO.Path.Combine(CustonDataDir, "Assets", "Shaders"); - EmuStandInfo.SaveDataPath = System.IO.Path.Combine(EmuStandInfo.programDataDirectory, EmuStandInfo.saveDataDirectoryName); - EmuStandInfo.ScreenshotPath = System.IO.Path.Combine(EmuStandInfo.programDataDirectory, EmuStandInfo.screenshotDirectoryName); - EmuStandInfo.SaveStatePath = System.IO.Path.Combine(EmuStandInfo.programDataDirectory, EmuStandInfo.saveStateDirectoryName); - EmuStandInfo.ExtraDataPath = System.IO.Path.Combine(EmuStandInfo.programDataDirectory, EmuStandInfo.extraDataDirectoryName); - - LoadConfiguration(); - - - if (!AxiIO.Directory.Exists(EmuStandInfo.SaveDataPath)) - AxiIO.Directory.CreateDirectory(EmuStandInfo.SaveDataPath); - - if (!AxiIO.Directory.Exists(EmuStandInfo.ScreenshotPath)) - AxiIO.Directory.CreateDirectory(EmuStandInfo.ScreenshotPath); - - if (!AxiIO.Directory.Exists(EmuStandInfo.SaveStatePath)) - AxiIO.Directory.CreateDirectory(EmuStandInfo.SaveStatePath); - - if (!AxiIO.Directory.Exists(EmuStandInfo.ExtraDataPath)) - AxiIO.Directory.CreateDirectory(EmuStandInfo.ExtraDataPath); - - if (AppEnvironment.EnableLogger) - { - //TODO 关闭Debug - //Logger.Flush(); - //Logger.Close(); - } - } - - void InitEmu() - { - //keysDown = new List(); - } - - #region 细节初始化 - - private void InitializeHandlers(IGameMetaReources metaresources) - { - InitializeOSDHandler(); - InitializeGraphicsHandler(); - InitializeSoundHandler(); - InitializeMetadataHandler(metaresources); - - mUniKeyboard = this.gameObject.AddComponent(); - } - - private void InitializeOSDHandler() - { - - //var osdFontText = Assembly.GetExecutingAssembly().ReadEmbeddedImageFile($"{Application.ProductName}.Assets.OsdFont.png"); - //onScreenDisplayHandler = new OnScreenDisplayHandler(osdFontText); - - //onScreenDisplayHandler?.EnqueueMessageDebug($"Hello from {GetProductNameAndVersionString(true)}, this is a debug build!\nOSD handler initialized; font bitmap is {osdFontText.Width}x{osdFontText.Height}."); - - //if (onScreenDisplayHandler == null) throw new HandlerException("Failed to initialize OSD handler"); - } - - private void InitializeGraphicsHandler() - { - graphicsHandler = this.gameObject.GetComponent(); - //graphicsHandler = new GraphicsHandler(onScreenDisplayHandler); - //graphicsHandler?.LoadShaderBundle(Program.Configuration.LastShader); - } - - private void InitializeSoundHandler() - { - soundHandler = this.gameObject.GetComponent(); - //soundHandler = new SoundHandler(onScreenDisplayHandler, Program.Configuration.SampleRate, 2, ExceptionHandler); - //soundHandler.SetVolume(Program.Configuration.Volume); - //soundHandler.SetMute(Program.Configuration.Mute); - //soundHandler.SetLowPassFilter(Program.Configuration.LowPassFilter); - //soundHandler.Startup(); - } - - private void InitializeMetadataHandler(IGameMetaReources metaresources) - { - //gameMetadataHandler = new GameMetadataHandler(onScreenDisplayHandler); - gameMetadataHandler = new GameMetadataHandler(metaresources); - } - #endregion - void Dispose(bool disposing) - { - //TODO 释放时 - //if (disposing) - //{ - // if (components != null) components.Dispose(); - - // if (onScreenDisplayHandler != null) onScreenDisplayHandler.Dispose(); - // if (graphicsHandler != null) graphicsHandler.Dispose(); - // if (soundHandler != null) soundHandler.Dispose(); - //} - - //base.Dispose(disposing); - } - #region 配置 - private static void LoadConfiguration() - { - //TODO 暂时跳过这里的配置加载 - //Directory.CreateDirectory(EmuStandInfo.programDataDirectory); - //if (!File.Exists(EmuStandInfo.programConfigPath) || (EmuStandInfo.Configuration = EmuStandInfo.programConfigPath.DeserializeFromFile()) == null) - //{ - // EmuStandInfo.Configuration = new Configuration(); - // EmuStandInfo.Configuration.SerializeToFile(EmuStandInfo.programConfigPath); - //} - - EmuStandInfo.Configuration = new Essgee.Configuration(); - - List machineType = new List(); - machineType.Add(typeof(GameBoy)); - machineType.Add(typeof(GameBoyColor)); - machineType.Add(typeof(ColecoVision)); - machineType.Add(typeof(GameGear)); - machineType.Add(typeof(MasterSystem)); - machineType.Add(typeof(SC3000)); - machineType.Add(typeof(SG1000)); - - //foreach (var machineConfigType in Assembly.GetExecutingAssembly().GetTypes().Where(x => typeof(IConfiguration).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract)) - foreach (var machineConfigType in machineType) - { - if (!EmuStandInfo.Configuration.Machines.ContainsKey(machineConfigType.Name)) - EmuStandInfo.Configuration.Machines.Add(machineConfigType.Name, (IConfiguration)Activator.CreateInstance(machineConfigType)); - } - - //foreach (var debuggerFormType in Assembly.GetExecutingAssembly().GetTypes().Where(x => typeof(IDebuggerForm).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract)) - //{ - // if (!StandInfo.Configuration.DebugWindows.ContainsKey(debuggerFormType.Name)) - // StandInfo.Configuration.DebugWindows.Add(debuggerFormType.Name, Point.Empty); - //} - } - - private void ApplyConfigOverrides(Type machineType) - { - var forcePowerOnWithoutCart = false; - var hasTVStandardOverride = false; - var hasRegionOverride = false; - var hasDisallowMemoryControlOverride = false; - - var overrideConfig = EmuStandInfo.Configuration.Machines[machineType.Name].CloneObject(); - - if (lastGameMetadata == null) - { - var property = overrideConfig.GetType().GetProperty("UseBootstrap"); - if (property != null && (bool)property.GetValue(overrideConfig) != true) - { - property.SetValue(overrideConfig, true); - forcePowerOnWithoutCart = true; - } - } - - if (lastGameMetadata != null && lastGameMetadata.PreferredTVStandard != TVStandard.Auto) - { - var property = overrideConfig.GetType().GetProperty("TVStandard"); - if (property != null) - { - property.SetValue(overrideConfig, lastGameMetadata.PreferredTVStandard); - hasTVStandardOverride = true; - } - } - - if (lastGameMetadata != null && lastGameMetadata.PreferredRegion != Essgee.Emulation.Region.Auto) - { - var property = overrideConfig.GetType().GetProperty("Region"); - if (property != null) - { - property.SetValue(overrideConfig, lastGameMetadata.PreferredRegion); - hasRegionOverride = true; - } - } - - if (lastGameMetadata != null && lastGameMetadata.AllowMemoryControl != true) - { - var propertyMem = overrideConfig.GetType().GetProperty("AllowMemoryControl"); - if (propertyMem != null) - { - propertyMem.SetValue(overrideConfig, lastGameMetadata.AllowMemoryControl); - hasDisallowMemoryControlOverride = true; - - var propertyBoot = overrideConfig.GetType().GetProperty("UseBootstrap"); - if (propertyBoot != null) - { - propertyBoot.SetValue(overrideConfig, false); - } - } - } - - if (forcePowerOnWithoutCart) - EssgeeLogger.EnqueueMessageWarning("Bootstrap ROM is disabled in settings; enabling it for this startup."); - - if (hasTVStandardOverride) - EssgeeLogger.EnqueueMessageWarning($"Overriding TV standard setting; running game as {lastGameMetadata?.PreferredTVStandard}."); - - if (hasRegionOverride) - EssgeeLogger.EnqueueMessageWarning($"Overriding region setting; running game as {lastGameMetadata?.PreferredRegion}."); - - if (hasDisallowMemoryControlOverride) - EssgeeLogger.EnqueueMessageWarning("Game-specific hack: Preventing software from reconfiguring memory control.\nBootstrap ROM has been disabled for this startup due to memory control hack."); - - if (forcePowerOnWithoutCart || hasTVStandardOverride || hasRegionOverride || hasDisallowMemoryControlOverride) - emulatorHandler.SetConfiguration(overrideConfig); - } - public static void SaveConfiguration() - { - //不用保存这个配置 - //EmuStandInfo.Configuration.SerializeToFile(EmuStandInfo.programConfigPath); - } - #endregion - - #region 模拟器基本设置 - - public void SetEmuFpsLimit(bool bOpen) - { - emulatorHandler?.SetFpsLimiting(bOpen); - } - public void SetSoundMute(bool bOpen) - { - //soundHandler?.SetMute(Program.Configuration.Mute); - } - public void SetSoundLowPassFilter(bool bOpen) - { - //soundHandler?.SetLowPassFilter(Program.Configuration.LowPassFilter);; - } - public void SetTemporaryPause(bool newTemporaryPauseState) - { - if (emulatorHandler == null || !emulatorHandler.IsRunning || !EmuStandInfo.Configuration.AutoPause) return; - - if (newTemporaryPauseState) - emulatorHandler.Pause(true); - else if (!lastUserPauseState) - emulatorHandler.Pause(false); - } - #endregion - - #region 模拟器生命周期 - - - private void PowerOnWithoutCartridge(Type machineType) - { - //TODO IsRecording?? 可能需要实现 - //if (soundHandler.IsRecording) - // soundHandler.CancelRecording(); - - InitializeEmulation(machineType); - - lastGameMetadata = null; - - ApplyConfigOverrides(machineType); - - - emulatorHandler.Startup(); - - EssgeeLogger.EnqueueMessageSuccess("Power on without cartridge."); - } - - - private bool LoadAndRunCartridge(string fileName) - { - try - { - - var (machineType, romData) = CartridgeLoader.Load(fileName, "ROM image"); - - //TODO IsRecording?? 可能需要实现 - //if (soundHandler.IsRecording) - // soundHandler.CancelRecording(); - - - InitializeEmulation(machineType); - - lastGameMetadata = gameMetadataHandler.GetGameMetadata(emulatorHandler.Information.DatFileName, fileName, Crc32.Calculate(romData), romData.Length); - - ApplyConfigOverrides(machineType); - - emulatorHandler.LoadCartridge(romData, lastGameMetadata); - - //AddToRecentFiles(fileName); - //CreateRecentFilesMenu(); - //CreateLoadSaveStateMenus(); - //CreateToggleGraphicsLayersMenu(); - //CreateToggleSoundChannelsMenu(); - - //takeScreenshotToolStripMenuItem.Enabled = pauseToolStripMenuItem.Enabled = resetToolStripMenuItem.Enabled = stopToolStripMenuItem.Enabled = true; - //loadStateToolStripMenuItem.Enabled = saveStateToolStripMenuItem.Enabled = true; - //startRecordingToolStripMenuItem.Enabled = true; - //toggleLayersToolStripMenuItem.Enabled = enableChannelsToolStripMenuItem.Enabled = true; - - - //初始化不同平台的按钮 - mUniKeyboard.Init(emulatorHandler.emulator); - - emulatorHandler.Startup(); - - - //初始化音频 - soundHandler.Initialize(); - - //SizeAndPositionWindow(); - //SetWindowTitleAndStatus(); - - EssgeeLogger.EnqueueMessage($"Loaded '{lastGameMetadata?.KnownName ?? "unrecognized game"}'."); - - return true; - } - catch (Exception ex) when (!AppEnvironment.DebugMode) - { - ExceptionHandler(ex); - return false; - } - } - private void InitializeEmulation(Type machineType) - { - if (emulatorHandler != null) - ShutdownEmulation(); - - emulatorHandler = new Essgee.Emulation.EmulatorHandler(machineType, ExceptionHandler, uegSaveByteConvert); - emulatorHandler.Initialize(); - - emulatorHandler.SendLogMessage += EmulatorHandler_SendLogMessage; - emulatorHandler.EmulationReset += EmulatorHandler_EmulationReset; - emulatorHandler.RenderScreen += EmulatorHandler_RenderScreen; - emulatorHandler.SizeScreen += EmulatorHandler_SizeScreen; - emulatorHandler.ChangeViewport += EmulatorHandler_ChangeViewport; - emulatorHandler.PollInput += EmulatorHandler_PollInput; - emulatorHandler.EnqueueSamples += EnqueueSoundSamples; - emulatorHandler.SaveExtraData += EmulatorHandler_SaveExtraData; - emulatorHandler.EnableRumble += EmulatorHandler_EnableRumble; - emulatorHandler.PauseChanged += EmulatorHandler_PauseChanged; - - //emulatorHandler.EnqueueSamples += soundDebuggerForm.EnqueueSamples; - - emulatorHandler.SetFpsLimiting(EmuStandInfo.Configuration.LimitFps); - - emulatorHandler.SetConfiguration(EmuStandInfo.Configuration.Machines[machineType.Name]); - - currentPixelAspectRatio = emulatorHandler.Information.PixelAspectRatio; - - //pauseToolStripMenuItem.DataBindings.Clear(); - //pauseToolStripMenuItem.CheckedChanged += (s, e) => - //{ - // var pauseState = (s as ToolStripMenuItem).Checked; - - // emulatorHandler.Pause(pauseState); - // lastUserPauseState = pauseState; - //}; - - EssgeeLogger.EnqueueMessageSuccess($"{emulatorHandler.Information.Manufacturer} {emulatorHandler.Information.Model} emulation initialized."); - } - - - private void ExceptionHandler(Exception ex) - { - //this.CheckInvokeMethod(() => - //{ - if (!AppEnvironment.TemporaryDisableCustomExceptionForm) - { - //TODO debug窗口? - //(_, ExceptionResult result, string prefix, string postfix) = ExceptionForm.GetExceptionInfo(ex); - - //if (result == ExceptionResult.Continue) - //{ - // //MessageBox.Show($"{prefix}{ex.InnerException?.Message ?? ex.Message}\n\n{postfix}.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); - // EssgeeLogger.Err($"{prefix}{ex.InnerException?.Message ?? ex.Message}\n\n{postfix}."); - //} - //else - //{ - // //var exceptionForm = new ExceptionForm(ex) { Owner = this }; - // //exceptionForm.ShowDialog(); - - // switch (result) - // { - // case ExceptionResult.StopEmulation: - // SignalStopEmulation(); - // break; - - // case ExceptionResult.ExitApplication: - // Environment.Exit(-1); - // break; - // } - //} - } - else - { - var exceptionInfoBuilder = new StringBuilder(); - exceptionInfoBuilder.AppendLine($"Thread: {ex.Data["Thread"] ?? ""}"); - exceptionInfoBuilder.AppendLine($"Function: {ex.TargetSite.ReflectedType.FullName}.{ex.TargetSite.Name}"); - exceptionInfoBuilder.AppendLine($"Exception: {ex.GetType().Name}"); - exceptionInfoBuilder.Append($"Message: {ex.Message}"); - - var isUnhandled = Convert.ToBoolean(ex.Data["IsUnhandled"]); - - if (!isUnhandled && ex is CartridgeLoaderException) - { - //MessageBox.Show($"{ex.InnerException?.Message ?? ex.Message}\n\nFailed to load cartridge.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); - EssgeeLogger.Err($"{ex.InnerException?.Message ?? ex.Message}\n\nFailed to load cartridge."); - } - else if (!isUnhandled && ex is EmulationException) - { - //MessageBox.Show($"An emulation exception has occured!\n\n{exceptionInfoBuilder.ToString()}\n\nEmulation cannot continue and will be terminated.", "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error); - EssgeeLogger.Err($"An emulation exception has occured!\n\n{exceptionInfoBuilder.ToString()}\n\nEmulation cannot continue and will be terminated."); - SignalStopEmulation(); - } - else - { - var errorBuilder = new StringBuilder(); - errorBuilder.AppendLine("An unhandled exception has occured!"); - errorBuilder.AppendLine(); - errorBuilder.AppendLine(exceptionInfoBuilder.ToString()); - errorBuilder.AppendLine(); - errorBuilder.AppendLine("Exception occured:"); - errorBuilder.AppendLine($"{ex.StackTrace}"); - errorBuilder.AppendLine(); - errorBuilder.AppendLine("Execution cannot continue and the application will be terminated."); - - //EssgeeLogger.Err(errorBuilder.ToString(), "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error); - EssgeeLogger.Err(errorBuilder.ToString()); - - Environment.Exit(-1); - } - } - //}); - } - - - - private void SignalStopEmulation() - { - ShutdownEmulation(); - - lastGameMetadata = null; - - //takeScreenshotToolStripMenuItem.Enabled = pauseToolStripMenuItem.Enabled = resetToolStripMenuItem.Enabled = stopToolStripMenuItem.Enabled = false; - //loadStateToolStripMenuItem.Enabled = saveStateToolStripMenuItem.Enabled = false; - //startRecordingToolStripMenuItem.Enabled = false; - //toggleLayersToolStripMenuItem.Enabled = enableChannelsToolStripMenuItem.Enabled = false; - - //SetWindowTitleAndStatus(); - } - - private void ShutdownEmulation() - { - if (emulatorHandler == null) return; - - emulatorHandler.SaveCartridge(); - - emulatorHandler.SendLogMessage -= EmulatorHandler_SendLogMessage; - emulatorHandler.EmulationReset -= EmulatorHandler_EmulationReset; - emulatorHandler.RenderScreen -= EmulatorHandler_RenderScreen; - emulatorHandler.SizeScreen -= EmulatorHandler_SizeScreen; - emulatorHandler.ChangeViewport -= EmulatorHandler_ChangeViewport; - emulatorHandler.PollInput -= EmulatorHandler_PollInput; - emulatorHandler.EnqueueSamples -= EnqueueSoundSamples; - emulatorHandler.SaveExtraData -= EmulatorHandler_SaveExtraData; - emulatorHandler.EnableRumble -= EmulatorHandler_EnableRumble; - emulatorHandler.PauseChanged -= EmulatorHandler_PauseChanged; - - //emulatorHandler.EnqueueSamples -= soundDebuggerForm.EnqueueSamples; - - emulatorHandler.Shutdown(); - while (emulatorHandler.IsRunning) { } - - emulatorHandler = null; - GC.Collect(); - - EssgeeLogger.WriteLine("Emulation stopped."); - } - #endregion - - #region 模拟器内部事件 - - private void EmulatorHandler_SendLogMessage(object sender, SendLogMessageEventArgs e) - { - //this.CheckInvokeMethod(delegate () { onScreenDisplayHandler.EnqueueMessageCore($"{emulatorHandler.Information.Model}: {e.Message}"); }); - //TODO log - EssgeeLogger.EnqueueMessageSuccess($"{emulatorHandler.Information.Model}: {e.Message}"); - } - - private void EmulatorHandler_EmulationReset(object sender, EventArgs e) - { - //this.CheckInvokeMethod(delegate () { onScreenDisplayHandler.EnqueueMessage("Emulation reset."); }); - EssgeeLogger.EnqueueMessageSuccess("Emulation reset."); - } - - private void EmulatorHandler_RenderScreen(object sender, RenderScreenEventArgs e) - { - //this.CheckInvokeMethod(delegate () - //{ - - //if (e.Width != lastFramebufferSize.width || e.Height != lastFramebufferSize.height) - //{ - // lastFramebufferSize = (e.Width, e.Height); - // graphicsHandler?.SetTextureSize(e.Width, e.Height); - //} - //lastFramebufferData = e.FrameData; - //graphicsHandler?.SetTextureData(e.FrameData); - - //graphicsHandler.SubmitVideo(e.Width, e.Height, e.FrameData, 0); - graphicsHandler.SubmitVideo(e.Width, e.Height, e.FrameDataPtr, 0); - - // TODO: create emulation "EndOfFrame" event for this? - //ControllerManager.Update(); - //}); - } - - private void EmulatorHandler_SizeScreen(object sender, SizeScreenEventArgs e) - { - //TODO 待实现 屏幕大小 - - //this.CheckInvokeMethod(delegate () - //{ - // lastFramebufferSize = (e.Width, e.Height); - // graphicsHandler?.SetTextureSize(e.Width, e.Height); - //}); - } - - private void EmulatorHandler_ChangeViewport(object sender, ChangeViewportEventArgs e) - { - //TODO 待实现 - - //this.CheckInvokeMethod(delegate () - //{ - // graphicsHandler?.SetScreenViewport(currentViewport = e.Viewport); - // SizeAndPositionWindow(); - //}); - } - - private void EmulatorHandler_PollInput(object sender, PollInputEventArgs e) - { - //TODO Input实现 - - //e.Keyboard = mUniKeyboard.mKeyCodeCore.GetPressedKeys(); - e.Keyboard.AddRange(mUniKeyboard.GetPressedKeys()); - e.MouseButtons = default; - e.MousePosition = default; - - // TODO: rare, random, weird argument exceptions on e.Keyboard assignment; does this lock help?? - //lock (uiLock) - //{ - // e.Keyboard = new List(keysDown); - // e.MouseButtons = mouseButtonsDown; - - // var vx = (currentViewport.x - 50); - // var dvx = renderControl.ClientSize.Width / (currentViewport.width - (double)vx); - // var dvy = renderControl.ClientSize.Height / (currentViewport.height - (double)currentViewport.y); - // e.MousePosition = ((int)(mousePosition.x / dvx) - vx, (int)(mousePosition.y / dvy) - currentViewport.y); - - // if (EmuStandInfo.Configuration.EnableXInput) - // e.ControllerState = ControllerManager.GetController(0).GetControllerState(); - //} - } - - private void EmulatorHandler_SaveExtraData(object sender, SaveExtraDataEventArgs e) - { - /* Extract options etc. */ - var includeDateTime = e.Options.HasFlag(ExtraDataOptions.IncludeDateTime); - var allowOverwrite = e.Options.HasFlag(ExtraDataOptions.AllowOverwrite); - - var extension = string.Empty; - switch (e.DataType) - { - case ExtraDataTypes.Image: extension = "png"; break; - case ExtraDataTypes.Raw: extension = "bin"; break; - default: throw new EmulationException($"Unknown extra data type {e.DataType}"); - } - - /* Generate filename/path */ - var filePrefix = $"{System.IO.Path.GetFileNameWithoutExtension(lastGameMetadata.FileName)} ({e.Description}{(includeDateTime ? $" {DateTime.Now:yyyy-MM-dd HH-mm-ss})" : ")")}"; - var filePath = System.IO.Path.Combine(EmuStandInfo.ExtraDataPath, $"{filePrefix}.{extension}"); - if (!allowOverwrite) - { - var existingFiles = AxiIO.Directory.EnumerateFiles(EmuStandInfo.ExtraDataPath, $"{filePrefix}*{extension}"); - if (existingFiles.Contains(filePath)) - for (int i = 2; existingFiles.Contains(filePath = System.IO.Path.Combine(EmuStandInfo.ExtraDataPath, $"{filePrefix} ({i}).{extension}")); i++) { } - } - - /* Handle data */ - //if (e.Data is Bitmap image) - if (e.DataType == ExtraDataTypes.Image) - { - /* Images, ex. GB Printer printouts */ - //image.Save(filePath); - - //TODO 图像存储 - } - else if (e.Data is byte[] raw) - { - /* Raw bytes */ - //using (var file = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) - //{ - // file.Write(raw, 0, raw.Length); - //} - - AxiIO.File.WriteAllBytes(filePath, raw); - } - } - - private void EmulatorHandler_EnableRumble(object sender, EventArgs e) - { - //if (EmuStandInfo.Configuration.EnableXInput && EmuStandInfo.Configuration.EnableRumble) - // ControllerManager.GetController(0).Vibrate(0.0f, 0.5f, TimeSpan.FromSeconds(0.1f)); - } - - private void EmulatorHandler_PauseChanged(object sender, EventArgs e) - { - //SetWindowTitleAndStatus(); - - if (emulatorHandler.IsPaused) - { - //TODO 音频暂停? - //soundHandler?.ClearSampleBuffer(); - } - } - - public unsafe void EnqueueSoundSamples(object sender, EnqueueSamplesEventArgs e) - { - //if (sampleQueue.Count > MaxQueueLength) - //{ - // var samplesToDrop = (sampleQueue.Count - MaxQueueLength); - // onScreenDisplayHandler.EnqueueMessageDebug($"({GetType().Name}/{DateTime.Now.Second:D2}s) Sample queue overflow; dropping {samplesToDrop} of {sampleQueue.Count} samples."); - // for (int i = 0; i < samplesToDrop; i++) - // if (sampleQueue.Count != 0) - // sampleQueue.Dequeue(); - //} - - //sampleQueue.Enqueue(e.MixedSamples.ToArray()); - - //if (IsRecording) - //{ - // dataChunk.AddSampleData(e.MixedSamples); - // waveHeader.FileLength += (uint)e.MixedSamples.Length; - //} - - //TODO 音频处理 - //soundHandler.SubmitSamples(e.MixedSamples, e.ChannelSamples, e.MixedSamples.Length); - soundHandler.SubmitSamples(e.MixedSamples, e.ChannelSamples, e.MixedSamplesLength); - } - - - #endregion -} - + + protected override void AfterPushFrame() + { + } + + public override void GetAudioParams(out int frequency, out int channels) + { + frequency = soundHandler.sampleRate; + channels = soundHandler.channle; + } + #endregion + + void InitAll(IGameMetaReources metaresources, IEssgeeIOSupport uegIO, string CustonDataDir) + { + //初始化配置 + InitAppEnvironment(CustonDataDir, uegIO); + InitEmu(); + //细节初始化 + InitializeHandlers(metaresources); + } + + private void InitAppEnvironment(string CustonDataDir, IEssgeeIOSupport uegIO) + { + Essgee.Emulation.EmulatorHandler.io = uegIO; + EssgeeLogger.Init(uegLog); + + //EmuStandInfo.datDirectoryPath = Path.Combine(BaseDataDir, "EssgeeAssets", "No-Intro"); + //EmuStandInfo.metadataDatabaseFilePath = Path.Combine(BaseDataDir, "EssgeeAssets", "MetadataDatabase.json"); + + EmuStandInfo.jsonConfigFileName = "Config.json"; + EmuStandInfo.saveDataDirectoryName = "Saves"; + EmuStandInfo.screenshotDirectoryName = "Screenshots"; + EmuStandInfo.saveStateDirectoryName = "Savestates"; + EmuStandInfo.extraDataDirectoryName = "Extras"; + EmuStandInfo.ProductName = "AxibugEmu"; + EmuStandInfo.ProductVersion = ""; + + EmuStandInfo.programDataDirectory = System.IO.Path.Combine(CustonDataDir, EmuStandInfo.ProductName); + EmuStandInfo.programConfigPath = System.IO.Path.Combine(EmuStandInfo.programDataDirectory, EmuStandInfo.jsonConfigFileName); + + EmuStandInfo.ShaderPath = System.IO.Path.Combine(CustonDataDir, "Assets", "Shaders"); + EmuStandInfo.SaveDataPath = System.IO.Path.Combine(EmuStandInfo.programDataDirectory, EmuStandInfo.saveDataDirectoryName); + EmuStandInfo.ScreenshotPath = System.IO.Path.Combine(EmuStandInfo.programDataDirectory, EmuStandInfo.screenshotDirectoryName); + EmuStandInfo.SaveStatePath = System.IO.Path.Combine(EmuStandInfo.programDataDirectory, EmuStandInfo.saveStateDirectoryName); + EmuStandInfo.ExtraDataPath = System.IO.Path.Combine(EmuStandInfo.programDataDirectory, EmuStandInfo.extraDataDirectoryName); + + LoadConfiguration(); + + + if (!AxiIO.Directory.Exists(EmuStandInfo.SaveDataPath)) + AxiIO.Directory.CreateDirectory(EmuStandInfo.SaveDataPath); + + if (!AxiIO.Directory.Exists(EmuStandInfo.ScreenshotPath)) + AxiIO.Directory.CreateDirectory(EmuStandInfo.ScreenshotPath); + + if (!AxiIO.Directory.Exists(EmuStandInfo.SaveStatePath)) + AxiIO.Directory.CreateDirectory(EmuStandInfo.SaveStatePath); + + if (!AxiIO.Directory.Exists(EmuStandInfo.ExtraDataPath)) + AxiIO.Directory.CreateDirectory(EmuStandInfo.ExtraDataPath); + + if (AppEnvironment.EnableLogger) + { + //TODO 关闭Debug + //Logger.Flush(); + //Logger.Close(); + } + } + + void InitEmu() + { + //keysDown = new List(); + } + + #region 细节初始化 + + private void InitializeHandlers(IGameMetaReources metaresources) + { + InitializeOSDHandler(); + InitializeGraphicsHandler(); + InitializeSoundHandler(); + InitializeMetadataHandler(metaresources); + + mUniKeyboard = this.gameObject.AddComponent(); + } + + private void InitializeOSDHandler() + { + + //var osdFontText = Assembly.GetExecutingAssembly().ReadEmbeddedImageFile($"{Application.ProductName}.Assets.OsdFont.png"); + //onScreenDisplayHandler = new OnScreenDisplayHandler(osdFontText); + + //onScreenDisplayHandler?.EnqueueMessageDebug($"Hello from {GetProductNameAndVersionString(true)}, this is a debug build!\nOSD handler initialized; font bitmap is {osdFontText.Width}x{osdFontText.Height}."); + + //if (onScreenDisplayHandler == null) throw new HandlerException("Failed to initialize OSD handler"); + } + + private void InitializeGraphicsHandler() + { + graphicsHandler = this.gameObject.GetComponent(); + //graphicsHandler = new GraphicsHandler(onScreenDisplayHandler); + //graphicsHandler?.LoadShaderBundle(Program.Configuration.LastShader); + } + + private void InitializeSoundHandler() + { + soundHandler = this.gameObject.GetComponent(); + //soundHandler = new SoundHandler(onScreenDisplayHandler, Program.Configuration.SampleRate, 2, ExceptionHandler); + //soundHandler.SetVolume(Program.Configuration.Volume); + //soundHandler.SetMute(Program.Configuration.Mute); + //soundHandler.SetLowPassFilter(Program.Configuration.LowPassFilter); + //soundHandler.Startup(); + } + + private void InitializeMetadataHandler(IGameMetaReources metaresources) + { + //gameMetadataHandler = new GameMetadataHandler(onScreenDisplayHandler); + gameMetadataHandler = new GameMetadataHandler(metaresources); + } + #endregion + void Dispose(bool disposing) + { + //TODO 释放时 + //if (disposing) + //{ + // if (components != null) components.Dispose(); + + // if (onScreenDisplayHandler != null) onScreenDisplayHandler.Dispose(); + // if (graphicsHandler != null) graphicsHandler.Dispose(); + // if (soundHandler != null) soundHandler.Dispose(); + //} + + //base.Dispose(disposing); + } + #region 配置 + private static void LoadConfiguration() + { + //TODO 暂时跳过这里的配置加载 + //Directory.CreateDirectory(EmuStandInfo.programDataDirectory); + //if (!File.Exists(EmuStandInfo.programConfigPath) || (EmuStandInfo.Configuration = EmuStandInfo.programConfigPath.DeserializeFromFile()) == null) + //{ + // EmuStandInfo.Configuration = new Configuration(); + // EmuStandInfo.Configuration.SerializeToFile(EmuStandInfo.programConfigPath); + //} + + EmuStandInfo.Configuration = new Essgee.Configuration(); + + List machineType = new List(); + machineType.Add(typeof(GameBoy)); + machineType.Add(typeof(GameBoyColor)); + machineType.Add(typeof(ColecoVision)); + machineType.Add(typeof(GameGear)); + machineType.Add(typeof(MasterSystem)); + machineType.Add(typeof(SC3000)); + machineType.Add(typeof(SG1000)); + + //foreach (var machineConfigType in Assembly.GetExecutingAssembly().GetTypes().Where(x => typeof(IConfiguration).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract)) + foreach (var machineConfigType in machineType) + { + if (!EmuStandInfo.Configuration.Machines.ContainsKey(machineConfigType.Name)) + EmuStandInfo.Configuration.Machines.Add(machineConfigType.Name, (IConfiguration)Activator.CreateInstance(machineConfigType)); + } + + //foreach (var debuggerFormType in Assembly.GetExecutingAssembly().GetTypes().Where(x => typeof(IDebuggerForm).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract)) + //{ + // if (!StandInfo.Configuration.DebugWindows.ContainsKey(debuggerFormType.Name)) + // StandInfo.Configuration.DebugWindows.Add(debuggerFormType.Name, Point.Empty); + //} + } + + private void ApplyConfigOverrides(Type machineType) + { + var forcePowerOnWithoutCart = false; + var hasTVStandardOverride = false; + var hasRegionOverride = false; + var hasDisallowMemoryControlOverride = false; + + var overrideConfig = EmuStandInfo.Configuration.Machines[machineType.Name].CloneObject(); + + if (lastGameMetadata == null) + { + var property = overrideConfig.GetType().GetProperty("UseBootstrap"); + if (property != null && (bool)property.GetValue(overrideConfig) != true) + { + property.SetValue(overrideConfig, true); + forcePowerOnWithoutCart = true; + } + } + + if (lastGameMetadata != null && lastGameMetadata.PreferredTVStandard != TVStandard.Auto) + { + var property = overrideConfig.GetType().GetProperty("TVStandard"); + if (property != null) + { + property.SetValue(overrideConfig, lastGameMetadata.PreferredTVStandard); + hasTVStandardOverride = true; + } + } + + if (lastGameMetadata != null && lastGameMetadata.PreferredRegion != Essgee.Emulation.Region.Auto) + { + var property = overrideConfig.GetType().GetProperty("Region"); + if (property != null) + { + property.SetValue(overrideConfig, lastGameMetadata.PreferredRegion); + hasRegionOverride = true; + } + } + + if (lastGameMetadata != null && lastGameMetadata.AllowMemoryControl != true) + { + var propertyMem = overrideConfig.GetType().GetProperty("AllowMemoryControl"); + if (propertyMem != null) + { + propertyMem.SetValue(overrideConfig, lastGameMetadata.AllowMemoryControl); + hasDisallowMemoryControlOverride = true; + + var propertyBoot = overrideConfig.GetType().GetProperty("UseBootstrap"); + if (propertyBoot != null) + { + propertyBoot.SetValue(overrideConfig, false); + } + } + } + + if (forcePowerOnWithoutCart) + EssgeeLogger.EnqueueMessageWarning("Bootstrap ROM is disabled in settings; enabling it for this startup."); + + if (hasTVStandardOverride) + EssgeeLogger.EnqueueMessageWarning($"Overriding TV standard setting; running game as {lastGameMetadata?.PreferredTVStandard}."); + + if (hasRegionOverride) + EssgeeLogger.EnqueueMessageWarning($"Overriding region setting; running game as {lastGameMetadata?.PreferredRegion}."); + + if (hasDisallowMemoryControlOverride) + EssgeeLogger.EnqueueMessageWarning("Game-specific hack: Preventing software from reconfiguring memory control.\nBootstrap ROM has been disabled for this startup due to memory control hack."); + + if (forcePowerOnWithoutCart || hasTVStandardOverride || hasRegionOverride || hasDisallowMemoryControlOverride) + emulatorHandler.SetConfiguration(overrideConfig); + } + public static void SaveConfiguration() + { + //不用保存这个配置 + //EmuStandInfo.Configuration.SerializeToFile(EmuStandInfo.programConfigPath); + } + #endregion + + #region 模拟器基本设置 + + public void SetEmuFpsLimit(bool bOpen) + { + emulatorHandler?.SetFpsLimiting(bOpen); + } + public void SetSoundMute(bool bOpen) + { + //soundHandler?.SetMute(Program.Configuration.Mute); + } + public void SetSoundLowPassFilter(bool bOpen) + { + //soundHandler?.SetLowPassFilter(Program.Configuration.LowPassFilter);; + } + public void SetTemporaryPause(bool newTemporaryPauseState) + { + if (emulatorHandler == null || !emulatorHandler.IsRunning || !EmuStandInfo.Configuration.AutoPause) return; + + if (newTemporaryPauseState) + emulatorHandler.Pause(true); + else if (!lastUserPauseState) + emulatorHandler.Pause(false); + } + #endregion + + #region 模拟器生命周期 + + + private void PowerOnWithoutCartridge(Type machineType) + { + //TODO IsRecording?? 可能需要实现 + //if (soundHandler.IsRecording) + // soundHandler.CancelRecording(); + + InitializeEmulation(machineType); + + lastGameMetadata = null; + + ApplyConfigOverrides(machineType); + + + emulatorHandler.Startup(); + + EssgeeLogger.EnqueueMessageSuccess("Power on without cartridge."); + } + + + private bool LoadAndRunCartridge(string fileName) + { + try + { + + var (machineType, romData) = CartridgeLoader.Load(fileName, "ROM image"); + + //TODO IsRecording?? 可能需要实现 + //if (soundHandler.IsRecording) + // soundHandler.CancelRecording(); + + + InitializeEmulation(machineType); + + lastGameMetadata = gameMetadataHandler.GetGameMetadata(emulatorHandler.Information.DatFileName, fileName, Crc32.Calculate(romData), romData.Length); + + ApplyConfigOverrides(machineType); + + emulatorHandler.LoadCartridge(romData, lastGameMetadata); + + //AddToRecentFiles(fileName); + //CreateRecentFilesMenu(); + //CreateLoadSaveStateMenus(); + //CreateToggleGraphicsLayersMenu(); + //CreateToggleSoundChannelsMenu(); + + //takeScreenshotToolStripMenuItem.Enabled = pauseToolStripMenuItem.Enabled = resetToolStripMenuItem.Enabled = stopToolStripMenuItem.Enabled = true; + //loadStateToolStripMenuItem.Enabled = saveStateToolStripMenuItem.Enabled = true; + //startRecordingToolStripMenuItem.Enabled = true; + //toggleLayersToolStripMenuItem.Enabled = enableChannelsToolStripMenuItem.Enabled = true; + + + //初始化不同平台的按钮 + mUniKeyboard.Init(emulatorHandler.emulator); + + emulatorHandler.Startup(); + + + //初始化音频 + soundHandler.Initialize(); + + //SizeAndPositionWindow(); + //SetWindowTitleAndStatus(); + + EssgeeLogger.EnqueueMessage($"Loaded '{lastGameMetadata?.KnownName ?? "unrecognized game"}'."); + + return true; + } + catch (Exception ex) when (!AppEnvironment.DebugMode) + { + ExceptionHandler(ex); + return false; + } + } + private void InitializeEmulation(Type machineType) + { + if (emulatorHandler != null) + ShutdownEmulation(); + + emulatorHandler = new Essgee.Emulation.EmulatorHandler(machineType, ExceptionHandler, uegSaveByteConvert); + emulatorHandler.Initialize(); + + emulatorHandler.SendLogMessage += EmulatorHandler_SendLogMessage; + emulatorHandler.EmulationReset += EmulatorHandler_EmulationReset; + emulatorHandler.RenderScreen += EmulatorHandler_RenderScreen; + emulatorHandler.SizeScreen += EmulatorHandler_SizeScreen; + emulatorHandler.ChangeViewport += EmulatorHandler_ChangeViewport; + emulatorHandler.PollInput += EmulatorHandler_PollInput; + emulatorHandler.EnqueueSamples += EnqueueSoundSamples; + emulatorHandler.SaveExtraData += EmulatorHandler_SaveExtraData; + emulatorHandler.EnableRumble += EmulatorHandler_EnableRumble; + emulatorHandler.PauseChanged += EmulatorHandler_PauseChanged; + + //emulatorHandler.EnqueueSamples += soundDebuggerForm.EnqueueSamples; + + emulatorHandler.SetFpsLimiting(EmuStandInfo.Configuration.LimitFps); + + emulatorHandler.SetConfiguration(EmuStandInfo.Configuration.Machines[machineType.Name]); + + currentPixelAspectRatio = emulatorHandler.Information.PixelAspectRatio; + + //pauseToolStripMenuItem.DataBindings.Clear(); + //pauseToolStripMenuItem.CheckedChanged += (s, e) => + //{ + // var pauseState = (s as ToolStripMenuItem).Checked; + + // emulatorHandler.Pause(pauseState); + // lastUserPauseState = pauseState; + //}; + + EssgeeLogger.EnqueueMessageSuccess($"{emulatorHandler.Information.Manufacturer} {emulatorHandler.Information.Model} emulation initialized."); + } + + + private void ExceptionHandler(Exception ex) + { + //this.CheckInvokeMethod(() => + //{ + if (!AppEnvironment.TemporaryDisableCustomExceptionForm) + { + //TODO debug窗口? + //(_, ExceptionResult result, string prefix, string postfix) = ExceptionForm.GetExceptionInfo(ex); + + //if (result == ExceptionResult.Continue) + //{ + // //MessageBox.Show($"{prefix}{ex.InnerException?.Message ?? ex.Message}\n\n{postfix}.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); + // EssgeeLogger.Err($"{prefix}{ex.InnerException?.Message ?? ex.Message}\n\n{postfix}."); + //} + //else + //{ + // //var exceptionForm = new ExceptionForm(ex) { Owner = this }; + // //exceptionForm.ShowDialog(); + + // switch (result) + // { + // case ExceptionResult.StopEmulation: + // SignalStopEmulation(); + // break; + + // case ExceptionResult.ExitApplication: + // Environment.Exit(-1); + // break; + // } + //} + } + else + { + var exceptionInfoBuilder = new StringBuilder(); + exceptionInfoBuilder.AppendLine($"Thread: {ex.Data["Thread"] ?? ""}"); + exceptionInfoBuilder.AppendLine($"Function: {ex.TargetSite.ReflectedType.FullName}.{ex.TargetSite.Name}"); + exceptionInfoBuilder.AppendLine($"Exception: {ex.GetType().Name}"); + exceptionInfoBuilder.Append($"Message: {ex.Message}"); + + var isUnhandled = Convert.ToBoolean(ex.Data["IsUnhandled"]); + + if (!isUnhandled && ex is CartridgeLoaderException) + { + //MessageBox.Show($"{ex.InnerException?.Message ?? ex.Message}\n\nFailed to load cartridge.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); + EssgeeLogger.Err($"{ex.InnerException?.Message ?? ex.Message}\n\nFailed to load cartridge."); + } + else if (!isUnhandled && ex is EmulationException) + { + //MessageBox.Show($"An emulation exception has occured!\n\n{exceptionInfoBuilder.ToString()}\n\nEmulation cannot continue and will be terminated.", "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error); + EssgeeLogger.Err($"An emulation exception has occured!\n\n{exceptionInfoBuilder.ToString()}\n\nEmulation cannot continue and will be terminated."); + SignalStopEmulation(); + } + else + { + var errorBuilder = new StringBuilder(); + errorBuilder.AppendLine("An unhandled exception has occured!"); + errorBuilder.AppendLine(); + errorBuilder.AppendLine(exceptionInfoBuilder.ToString()); + errorBuilder.AppendLine(); + errorBuilder.AppendLine("Exception occured:"); + errorBuilder.AppendLine($"{ex.StackTrace}"); + errorBuilder.AppendLine(); + errorBuilder.AppendLine("Execution cannot continue and the application will be terminated."); + + //EssgeeLogger.Err(errorBuilder.ToString(), "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error); + EssgeeLogger.Err(errorBuilder.ToString()); + + Environment.Exit(-1); + } + } + //}); + } + + + + private void SignalStopEmulation() + { + ShutdownEmulation(); + + lastGameMetadata = null; + + //takeScreenshotToolStripMenuItem.Enabled = pauseToolStripMenuItem.Enabled = resetToolStripMenuItem.Enabled = stopToolStripMenuItem.Enabled = false; + //loadStateToolStripMenuItem.Enabled = saveStateToolStripMenuItem.Enabled = false; + //startRecordingToolStripMenuItem.Enabled = false; + //toggleLayersToolStripMenuItem.Enabled = enableChannelsToolStripMenuItem.Enabled = false; + + //SetWindowTitleAndStatus(); + } + + private void ShutdownEmulation() + { + if (emulatorHandler == null) return; + + emulatorHandler.SaveCartridge(); + + emulatorHandler.SendLogMessage -= EmulatorHandler_SendLogMessage; + emulatorHandler.EmulationReset -= EmulatorHandler_EmulationReset; + emulatorHandler.RenderScreen -= EmulatorHandler_RenderScreen; + emulatorHandler.SizeScreen -= EmulatorHandler_SizeScreen; + emulatorHandler.ChangeViewport -= EmulatorHandler_ChangeViewport; + emulatorHandler.PollInput -= EmulatorHandler_PollInput; + emulatorHandler.EnqueueSamples -= EnqueueSoundSamples; + emulatorHandler.SaveExtraData -= EmulatorHandler_SaveExtraData; + emulatorHandler.EnableRumble -= EmulatorHandler_EnableRumble; + emulatorHandler.PauseChanged -= EmulatorHandler_PauseChanged; + + //emulatorHandler.EnqueueSamples -= soundDebuggerForm.EnqueueSamples; + + emulatorHandler.Shutdown(); + while (emulatorHandler.IsRunning) { } + + emulatorHandler = null; + GC.Collect(); + + EssgeeLogger.WriteLine("Emulation stopped."); + } + #endregion + + #region 模拟器内部事件 + + private void EmulatorHandler_SendLogMessage(object sender, SendLogMessageEventArgs e) + { + //this.CheckInvokeMethod(delegate () { onScreenDisplayHandler.EnqueueMessageCore($"{emulatorHandler.Information.Model}: {e.Message}"); }); + //TODO log + EssgeeLogger.EnqueueMessageSuccess($"{emulatorHandler.Information.Model}: {e.Message}"); + } + + private void EmulatorHandler_EmulationReset(object sender, EventArgs e) + { + //this.CheckInvokeMethod(delegate () { onScreenDisplayHandler.EnqueueMessage("Emulation reset."); }); + EssgeeLogger.EnqueueMessageSuccess("Emulation reset."); + } + + private void EmulatorHandler_RenderScreen(object sender, RenderScreenEventArgs e) + { + //this.CheckInvokeMethod(delegate () + //{ + + //if (e.Width != lastFramebufferSize.width || e.Height != lastFramebufferSize.height) + //{ + // lastFramebufferSize = (e.Width, e.Height); + // graphicsHandler?.SetTextureSize(e.Width, e.Height); + //} + //lastFramebufferData = e.FrameData; + //graphicsHandler?.SetTextureData(e.FrameData); + + //graphicsHandler.SubmitVideo(e.Width, e.Height, e.FrameData, 0); + graphicsHandler.SubmitVideo(e.Width, e.Height, e.FrameDataPtr, 0); + + // TODO: create emulation "EndOfFrame" event for this? + //ControllerManager.Update(); + //}); + } + + private void EmulatorHandler_SizeScreen(object sender, SizeScreenEventArgs e) + { + //TODO 待实现 屏幕大小 + + //this.CheckInvokeMethod(delegate () + //{ + // lastFramebufferSize = (e.Width, e.Height); + // graphicsHandler?.SetTextureSize(e.Width, e.Height); + //}); + } + + private void EmulatorHandler_ChangeViewport(object sender, ChangeViewportEventArgs e) + { + //TODO 待实现 + + //this.CheckInvokeMethod(delegate () + //{ + // graphicsHandler?.SetScreenViewport(currentViewport = e.Viewport); + // SizeAndPositionWindow(); + //}); + } + + private void EmulatorHandler_PollInput(object sender, PollInputEventArgs e) + { + //TODO Input实现 + + //e.Keyboard = mUniKeyboard.mKeyCodeCore.GetPressedKeys(); + e.Keyboard.AddRange(mUniKeyboard.GetPressedKeys()); + e.MouseButtons = default; + e.MousePosition = default; + + // TODO: rare, random, weird argument exceptions on e.Keyboard assignment; does this lock help?? + //lock (uiLock) + //{ + // e.Keyboard = new List(keysDown); + // e.MouseButtons = mouseButtonsDown; + + // var vx = (currentViewport.x - 50); + // var dvx = renderControl.ClientSize.Width / (currentViewport.width - (double)vx); + // var dvy = renderControl.ClientSize.Height / (currentViewport.height - (double)currentViewport.y); + // e.MousePosition = ((int)(mousePosition.x / dvx) - vx, (int)(mousePosition.y / dvy) - currentViewport.y); + + // if (EmuStandInfo.Configuration.EnableXInput) + // e.ControllerState = ControllerManager.GetController(0).GetControllerState(); + //} + } + + private void EmulatorHandler_SaveExtraData(object sender, SaveExtraDataEventArgs e) + { + /* Extract options etc. */ + var includeDateTime = e.Options.HasFlag(ExtraDataOptions.IncludeDateTime); + var allowOverwrite = e.Options.HasFlag(ExtraDataOptions.AllowOverwrite); + + var extension = string.Empty; + switch (e.DataType) + { + case ExtraDataTypes.Image: extension = "png"; break; + case ExtraDataTypes.Raw: extension = "bin"; break; + default: throw new EmulationException($"Unknown extra data type {e.DataType}"); + } + + /* Generate filename/path */ + var filePrefix = $"{System.IO.Path.GetFileNameWithoutExtension(lastGameMetadata.FileName)} ({e.Description}{(includeDateTime ? $" {DateTime.Now:yyyy-MM-dd HH-mm-ss})" : ")")}"; + var filePath = System.IO.Path.Combine(EmuStandInfo.ExtraDataPath, $"{filePrefix}.{extension}"); + if (!allowOverwrite) + { + var existingFiles = AxiIO.Directory.EnumerateFiles(EmuStandInfo.ExtraDataPath, $"{filePrefix}*{extension}"); + if (existingFiles.Contains(filePath)) + for (int i = 2; existingFiles.Contains(filePath = System.IO.Path.Combine(EmuStandInfo.ExtraDataPath, $"{filePrefix} ({i}).{extension}")); i++) { } + } + + /* Handle data */ + //if (e.Data is Bitmap image) + if (e.DataType == ExtraDataTypes.Image) + { + /* Images, ex. GB Printer printouts */ + //image.Save(filePath); + + //TODO 图像存储 + } + else if (e.Data is byte[] raw) + { + /* Raw bytes */ + //using (var file = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) + //{ + // file.Write(raw, 0, raw.Length); + //} + + AxiIO.File.WriteAllBytes(filePath, raw); + } + } + + private void EmulatorHandler_EnableRumble(object sender, EventArgs e) + { + //if (EmuStandInfo.Configuration.EnableXInput && EmuStandInfo.Configuration.EnableRumble) + // ControllerManager.GetController(0).Vibrate(0.0f, 0.5f, TimeSpan.FromSeconds(0.1f)); + } + + private void EmulatorHandler_PauseChanged(object sender, EventArgs e) + { + //SetWindowTitleAndStatus(); + + if (emulatorHandler.IsPaused) + { + //TODO 音频暂停? + //soundHandler?.ClearSampleBuffer(); + } + } + + public unsafe void EnqueueSoundSamples(object sender, EnqueueSamplesEventArgs e) + { + //if (sampleQueue.Count > MaxQueueLength) + //{ + // var samplesToDrop = (sampleQueue.Count - MaxQueueLength); + // onScreenDisplayHandler.EnqueueMessageDebug($"({GetType().Name}/{DateTime.Now.Second:D2}s) Sample queue overflow; dropping {samplesToDrop} of {sampleQueue.Count} samples."); + // for (int i = 0; i < samplesToDrop; i++) + // if (sampleQueue.Count != 0) + // sampleQueue.Dequeue(); + //} + + //sampleQueue.Enqueue(e.MixedSamples.ToArray()); + + //if (IsRecording) + //{ + // dataChunk.AddSampleData(e.MixedSamples); + // waveHeader.FileLength += (uint)e.MixedSamples.Length; + //} + + //TODO 音频处理 + //soundHandler.SubmitSamples(e.MixedSamples, e.ChannelSamples, e.MixedSamples.Length); + soundHandler.SubmitSamples(e.MixedSamples, e.ChannelSamples, e.MixedSamplesLength); + } + + + #endregion +} + diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UMAME.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UMAME.cs index 13e0eb28..5a5dfbf3 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UMAME.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UMAME.cs @@ -1,161 +1,161 @@ -using AxibugEmuOnline.Client; -using AxibugEmuOnline.Client.ClientCore; -using AxibugProtobuf; -using AxiReplay; -using MAME.Core; -using System; -using System.Collections.Generic; -using System.Text; -using UnityEngine; -using UnityEngine.UI; - -public class UMAME : EmuCore -{ - public static UMAME instance { get; private set; } - public MAMEEmu emu { get; private set; } - UniLog mUniLog; - UniMouse mUniMouse; - [HideInInspector] - public UniVideoPlayer mUniVideoPlayer; - UniSoundPlayer mUniSoundPlayer; - UniKeyboard mUniKeyboard; - UniResources mUniResources; - UniIO mUniIO; - - public Text mFPS; - private Canvas mCanvas; - public List HadGameList = new List(); - string mChangeRomName = string.Empty; - public UniTimeSpan mTimeSpan; - public bool bQuickTestRom = false; - public string mQuickTestRom = string.Empty; - public ReplayWriter mReplayWriter; - public ReplayReader mReplayReader; - public long currEmuFrame => emu.currEmuFrame; - public static System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew(); - public static bool bInGame { get; private set; } - public static bool bLogicUpdatePause { get; private set; } - public string EmuDataPath { get { return App.PersistentDataPath(Platform); } } - public string RomPath => EmuDataPath + "/RemoteRoms/"; - public string SavePath => EmuDataPath + "/sav/"; - public override RomPlatformType Platform { get { return mPlatform; } } - RomPlatformType mPlatform = RomPlatformType.Cps1; - public override uint Frame => (uint)emu.currEmuFrame; - void Awake() - { - instance = this; - mFPS = GameObject.Find("FPS").GetComponent(); - mCanvas = GameObject.Find("Canvas").GetComponent(); - mCanvas.worldCamera = Camera.main; - emu = new MAMEEmu(); - mUniLog = new UniLog(); - mUniMouse = this.gameObject.AddComponent(); - mUniVideoPlayer = this.gameObject.AddComponent(); - mUniSoundPlayer = GameObject.Find("Audio").transform.GetComponent(); - mUniKeyboard = this.gameObject.AddComponent(); - mUniResources = new UniResources(); - mUniIO = new UniIO(); - mChangeRomName = string.Empty; - mTimeSpan = new UniTimeSpan(); - emu.Init(RomPath, mUniLog, mUniResources, mUniVideoPlayer, mUniSoundPlayer, mUniKeyboard, mUniMouse, mTimeSpan, mUniIO); - } - void OnEnable() - { - } - void OnDisable() - { - StopGame(); - } - #region 实现接口 - public override object GetState() - { - return SaveState(); - } - public override byte[] GetStateBytes() - { - return SaveState(); - } - public override void LoadState(object state) - { - LoadState((byte[])state); - } - public override void LoadStateFromBytes(byte[] data) - { - LoadState(data); - } - public override void Pause() - { - bLogicUpdatePause = false; - } - public override void Resume() - { - bLogicUpdatePause = true; - } - public override MsgBool StartGame(RomFile romFile) - { - mPlatform = romFile.Platform; - mTimeSpan.InitStandTime(); - if (LoadGame(romFile.FileName)) - return true; - else - return "Rom加载失败"; - } - public override void Dispose() - { - StopGame(); - } - public override void DoReset() - { - StopGame(); - LoadGame(mChangeRomName); - } - public override IControllerSetuper GetControllerSetuper() - { - return mUniKeyboard.ControllerMapper; +using AxibugEmuOnline.Client; +using AxibugEmuOnline.Client.ClientCore; +using AxibugProtobuf; +using AxiReplay; +using MAME.Core; +using System; +using System.Collections.Generic; +using System.Text; +using UnityEngine; +using UnityEngine.UI; + +public class UMAME : EmuCore +{ + public static UMAME instance { get; private set; } + public MAMEEmu emu { get; private set; } + UniLog mUniLog; + UniMouse mUniMouse; + [HideInInspector] + public UniVideoPlayer mUniVideoPlayer; + UniSoundPlayer mUniSoundPlayer; + UniKeyboard mUniKeyboard; + UniResources mUniResources; + UniIO mUniIO; + + public Text mFPS; + private Canvas mCanvas; + public List HadGameList = new List(); + string mChangeRomName = string.Empty; + public UniTimeSpan mTimeSpan; + public bool bQuickTestRom = false; + public string mQuickTestRom = string.Empty; + public ReplayWriter mReplayWriter; + public ReplayReader mReplayReader; + public long currEmuFrame => emu.currEmuFrame; + public static System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew(); + public static bool bInGame { get; private set; } + public static bool bLogicUpdatePause { get; private set; } + public string EmuDataPath { get { return App.PersistentDataPath(Platform); } } + public string RomPath => EmuDataPath + "/RemoteRoms/"; + public string SavePath => EmuDataPath + "/sav/"; + public override RomPlatformType Platform { get { return mPlatform; } } + RomPlatformType mPlatform = RomPlatformType.Cps1; + public override uint Frame => (uint)emu.currEmuFrame; + void Awake() + { + instance = this; + mFPS = GameObject.Find("FPS").GetComponent(); + mCanvas = GameObject.Find("Canvas").GetComponent(); + mCanvas.worldCamera = Camera.main; + emu = new MAMEEmu(); + mUniLog = new UniLog(); + mUniMouse = this.gameObject.AddComponent(); + mUniVideoPlayer = this.gameObject.AddComponent(); + mUniSoundPlayer = GameObject.Find("Audio").transform.GetComponent(); + mUniKeyboard = this.gameObject.AddComponent(); + mUniResources = new UniResources(); + mUniIO = new UniIO(); + mChangeRomName = string.Empty; + mTimeSpan = new UniTimeSpan(); + emu.Init(RomPath, mUniLog, mUniResources, mUniVideoPlayer, mUniSoundPlayer, mUniKeyboard, mUniMouse, mTimeSpan, mUniIO); + } + void OnEnable() + { + } + void OnDisable() + { + StopGame(); + } + #region 实现接口 + public override object GetState() + { + return SaveState(); + } + public override byte[] GetStateBytes() + { + return SaveState(); + } + public override void LoadState(object state) + { + LoadState((byte[])state); + } + public override void LoadStateFromBytes(byte[] data) + { + LoadState(data); + } + public override void Pause() + { + bLogicUpdatePause = false; + } + public override void Resume() + { + bLogicUpdatePause = true; + } + public override MsgBool StartGame(RomFile romFile) + { + mPlatform = romFile.Platform; + mTimeSpan.InitStandTime(); + if (LoadGame(romFile.FileName)) + return true; + else + return "Rom加载失败"; + } + public override void Dispose() + { + StopGame(); + } + public override void DoReset() + { + StopGame(); + LoadGame(mChangeRomName); + } + public override IControllerSetuper GetControllerSetuper() + { + return mUniKeyboard.ControllerMapper; } public override void GetAudioParams(out int frequency, out int channels) { mUniSoundPlayer.GetAudioParams(out frequency, out channels); - } - - #endregion - bool LoadGame(string loadRom) - { - emu.ResetRomRoot(RomPath); - //Application.targetFrameRate = 60; - mReplayWriter = new ReplayWriter(mChangeRomName, "fuck", ReplayData.ReplayFormat.FM32IP64, Encoding.UTF8); - mChangeRomName = loadRom; - StopGame(); - //读取ROM - emu.LoadRom(mChangeRomName); - //读取成功 - if (emu.bRom) - { - - //读取ROM之后获得宽高初始化画面 - int _width; int _height; IntPtr _framePtr; - emu.GetGameScreenSize(out _width, out _height, out _framePtr); - App.log.Debug($"_width->{_width}, _height->{_height}, _framePtr->{_framePtr}"); - mUniVideoPlayer.Initialize(_width, _height, _framePtr); - //初始化音频 - mUniSoundPlayer.Initialize(); - //开始游戏 - emu.StartGame(); - bInGame = true; - bLogicUpdatePause = true; - return true; - } - else - { - App.log.Debug($"ROM加载失败"); - return false; - } - } + } + + #endregion + bool LoadGame(string loadRom) + { + emu.ResetRomRoot(RomPath); + //Application.targetFrameRate = 60; + mReplayWriter = new ReplayWriter(mChangeRomName, "fuck", ReplayData.ReplayFormat.FM32IP64, Encoding.UTF8); + mChangeRomName = loadRom; + StopGame(); + //读取ROM + emu.LoadRom(mChangeRomName); + //读取成功 + if (emu.bRom) + { + + //读取ROM之后获得宽高初始化画面 + int _width; int _height; IntPtr _framePtr; + emu.GetGameScreenSize(out _width, out _height, out _framePtr); + App.log.Debug($"_width->{_width}, _height->{_height}, _framePtr->{_framePtr}"); + mUniVideoPlayer.Initialize(_width, _height, _framePtr); + //初始化音频 + mUniSoundPlayer.Initialize(); + //开始游戏 + emu.StartGame(); + bInGame = true; + bLogicUpdatePause = true; + return true; + } + else + { + App.log.Debug($"ROM加载失败"); + return false; + } + } protected override bool OnPushEmulatorFrame(ulong InputData) { - if (!bInGame) return false; + if (!bInGame) return false; if (!bLogicUpdatePause) return false; mUniKeyboard.SyncInput(InputData); @@ -181,53 +181,53 @@ public class UMAME : EmuCore protected override void AfterPushFrame() { - mFPS.text = ($"fpsv {mUniVideoPlayer.videoFPS.ToString("F2")} fpsa {mUniSoundPlayer.audioFPS.ToString("F2")} ,Idx:{App.roomMgr.netReplay?.mCurrClientFrameIdx},RIdx:{App.roomMgr.netReplay?.mRemoteFrameIdx},RForward:{App.roomMgr.netReplay?.mRemoteForwardCount} ,RD:{App.roomMgr.netReplay?.mRemoteForwardCount} ,D:{App.roomMgr.netReplay?.mDiffFrameCount} ,Q:{App.roomMgr.netReplay?.mNetReplayQueue.Count}"); - } - public void SaveReplay() - { - string Path = SavePath + Machine.sName + ".rp"; - string dbgPath = SavePath + Machine.sName + ".rpwrite"; - mReplayWriter.SaveData(Path, true, dbgPath); - } - public void StopGame() - { - if (bInGame) - { - emu.StopGame(); - mUniVideoPlayer.StopVideo(); - mUniSoundPlayer.StopPlay(); - bInGame = false; - bLogicUpdatePause = false; - } - } - byte[] SaveState() - { - if (!AxiIO.Directory.Exists(SavePath)) - AxiIO.Directory.CreateDirectory(SavePath); - - System.IO.MemoryStream ms = new System.IO.MemoryStream(); - System.IO.BinaryWriter bw = new System.IO.BinaryWriter(ms); - emu.SaveState(bw); - byte[] data = ms.ToArray(); - bw.Close(); - ms.Close(); - - return data; - - - //byte[] screenData = UMAME.instance.mUniVideoPlayer.GetScreenImg(); - - //FileStream fsImg = new FileStream(SavePath + Machine.sName + ".jpg", FileMode.Create); - //fsImg.Write(screenData, 0, screenData.Length); - //fsImg.Close(); - } - void LoadState(byte[] data) - { - System.IO.MemoryStream fs = new System.IO.MemoryStream(data); - System.IO.BinaryReader br = new System.IO.BinaryReader(fs); - emu.LoadState(br); - br.Close(); - fs.Close(); + mFPS.text = ($"fpsv {mUniVideoPlayer.videoFPS.ToString("F2")} fpsa {mUniSoundPlayer.audioFPS.ToString("F2")} ,Idx:{App.roomMgr.netReplay?.mCurrClientFrameIdx},RIdx:{App.roomMgr.netReplay?.mRemoteFrameIdx},RForward:{App.roomMgr.netReplay?.mRemoteForwardCount} ,RD:{App.roomMgr.netReplay?.mRemoteForwardCount} ,D:{App.roomMgr.netReplay?.mDiffFrameCount} ,Q:{App.roomMgr.netReplay?.mNetReplayQueue.Count}"); + } + public void SaveReplay() + { + string Path = SavePath + Machine.sName + ".rp"; + string dbgPath = SavePath + Machine.sName + ".rpwrite"; + mReplayWriter.SaveData(Path, true, dbgPath); + } + public void StopGame() + { + if (bInGame) + { + emu.StopGame(); + mUniVideoPlayer.StopVideo(); + mUniSoundPlayer.StopPlay(); + bInGame = false; + bLogicUpdatePause = false; + } + } + byte[] SaveState() + { + if (!AxiIO.Directory.Exists(SavePath)) + AxiIO.Directory.CreateDirectory(SavePath); + + System.IO.MemoryStream ms = new System.IO.MemoryStream(); + System.IO.BinaryWriter bw = new System.IO.BinaryWriter(ms); + emu.SaveState(bw); + byte[] data = ms.ToArray(); + bw.Close(); + ms.Close(); + + return data; + + + //byte[] screenData = UMAME.instance.mUniVideoPlayer.GetScreenImg(); + + //FileStream fsImg = new FileStream(SavePath + Machine.sName + ".jpg", FileMode.Create); + //fsImg.Write(screenData, 0, screenData.Length); + //fsImg.Close(); + } + void LoadState(byte[] data) + { + System.IO.MemoryStream fs = new System.IO.MemoryStream(data); + System.IO.BinaryReader br = new System.IO.BinaryReader(fs); + emu.LoadState(br); + br.Close(); + fs.Close(); } diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UniInterface/UniKeyboard.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UniInterface/UniKeyboard.cs index 924701bb..6a6736d0 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UniInterface/UniKeyboard.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UniInterface/UniKeyboard.cs @@ -1,111 +1,111 @@ -using AxibugEmuOnline.Client; -using AxibugEmuOnline.Client.ClientCore; -using AxibugEmuOnline.Client.Event; -using AxibugEmuOnline.Client.Settings; -using AxiReplay; -using MAME.Core; -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; - -public class UniKeyboard : MonoBehaviour, IKeyboard -{ - public MameControllerMapper ControllerMapper { get; private set; } - PlayMode mPlayMode; - - void Awake() - { - ControllerMapper = new MameControllerMapper(); - Init(); - } - - public ulong GetPressedKeys() - { - return mPlayMode.GetPressedKeys(); - } +using AxibugEmuOnline.Client; +using AxibugEmuOnline.Client.ClientCore; +using AxibugEmuOnline.Client.Event; +using AxibugEmuOnline.Client.Settings; +using AxiReplay; +using MAME.Core; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +public class UniKeyboard : MonoBehaviour, IKeyboard +{ + public MameControllerMapper ControllerMapper { get; private set; } + PlayMode mPlayMode; + + void Awake() + { + ControllerMapper = new MameControllerMapper(); + Init(); + } + + public ulong GetPressedKeys() + { + return mPlayMode.GetPressedKeys(); + } public void SyncInput(ulong inputData) { mPlayMode.CurrLocalInpuAllData = inputData; - } - + } + public ulong DoLocalPressedKeys() { return mPlayMode.DoLocalPressedKeys(); - } - - #region - - - public void Init() - { - mPlayMode = new PlayMode(this); - } - - public static IEnumerable GetInputpDataToMotionKey(ulong inputdata) - { - if (inputdata == 0) - yield break; - for (int i = 0; i < MotionKey.AllNeedCheckList.Length; i++) - { - if ((inputdata & MotionKey.AllNeedCheckList[i]) > 0) - yield return MotionKey.GetKeyName(MotionKey.AllNeedCheckList[i]); - } - } - public class PlayMode - { - UniKeyboard mUniKeyboard; - public ulong CurrLocalInpuAllData = 0; - public ulong CurrRemoteInpuAllData = 0; - - public PlayMode(UniKeyboard uniKeyboard) - { - this.mUniKeyboard = uniKeyboard; - } - - public ulong GetPressedKeys() - { - if (InGameUI.Instance.Core.IsNetPlay) - return CurrRemoteInpuAllData; - else - return CurrLocalInpuAllData; - } - - public ulong DoLocalPressedKeys() - { - ulong tempLocalInputAllData = 0; - tempLocalInputAllData |= mUniKeyboard.ControllerMapper.Controller0.GetSingleAllInput(); - tempLocalInputAllData |= mUniKeyboard.ControllerMapper.Controller1.GetSingleAllInput(); - tempLocalInputAllData |= mUniKeyboard.ControllerMapper.Controller2.GetSingleAllInput(); - tempLocalInputAllData |= mUniKeyboard.ControllerMapper.Controller3.GetSingleAllInput(); - -#if UNITY_EDITOR - if (CurrLocalInpuAllData != tempLocalInputAllData) - { - string ShowKeyNames = string.Empty; - foreach (string keyname in GetInputpDataToMotionKey(CurrLocalInpuAllData)) - { - ShowKeyNames += keyname + " |"; - } - Debug.Log("GetPressedKeys=>" + ShowKeyNames); - } -#endif - - CurrLocalInpuAllData = tempLocalInputAllData; - //写入replay - UMAME.instance.mReplayWriter.NextFramebyFrameIdx((int)UMAME.instance.mUniVideoPlayer.mFrame, CurrLocalInpuAllData); - - CheckPlayerSlotChanged(); - - return CurrLocalInpuAllData; - } - - - void CheckPlayerSlotChanged() - { + } + + #region + + + public void Init() + { + mPlayMode = new PlayMode(this); + } + + public static IEnumerable GetInputpDataToMotionKey(ulong inputdata) + { + if (inputdata == 0) + yield break; + for (int i = 0; i < MotionKey.AllNeedCheckList.Length; i++) + { + if ((inputdata & MotionKey.AllNeedCheckList[i]) > 0) + yield return MotionKey.GetKeyName(MotionKey.AllNeedCheckList[i]); + } + } + public class PlayMode + { + UniKeyboard mUniKeyboard; + public ulong CurrLocalInpuAllData = 0; + public ulong CurrRemoteInpuAllData = 0; + + public PlayMode(UniKeyboard uniKeyboard) + { + this.mUniKeyboard = uniKeyboard; + } + + public ulong GetPressedKeys() + { + if (InGameUI.Instance.Core.IsNetPlay) + return CurrRemoteInpuAllData; + else + return CurrLocalInpuAllData; + } + + public ulong DoLocalPressedKeys() + { + ulong tempLocalInputAllData = 0; + tempLocalInputAllData |= mUniKeyboard.ControllerMapper.Controller0.GetSingleAllInput(); + tempLocalInputAllData |= mUniKeyboard.ControllerMapper.Controller1.GetSingleAllInput(); + tempLocalInputAllData |= mUniKeyboard.ControllerMapper.Controller2.GetSingleAllInput(); + tempLocalInputAllData |= mUniKeyboard.ControllerMapper.Controller3.GetSingleAllInput(); + +#if UNITY_EDITOR + if (CurrLocalInpuAllData != tempLocalInputAllData) + { + string ShowKeyNames = string.Empty; + foreach (string keyname in GetInputpDataToMotionKey(CurrLocalInpuAllData)) + { + ShowKeyNames += keyname + " |"; + } + Debug.Log("GetPressedKeys=>" + ShowKeyNames); + } +#endif + + CurrLocalInpuAllData = tempLocalInputAllData; + //写入replay + UMAME.instance.mReplayWriter.NextFramebyFrameIdx((int)UMAME.instance.mUniVideoPlayer.mFrame, CurrLocalInpuAllData); + + CheckPlayerSlotChanged(); + + return CurrLocalInpuAllData; + } + + + void CheckPlayerSlotChanged() + { if (!mUniKeyboard.ControllerMapper.Controller0.ConnectSlot.HasValue && mUniKeyboard.ControllerMapper.Controller0.AnyButtonDown()) - Eventer.Instance.PostEvent(EEvent.OnLocalJoyDesireInvert, 0); - + Eventer.Instance.PostEvent(EEvent.OnLocalJoyDesireInvert, 0); + if (!mUniKeyboard.ControllerMapper.Controller1.ConnectSlot.HasValue && mUniKeyboard.ControllerMapper.Controller1.AnyButtonDown()) Eventer.Instance.PostEvent(EEvent.OnLocalJoyDesireInvert, 1); @@ -113,340 +113,340 @@ public class UniKeyboard : MonoBehaviour, IKeyboard Eventer.Instance.PostEvent(EEvent.OnLocalJoyDesireInvert, 2); if (!mUniKeyboard.ControllerMapper.Controller3.ConnectSlot.HasValue && mUniKeyboard.ControllerMapper.Controller3.AnyButtonDown()) - Eventer.Instance.PostEvent(EEvent.OnLocalJoyDesireInvert, 3); - } - - } - public class ReplayMode - { - ulong currInputData; - - public ReplayMode() - { - } - - public ulong GetPressedKeys() - { - int targetFrame = (int)UMAME.instance.mUniVideoPlayer.mFrame; - AxiReplay.ReplayStep stepData; - //有变化 - if (UMAME.instance.mReplayReader.NextFramebyFrameIdx(targetFrame, out stepData)) - { -#if UNITY_EDITOR - string ShowKeyNames = string.Empty; - foreach (string keyname in GetInputpDataToMotionKey(currInputData)) - { - ShowKeyNames += keyname + " |"; - } - Debug.Log("GetPressedKeys=>" + ShowKeyNames); -#endif - currInputData = stepData.InPut; - } - return currInputData; - } - } - #endregion -} - -public class MameControllerMapper : IControllerSetuper -{ - public MameSingleConoller Controller0 = new MameSingleConoller(0); - public MameSingleConoller Controller1 = new MameSingleConoller(1); - public MameSingleConoller Controller2 = new MameSingleConoller(2); - public MameSingleConoller Controller3 = new MameSingleConoller(3); - - ulong mCurrAllInput; - - public void SetConnect(uint? con0ToSlot = null, - uint? con1ToSlot = null, - uint? con2ToSlot = null, - uint? con3ToSlot = null) - { - Controller0.ConnectSlot = con0ToSlot; - Controller1.ConnectSlot = con1ToSlot; - Controller2.ConnectSlot = con2ToSlot; - Controller3.ConnectSlot = con3ToSlot; - } - public int? GetSlotConnectingControllerIndex(int slotIndex) - { - if (Controller0.ConnectSlot.HasValue && Controller0.ConnectSlot.Value == slotIndex) return 0; - else if (Controller1.ConnectSlot.HasValue && Controller1.ConnectSlot.Value == slotIndex) return 1; - else if (Controller2.ConnectSlot.HasValue && Controller2.ConnectSlot.Value == slotIndex) return 2; - else if (Controller3.ConnectSlot.HasValue && Controller3.ConnectSlot.Value == slotIndex) return 3; - else return null; - } - public IController GetSlotConnectingController(int slotIndex) - { - if (Controller0.ConnectSlot.HasValue && Controller0.ConnectSlot.Value == slotIndex) return Controller0; - else if (Controller1.ConnectSlot.HasValue && Controller1.ConnectSlot.Value == slotIndex) return Controller1; - else if (Controller2.ConnectSlot.HasValue && Controller2.ConnectSlot.Value == slotIndex) return Controller2; - else if (Controller3.ConnectSlot.HasValue && Controller3.ConnectSlot.Value == slotIndex) return Controller3; - else return null; - } - static HashSet s_temp = new HashSet(); - public uint? GetFreeSlotIndex() - { - s_temp.Clear(); - s_temp.Add(0); - s_temp.Add(1); - s_temp.Add(2); - s_temp.Add(3); - - if (Controller0.ConnectSlot.HasValue) s_temp.Remove(Controller0.ConnectSlot.Value); - if (Controller1.ConnectSlot.HasValue) s_temp.Remove(Controller1.ConnectSlot.Value); - if (Controller2.ConnectSlot.HasValue) s_temp.Remove(Controller2.ConnectSlot.Value); - if (Controller3.ConnectSlot.HasValue) s_temp.Remove(Controller3.ConnectSlot.Value); - - if (s_temp.Count > 0) return s_temp.First(); - else return null; - } - public void LetControllerConnect(int conIndex, uint slotIndex) - { - MameSingleConoller targetController; - switch (conIndex) - { - case 0: targetController = Controller0; break; - case 1: targetController = Controller1; break; - case 2: targetController = Controller2; break; - case 3: targetController = Controller3; break; - default: - throw new System.Exception($"Not Allowed conIndex Range: {conIndex}"); - break; - } - if (targetController.ConnectSlot.HasValue) return; - - targetController.ConnectSlot = slotIndex; - Eventer.Instance.PostEvent(EEvent.OnControllerConnectChanged); - } - -} - -/// -/// MAME控制器 -/// -public class MameSingleConoller : IController -{ - //public KeyCode INSERT_COIN, GAMESTART, - //UP, DOWN, LEFT, RIGHT, - //BTN_A, BTN_B, BTN_C, BTN_D, BTN_E, BTN_F; - - public ulong tg_INSERT_COIN, tg_GAMESTART, - tg_UP, tg_DOWN, tg_LEFT, tg_RIGHT, - tg_BTN_A, tg_BTN_B, tg_BTN_C, tg_BTN_D, tg_BTN_E, tg_BTN_F; - + Eventer.Instance.PostEvent(EEvent.OnLocalJoyDesireInvert, 3); + } + + } + public class ReplayMode + { + ulong currInputData; + + public ReplayMode() + { + } + + public ulong GetPressedKeys() + { + int targetFrame = (int)UMAME.instance.mUniVideoPlayer.mFrame; + AxiReplay.ReplayStep stepData; + //有变化 + if (UMAME.instance.mReplayReader.NextFramebyFrameIdx(targetFrame, out stepData)) + { +#if UNITY_EDITOR + string ShowKeyNames = string.Empty; + foreach (string keyname in GetInputpDataToMotionKey(currInputData)) + { + ShowKeyNames += keyname + " |"; + } + Debug.Log("GetPressedKeys=>" + ShowKeyNames); +#endif + currInputData = stepData.InPut; + } + return currInputData; + } + } + #endregion +} + +public class MameControllerMapper : IControllerSetuper +{ + public MameSingleConoller Controller0 = new MameSingleConoller(0); + public MameSingleConoller Controller1 = new MameSingleConoller(1); + public MameSingleConoller Controller2 = new MameSingleConoller(2); + public MameSingleConoller Controller3 = new MameSingleConoller(3); + + ulong mCurrAllInput; + + public void SetConnect(uint? con0ToSlot = null, + uint? con1ToSlot = null, + uint? con2ToSlot = null, + uint? con3ToSlot = null) + { + Controller0.ConnectSlot = con0ToSlot; + Controller1.ConnectSlot = con1ToSlot; + Controller2.ConnectSlot = con2ToSlot; + Controller3.ConnectSlot = con3ToSlot; + } + public int? GetSlotConnectingControllerIndex(int slotIndex) + { + if (Controller0.ConnectSlot.HasValue && Controller0.ConnectSlot.Value == slotIndex) return 0; + else if (Controller1.ConnectSlot.HasValue && Controller1.ConnectSlot.Value == slotIndex) return 1; + else if (Controller2.ConnectSlot.HasValue && Controller2.ConnectSlot.Value == slotIndex) return 2; + else if (Controller3.ConnectSlot.HasValue && Controller3.ConnectSlot.Value == slotIndex) return 3; + else return null; + } + public IController GetSlotConnectingController(int slotIndex) + { + if (Controller0.ConnectSlot.HasValue && Controller0.ConnectSlot.Value == slotIndex) return Controller0; + else if (Controller1.ConnectSlot.HasValue && Controller1.ConnectSlot.Value == slotIndex) return Controller1; + else if (Controller2.ConnectSlot.HasValue && Controller2.ConnectSlot.Value == slotIndex) return Controller2; + else if (Controller3.ConnectSlot.HasValue && Controller3.ConnectSlot.Value == slotIndex) return Controller3; + else return null; + } + static HashSet s_temp = new HashSet(); + public uint? GetFreeSlotIndex() + { + s_temp.Clear(); + s_temp.Add(0); + s_temp.Add(1); + s_temp.Add(2); + s_temp.Add(3); + + if (Controller0.ConnectSlot.HasValue) s_temp.Remove(Controller0.ConnectSlot.Value); + if (Controller1.ConnectSlot.HasValue) s_temp.Remove(Controller1.ConnectSlot.Value); + if (Controller2.ConnectSlot.HasValue) s_temp.Remove(Controller2.ConnectSlot.Value); + if (Controller3.ConnectSlot.HasValue) s_temp.Remove(Controller3.ConnectSlot.Value); + + if (s_temp.Count > 0) return s_temp.First(); + else return null; + } + public void LetControllerConnect(int conIndex, uint slotIndex) + { + MameSingleConoller targetController; + switch (conIndex) + { + case 0: targetController = Controller0; break; + case 1: targetController = Controller1; break; + case 2: targetController = Controller2; break; + case 3: targetController = Controller3; break; + default: + throw new System.Exception($"Not Allowed conIndex Range: {conIndex}"); + break; + } + if (targetController.ConnectSlot.HasValue) return; + + targetController.ConnectSlot = slotIndex; + Eventer.Instance.PostEvent(EEvent.OnControllerConnectChanged); + } + +} + +/// +/// MAME控制器 +/// +public class MameSingleConoller : IController +{ + //public KeyCode INSERT_COIN, GAMESTART, + //UP, DOWN, LEFT, RIGHT, + //BTN_A, BTN_B, BTN_C, BTN_D, BTN_E, BTN_F; + + public ulong tg_INSERT_COIN, tg_GAMESTART, + tg_UP, tg_DOWN, tg_LEFT, tg_RIGHT, + tg_BTN_A, tg_BTN_B, tg_BTN_C, tg_BTN_D, tg_BTN_E, tg_BTN_F; + public ulong CurrLocalSingleAllInput { get; private set; } - private MAMEKeyBinding m_keyMapper; - int mControllerIndex; - uint? mConnectSlot; - - /// - /// 指示该手柄连接的手柄插槽 - /// 这个值代表了该手柄在实际游戏中控制的Player - /// [0,3] 例外:为空代表未连接 - /// - public uint? ConnectSlot - { - get { return mConnectSlot; } - set { mConnectSlot = value; this.ResetTargetMotionKey(); } - } - - /// - /// 控制器编号 - /// 此编号并非对应游戏中的player1,player2,player3,player4,仅仅作为本地4个手柄的实例 - /// [0,3] - /// - public int ControllerIndex - { - get { return mControllerIndex; } + private MAMEKeyBinding m_keyMapper; + int mControllerIndex; + uint? mConnectSlot; + + /// + /// 指示该手柄连接的手柄插槽 + /// 这个值代表了该手柄在实际游戏中控制的Player + /// [0,3] 例外:为空代表未连接 + /// + public uint? ConnectSlot + { + get { return mConnectSlot; } + set { mConnectSlot = value; this.ResetTargetMotionKey(); } + } + + /// + /// 控制器编号 + /// 此编号并非对应游戏中的player1,player2,player3,player4,仅仅作为本地4个手柄的实例 + /// [0,3] + /// + public int ControllerIndex + { + get { return mControllerIndex; } set { mControllerIndex = value; //this.LoadControlKeyForConfig(); //走统一配置 - } - } - public MameSingleConoller(int controllerIndex) - { - ControllerIndex = controllerIndex; - m_keyMapper = App.settings.KeyMapper.GetBinder(UMAME.instance.Platform); - } - - public bool AnyButtonDown() - { - return m_keyMapper.AnyKeyDown(ControllerIndex); - //if (Input.GetKeyDown(INSERT_COIN)) return true; - //if (Input.GetKeyDown(GAMESTART)) return true; - //if (Input.GetKeyDown(UP)) return true; - //if (Input.GetKeyDown(DOWN)) return true; - //if (Input.GetKeyDown(LEFT)) return true; - //if (Input.GetKeyDown(RIGHT)) return true; - //if (Input.GetKeyDown(BTN_A)) return true; - //if (Input.GetKeyDown(BTN_B)) return true; - //if (Input.GetKeyDown(BTN_C)) return true; - //if (Input.GetKeyDown(BTN_D)) return true; - //if (Input.GetKeyDown(BTN_E)) return true; - //if (Input.GetKeyDown(BTN_F)) return true; - //return false; - } - public ulong GetSingleAllInput() - { - if (!ConnectSlot.HasValue) - return 0; - CurrLocalSingleAllInput = 0; - - - if (m_keyMapper.GetKey(UMAMEKSingleKey.INSERT_COIN, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_INSERT_COIN; - if (m_keyMapper.GetKey(UMAMEKSingleKey.GAMESTART, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_GAMESTART; - if (m_keyMapper.GetKey(UMAMEKSingleKey.UP, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_UP; - if (m_keyMapper.GetKey(UMAMEKSingleKey.DOWN, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_DOWN; - if (m_keyMapper.GetKey(UMAMEKSingleKey.LEFT, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_LEFT; - if (m_keyMapper.GetKey(UMAMEKSingleKey.RIGHT, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_RIGHT; - if (m_keyMapper.GetKey(UMAMEKSingleKey.BTN_A, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_BTN_A; - if (m_keyMapper.GetKey(UMAMEKSingleKey.BTN_B, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_BTN_B; - if (m_keyMapper.GetKey(UMAMEKSingleKey.BTN_C, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_BTN_C; - if (m_keyMapper.GetKey(UMAMEKSingleKey.BTN_D, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_BTN_D; - if (m_keyMapper.GetKey(UMAMEKSingleKey.BTN_E, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_BTN_E; - if (m_keyMapper.GetKey(UMAMEKSingleKey.BTN_F, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_BTN_F; - - //if (Input.GetKey(INSERT_COIN)) CurrLocalSingleAllInput |= (ulong)tg_INSERT_COIN; - //if (Input.GetKey(GAMESTART)) CurrLocalSingleAllInput |= (ulong)tg_GAMESTART; - //if (Input.GetKey(UP)) CurrLocalSingleAllInput |= (ulong)tg_UP; - //if (Input.GetKey(DOWN)) CurrLocalSingleAllInput |= (ulong)tg_DOWN; - //if (Input.GetKey(LEFT)) CurrLocalSingleAllInput |= (ulong)tg_LEFT; - //if (Input.GetKey(RIGHT)) CurrLocalSingleAllInput |= (ulong)tg_RIGHT; - //if (Input.GetKey(BTN_A)) CurrLocalSingleAllInput |= (ulong)tg_BTN_A; - //if (Input.GetKey(BTN_B)) CurrLocalSingleAllInput |= (ulong)tg_BTN_B; - //if (Input.GetKey(BTN_C)) CurrLocalSingleAllInput |= (ulong)tg_BTN_C; - //if (Input.GetKey(BTN_D)) CurrLocalSingleAllInput |= (ulong)tg_BTN_D; - //if (Input.GetKey(BTN_E)) CurrLocalSingleAllInput |= (ulong)tg_BTN_E; - //if (Input.GetKey(BTN_F)) CurrLocalSingleAllInput |= (ulong)tg_BTN_F; - - return CurrLocalSingleAllInput; - } - -} -public static class MameSingleControllSetter -{ - //不再需要 - //public static void LoadControlKeyForConfig(this MameSingleConoller singlecontrol) - //{ - // //TODO 等待支持配置,或统一 - // switch (singlecontrol.ControllerIndex) - // { - // case 0: - // singlecontrol.INSERT_COIN = KeyCode.Alpha5; - // singlecontrol.GAMESTART = KeyCode.Alpha1; - // singlecontrol.UP = KeyCode.W; - // singlecontrol.DOWN = KeyCode.S; - // singlecontrol.LEFT = KeyCode.A; - // singlecontrol.RIGHT = KeyCode.D; - // singlecontrol.BTN_A = KeyCode.J; - // singlecontrol.BTN_B = KeyCode.K; - // singlecontrol.BTN_C = KeyCode.L; - // singlecontrol.BTN_D = KeyCode.U; - // singlecontrol.BTN_E = KeyCode.I; - // singlecontrol.BTN_F = KeyCode.O; - // break; - // case 1: - // singlecontrol.INSERT_COIN = KeyCode.KeypadMultiply; - // singlecontrol.GAMESTART = KeyCode.KeypadDivide; - // singlecontrol.UP = KeyCode.UpArrow; - // singlecontrol.DOWN = KeyCode.DownArrow; - // singlecontrol.LEFT = KeyCode.LeftArrow; - // singlecontrol.RIGHT = KeyCode.RightArrow; - // singlecontrol.BTN_A = KeyCode.Keypad1; - // singlecontrol.BTN_B = KeyCode.Keypad2; - // singlecontrol.BTN_C = KeyCode.Keypad3; - // singlecontrol.BTN_D = KeyCode.Keypad4; - // singlecontrol.BTN_E = KeyCode.Keypad5; - // singlecontrol.BTN_F = KeyCode.Keypad6; - // break; - // case 2: - // break; - // case 3: - // break; - // } - //} - public static void ResetTargetMotionKey(this MameSingleConoller singlecontrol) - { - if (!singlecontrol.ConnectSlot.HasValue) - { - singlecontrol.tg_INSERT_COIN - = singlecontrol.tg_GAMESTART - = singlecontrol.tg_UP - = singlecontrol.tg_DOWN - = singlecontrol.tg_LEFT - = singlecontrol.tg_RIGHT - = singlecontrol.tg_BTN_A - = singlecontrol.tg_BTN_B - = singlecontrol.tg_BTN_C - = singlecontrol.tg_BTN_D - = singlecontrol.tg_BTN_E - = singlecontrol.tg_BTN_F - = MotionKey.FinalKey; - return; - } - switch (singlecontrol.ConnectSlot.Value) - { - case 0: - singlecontrol.tg_INSERT_COIN = MotionKey.P1_INSERT_COIN; - singlecontrol.tg_GAMESTART = MotionKey.P1_GAMESTART; - singlecontrol.tg_UP = MotionKey.P1_UP; - singlecontrol.tg_DOWN = MotionKey.P1_DOWN; - singlecontrol.tg_LEFT = MotionKey.P1_LEFT; - singlecontrol.tg_RIGHT = MotionKey.P1_RIGHT; - singlecontrol.tg_BTN_A = MotionKey.P1_BTN_1; - singlecontrol.tg_BTN_B = MotionKey.P1_BTN_2; - singlecontrol.tg_BTN_C = MotionKey.P1_BTN_3; - singlecontrol.tg_BTN_D = MotionKey.P1_BTN_4; - singlecontrol.tg_BTN_E = MotionKey.P1_BTN_5; - singlecontrol.tg_BTN_F = MotionKey.P1_BTN_6; - break; - case 1: - singlecontrol.tg_INSERT_COIN = MotionKey.P2_INSERT_COIN; - singlecontrol.tg_GAMESTART = MotionKey.P2_GAMESTART; - singlecontrol.tg_UP = MotionKey.P2_UP; - singlecontrol.tg_DOWN = MotionKey.P2_DOWN; - singlecontrol.tg_LEFT = MotionKey.P2_LEFT; - singlecontrol.tg_RIGHT = MotionKey.P2_RIGHT; - singlecontrol.tg_BTN_A = MotionKey.P2_BTN_1; - singlecontrol.tg_BTN_B = MotionKey.P2_BTN_2; - singlecontrol.tg_BTN_C = MotionKey.P2_BTN_3; - singlecontrol.tg_BTN_D = MotionKey.P2_BTN_4; - singlecontrol.tg_BTN_E = MotionKey.P2_BTN_5; - singlecontrol.tg_BTN_F = MotionKey.P2_BTN_6; - break; - //后续修改后 支持P3 P4 - case 2: - singlecontrol.tg_INSERT_COIN = MotionKey.FinalKey; - singlecontrol.tg_GAMESTART = MotionKey.FinalKey; - singlecontrol.tg_UP = MotionKey.FinalKey; - singlecontrol.tg_DOWN = MotionKey.FinalKey; - singlecontrol.tg_LEFT = MotionKey.FinalKey; - singlecontrol.tg_RIGHT = MotionKey.FinalKey; - singlecontrol.tg_BTN_A = MotionKey.FinalKey; - singlecontrol.tg_BTN_B = MotionKey.FinalKey; - singlecontrol.tg_BTN_C = MotionKey.FinalKey; - singlecontrol.tg_BTN_D = MotionKey.FinalKey; - singlecontrol.tg_BTN_E = MotionKey.FinalKey; - singlecontrol.tg_BTN_F = MotionKey.FinalKey; - break; - case 3: - singlecontrol.tg_INSERT_COIN = MotionKey.FinalKey; - singlecontrol.tg_GAMESTART = MotionKey.FinalKey; - singlecontrol.tg_UP = MotionKey.FinalKey; - singlecontrol.tg_DOWN = MotionKey.FinalKey; - singlecontrol.tg_LEFT = MotionKey.FinalKey; - singlecontrol.tg_RIGHT = MotionKey.FinalKey; - singlecontrol.tg_BTN_A = MotionKey.FinalKey; - singlecontrol.tg_BTN_B = MotionKey.FinalKey; - singlecontrol.tg_BTN_C = MotionKey.FinalKey; - singlecontrol.tg_BTN_D = MotionKey.FinalKey; - singlecontrol.tg_BTN_E = MotionKey.FinalKey; - singlecontrol.tg_BTN_F = MotionKey.FinalKey; - break; - } - } -} - + } + } + public MameSingleConoller(int controllerIndex) + { + ControllerIndex = controllerIndex; + m_keyMapper = App.settings.KeyMapper.GetBinder(UMAME.instance.Platform); + } + + public bool AnyButtonDown() + { + return m_keyMapper.AnyKeyDown(ControllerIndex); + //if (Input.GetKeyDown(INSERT_COIN)) return true; + //if (Input.GetKeyDown(GAMESTART)) return true; + //if (Input.GetKeyDown(UP)) return true; + //if (Input.GetKeyDown(DOWN)) return true; + //if (Input.GetKeyDown(LEFT)) return true; + //if (Input.GetKeyDown(RIGHT)) return true; + //if (Input.GetKeyDown(BTN_A)) return true; + //if (Input.GetKeyDown(BTN_B)) return true; + //if (Input.GetKeyDown(BTN_C)) return true; + //if (Input.GetKeyDown(BTN_D)) return true; + //if (Input.GetKeyDown(BTN_E)) return true; + //if (Input.GetKeyDown(BTN_F)) return true; + //return false; + } + public ulong GetSingleAllInput() + { + if (!ConnectSlot.HasValue) + return 0; + CurrLocalSingleAllInput = 0; + + + if (m_keyMapper.GetKey(UMAMEKSingleKey.INSERT_COIN, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_INSERT_COIN; + if (m_keyMapper.GetKey(UMAMEKSingleKey.GAMESTART, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_GAMESTART; + if (m_keyMapper.GetKey(UMAMEKSingleKey.UP, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_UP; + if (m_keyMapper.GetKey(UMAMEKSingleKey.DOWN, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_DOWN; + if (m_keyMapper.GetKey(UMAMEKSingleKey.LEFT, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_LEFT; + if (m_keyMapper.GetKey(UMAMEKSingleKey.RIGHT, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_RIGHT; + if (m_keyMapper.GetKey(UMAMEKSingleKey.BTN_A, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_BTN_A; + if (m_keyMapper.GetKey(UMAMEKSingleKey.BTN_B, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_BTN_B; + if (m_keyMapper.GetKey(UMAMEKSingleKey.BTN_C, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_BTN_C; + if (m_keyMapper.GetKey(UMAMEKSingleKey.BTN_D, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_BTN_D; + if (m_keyMapper.GetKey(UMAMEKSingleKey.BTN_E, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_BTN_E; + if (m_keyMapper.GetKey(UMAMEKSingleKey.BTN_F, ControllerIndex)) CurrLocalSingleAllInput |= (ulong)tg_BTN_F; + + //if (Input.GetKey(INSERT_COIN)) CurrLocalSingleAllInput |= (ulong)tg_INSERT_COIN; + //if (Input.GetKey(GAMESTART)) CurrLocalSingleAllInput |= (ulong)tg_GAMESTART; + //if (Input.GetKey(UP)) CurrLocalSingleAllInput |= (ulong)tg_UP; + //if (Input.GetKey(DOWN)) CurrLocalSingleAllInput |= (ulong)tg_DOWN; + //if (Input.GetKey(LEFT)) CurrLocalSingleAllInput |= (ulong)tg_LEFT; + //if (Input.GetKey(RIGHT)) CurrLocalSingleAllInput |= (ulong)tg_RIGHT; + //if (Input.GetKey(BTN_A)) CurrLocalSingleAllInput |= (ulong)tg_BTN_A; + //if (Input.GetKey(BTN_B)) CurrLocalSingleAllInput |= (ulong)tg_BTN_B; + //if (Input.GetKey(BTN_C)) CurrLocalSingleAllInput |= (ulong)tg_BTN_C; + //if (Input.GetKey(BTN_D)) CurrLocalSingleAllInput |= (ulong)tg_BTN_D; + //if (Input.GetKey(BTN_E)) CurrLocalSingleAllInput |= (ulong)tg_BTN_E; + //if (Input.GetKey(BTN_F)) CurrLocalSingleAllInput |= (ulong)tg_BTN_F; + + return CurrLocalSingleAllInput; + } + +} +public static class MameSingleControllSetter +{ + //不再需要 + //public static void LoadControlKeyForConfig(this MameSingleConoller singlecontrol) + //{ + // //TODO 等待支持配置,或统一 + // switch (singlecontrol.ControllerIndex) + // { + // case 0: + // singlecontrol.INSERT_COIN = KeyCode.Alpha5; + // singlecontrol.GAMESTART = KeyCode.Alpha1; + // singlecontrol.UP = KeyCode.W; + // singlecontrol.DOWN = KeyCode.S; + // singlecontrol.LEFT = KeyCode.A; + // singlecontrol.RIGHT = KeyCode.D; + // singlecontrol.BTN_A = KeyCode.J; + // singlecontrol.BTN_B = KeyCode.K; + // singlecontrol.BTN_C = KeyCode.L; + // singlecontrol.BTN_D = KeyCode.U; + // singlecontrol.BTN_E = KeyCode.I; + // singlecontrol.BTN_F = KeyCode.O; + // break; + // case 1: + // singlecontrol.INSERT_COIN = KeyCode.KeypadMultiply; + // singlecontrol.GAMESTART = KeyCode.KeypadDivide; + // singlecontrol.UP = KeyCode.UpArrow; + // singlecontrol.DOWN = KeyCode.DownArrow; + // singlecontrol.LEFT = KeyCode.LeftArrow; + // singlecontrol.RIGHT = KeyCode.RightArrow; + // singlecontrol.BTN_A = KeyCode.Keypad1; + // singlecontrol.BTN_B = KeyCode.Keypad2; + // singlecontrol.BTN_C = KeyCode.Keypad3; + // singlecontrol.BTN_D = KeyCode.Keypad4; + // singlecontrol.BTN_E = KeyCode.Keypad5; + // singlecontrol.BTN_F = KeyCode.Keypad6; + // break; + // case 2: + // break; + // case 3: + // break; + // } + //} + public static void ResetTargetMotionKey(this MameSingleConoller singlecontrol) + { + if (!singlecontrol.ConnectSlot.HasValue) + { + singlecontrol.tg_INSERT_COIN + = singlecontrol.tg_GAMESTART + = singlecontrol.tg_UP + = singlecontrol.tg_DOWN + = singlecontrol.tg_LEFT + = singlecontrol.tg_RIGHT + = singlecontrol.tg_BTN_A + = singlecontrol.tg_BTN_B + = singlecontrol.tg_BTN_C + = singlecontrol.tg_BTN_D + = singlecontrol.tg_BTN_E + = singlecontrol.tg_BTN_F + = MotionKey.FinalKey; + return; + } + switch (singlecontrol.ConnectSlot.Value) + { + case 0: + singlecontrol.tg_INSERT_COIN = MotionKey.P1_INSERT_COIN; + singlecontrol.tg_GAMESTART = MotionKey.P1_GAMESTART; + singlecontrol.tg_UP = MotionKey.P1_UP; + singlecontrol.tg_DOWN = MotionKey.P1_DOWN; + singlecontrol.tg_LEFT = MotionKey.P1_LEFT; + singlecontrol.tg_RIGHT = MotionKey.P1_RIGHT; + singlecontrol.tg_BTN_A = MotionKey.P1_BTN_1; + singlecontrol.tg_BTN_B = MotionKey.P1_BTN_2; + singlecontrol.tg_BTN_C = MotionKey.P1_BTN_3; + singlecontrol.tg_BTN_D = MotionKey.P1_BTN_4; + singlecontrol.tg_BTN_E = MotionKey.P1_BTN_5; + singlecontrol.tg_BTN_F = MotionKey.P1_BTN_6; + break; + case 1: + singlecontrol.tg_INSERT_COIN = MotionKey.P2_INSERT_COIN; + singlecontrol.tg_GAMESTART = MotionKey.P2_GAMESTART; + singlecontrol.tg_UP = MotionKey.P2_UP; + singlecontrol.tg_DOWN = MotionKey.P2_DOWN; + singlecontrol.tg_LEFT = MotionKey.P2_LEFT; + singlecontrol.tg_RIGHT = MotionKey.P2_RIGHT; + singlecontrol.tg_BTN_A = MotionKey.P2_BTN_1; + singlecontrol.tg_BTN_B = MotionKey.P2_BTN_2; + singlecontrol.tg_BTN_C = MotionKey.P2_BTN_3; + singlecontrol.tg_BTN_D = MotionKey.P2_BTN_4; + singlecontrol.tg_BTN_E = MotionKey.P2_BTN_5; + singlecontrol.tg_BTN_F = MotionKey.P2_BTN_6; + break; + //后续修改后 支持P3 P4 + case 2: + singlecontrol.tg_INSERT_COIN = MotionKey.FinalKey; + singlecontrol.tg_GAMESTART = MotionKey.FinalKey; + singlecontrol.tg_UP = MotionKey.FinalKey; + singlecontrol.tg_DOWN = MotionKey.FinalKey; + singlecontrol.tg_LEFT = MotionKey.FinalKey; + singlecontrol.tg_RIGHT = MotionKey.FinalKey; + singlecontrol.tg_BTN_A = MotionKey.FinalKey; + singlecontrol.tg_BTN_B = MotionKey.FinalKey; + singlecontrol.tg_BTN_C = MotionKey.FinalKey; + singlecontrol.tg_BTN_D = MotionKey.FinalKey; + singlecontrol.tg_BTN_E = MotionKey.FinalKey; + singlecontrol.tg_BTN_F = MotionKey.FinalKey; + break; + case 3: + singlecontrol.tg_INSERT_COIN = MotionKey.FinalKey; + singlecontrol.tg_GAMESTART = MotionKey.FinalKey; + singlecontrol.tg_UP = MotionKey.FinalKey; + singlecontrol.tg_DOWN = MotionKey.FinalKey; + singlecontrol.tg_LEFT = MotionKey.FinalKey; + singlecontrol.tg_RIGHT = MotionKey.FinalKey; + singlecontrol.tg_BTN_A = MotionKey.FinalKey; + singlecontrol.tg_BTN_B = MotionKey.FinalKey; + singlecontrol.tg_BTN_C = MotionKey.FinalKey; + singlecontrol.tg_BTN_D = MotionKey.FinalKey; + singlecontrol.tg_BTN_E = MotionKey.FinalKey; + singlecontrol.tg_BTN_F = MotionKey.FinalKey; + break; + } + } +} + diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/NesEmulator/CoreSupporter.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/NesEmulator/CoreSupporter.cs index eec32d97..71b93ceb 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/NesEmulator/CoreSupporter.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/NesEmulator/CoreSupporter.cs @@ -1,135 +1,135 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugProtobuf; -using AxiReplay; -using System; -using System.Runtime.InteropServices; -using UnityEngine; -using VirtualNes.Core; - -namespace AxibugEmuOnline.Client -{ - public class CoreSupporter : ISupporterImpl - { - - public System.IO.Stream OpenRom(string fname) - { - try - { - var romFile = App.GetRomLib(RomPlatformType.Nes).GetRomFile(fname); - var bytes = romFile.GetRomFileData(); - Debug.Log($"Open {romFile.Alias}"); - return new System.IO.MemoryStream(bytes); - } - catch (Exception ex) - { - Debug.LogError(ex); - return null; - } - } - - public void GetRomPathInfo(string fname, out string fullPath, out string directPath) - { - var romFile = App.GetRomLib(RomPlatformType.Nes).GetRomFile(fname); - UnityEngine.Debug.Assert(romFile != null); - - fullPath = romFile.LocalFilePath; - directPath = System.IO.Path.GetDirectoryName(fullPath); - } - - public System.IO.Stream OpenFile_DISKSYS() - { - return new System.IO.MemoryStream(Resources.Load("NES/Disksys.rom").bytes); - } - - public void SaveSRAMToFile(byte[] sramContent, string romName) - { - string sramDirectoryPath = $"{App.PersistentDataPath(AxibugProtobuf.RomPlatformType.Nes)}/{Config.path.szSavePath}"; - AxiIO.Directory.CreateDirectory(sramDirectoryPath); - romName = System.IO.Path.GetFileNameWithoutExtension(romName); - AxiIO.File.WriteAllBytes($"{sramDirectoryPath}/{romName}.sav", sramContent); - } - - public void SaveDISKToFile(byte[] diskFileContent, string romName) - { - string diskFileDirectoryPath = $"{App.PersistentDataPath(AxibugProtobuf.RomPlatformType.Nes)}/dsv"; - AxiIO.Directory.CreateDirectory(diskFileDirectoryPath); - romName = System.IO.Path.GetFileNameWithoutExtension(romName); - AxiIO.File.WriteAllBytes($"{diskFileDirectoryPath}/{romName}.dsv", diskFileContent); - } - - public EmulatorConfig Config { get; private set; } = new EmulatorConfig(); - public void PrepareDirectory(string directPath) - { - AxiIO.Directory.CreateDirectory($"{App.PersistentDataPath(AxibugProtobuf.RomPlatformType.Nes)}/{directPath}"); - } - - public void SaveFile(byte[] fileData, string directPath, string fileName) - { - PrepareDirectory(directPath); - - var fileFullpath = $"{App.PersistentDataPath(AxibugProtobuf.RomPlatformType.Nes)}/{directPath}/{fileName}"; - AxiIO.File.WriteAllBytes(fileFullpath, fileData); - } - - public System.IO.Stream OpenFile(string directPath, string fileName) - { - try - { - var path = $"{App.PersistentDataPath(AxibugProtobuf.RomPlatformType.Nes)}/{directPath}/{fileName}"; - var data = AxiIO.File.ReadAllBytes(path); - if (data == null) return null; - return new System.IO.MemoryStream(data); - } - catch - { - return null; - } - } - - public bool TryGetMapperNo(ROM rom, out int mapperNo) - { - var db = Resources.Load("NES/ROMDB"); - return db.GetMapperNo(rom.GetPROM_CRC(), out mapperNo); +using AxibugEmuOnline.Client.ClientCore; +using AxibugProtobuf; +using AxiReplay; +using System; +using System.Runtime.InteropServices; +using UnityEngine; +using VirtualNes.Core; + +namespace AxibugEmuOnline.Client +{ + public class CoreSupporter : ISupporterImpl + { + + public System.IO.Stream OpenRom(string fname) + { + try + { + var romFile = App.GetRomLib(RomPlatformType.Nes).GetRomFile(fname); + var bytes = romFile.GetRomFileData(); + Debug.Log($"Open {romFile.Alias}"); + return new System.IO.MemoryStream(bytes); + } + catch (Exception ex) + { + Debug.LogError(ex); + return null; + } + } + + public void GetRomPathInfo(string fname, out string fullPath, out string directPath) + { + var romFile = App.GetRomLib(RomPlatformType.Nes).GetRomFile(fname); + UnityEngine.Debug.Assert(romFile != null); + + fullPath = romFile.LocalFilePath; + directPath = System.IO.Path.GetDirectoryName(fullPath); + } + + public System.IO.Stream OpenFile_DISKSYS() + { + return new System.IO.MemoryStream(Resources.Load("NES/Disksys.rom").bytes); + } + + public void SaveSRAMToFile(byte[] sramContent, string romName) + { + string sramDirectoryPath = $"{App.PersistentDataPath(AxibugProtobuf.RomPlatformType.Nes)}/{Config.path.szSavePath}"; + AxiIO.Directory.CreateDirectory(sramDirectoryPath); + romName = System.IO.Path.GetFileNameWithoutExtension(romName); + AxiIO.File.WriteAllBytes($"{sramDirectoryPath}/{romName}.sav", sramContent); + } + + public void SaveDISKToFile(byte[] diskFileContent, string romName) + { + string diskFileDirectoryPath = $"{App.PersistentDataPath(AxibugProtobuf.RomPlatformType.Nes)}/dsv"; + AxiIO.Directory.CreateDirectory(diskFileDirectoryPath); + romName = System.IO.Path.GetFileNameWithoutExtension(romName); + AxiIO.File.WriteAllBytes($"{diskFileDirectoryPath}/{romName}.dsv", diskFileContent); + } + + public EmulatorConfig Config { get; private set; } = new EmulatorConfig(); + public void PrepareDirectory(string directPath) + { + AxiIO.Directory.CreateDirectory($"{App.PersistentDataPath(AxibugProtobuf.RomPlatformType.Nes)}/{directPath}"); + } + + public void SaveFile(byte[] fileData, string directPath, string fileName) + { + PrepareDirectory(directPath); + + var fileFullpath = $"{App.PersistentDataPath(AxibugProtobuf.RomPlatformType.Nes)}/{directPath}/{fileName}"; + AxiIO.File.WriteAllBytes(fileFullpath, fileData); + } + + public System.IO.Stream OpenFile(string directPath, string fileName) + { + try + { + var path = $"{App.PersistentDataPath(AxibugProtobuf.RomPlatformType.Nes)}/{directPath}/{fileName}"; + var data = AxiIO.File.ReadAllBytes(path); + if (data == null) return null; + return new System.IO.MemoryStream(data); + } + catch + { + return null; + } + } + + public bool TryGetMapperNo(ROM rom, out int mapperNo) + { + var db = Resources.Load("NES/ROMDB"); + return db.GetMapperNo(rom.GetPROM_CRC(), out mapperNo); } - public ControllerState FromNet(AxiReplay.ReplayStep step) - { - var temp = new ServerInputSnapShot(); - var result = new ControllerState(); - temp.all = step.InPut; - result.raw0 = temp.p1; - result.raw1 = temp.p2; - result.raw2 = temp.p3; - result.raw3 = temp.p4; - result.valid = true; - - return result; - } - - public uint ToNet(ControllerState state) - { - var temp = new ServerInputSnapShot(); - temp.p1 = (byte)state.raw0; - temp.p2 = (byte)state.raw1; - temp.p3 = (byte)state.raw2; - temp.p4 = (byte)state.raw3; - return (uint)temp.all; - } - - [StructLayout(LayoutKind.Explicit, Size = 8)] - struct ServerInputSnapShot - { - [FieldOffset(0)] - public UInt64 all; - [FieldOffset(0)] - public byte p1; - [FieldOffset(1)] - public byte p2; - [FieldOffset(2)] - public byte p3; - [FieldOffset(3)] - public byte p4; - } - } -} + public ControllerState FromNet(AxiReplay.ReplayStep step) + { + var temp = new ServerInputSnapShot(); + var result = new ControllerState(); + temp.all = step.InPut; + result.raw0 = temp.p1; + result.raw1 = temp.p2; + result.raw2 = temp.p3; + result.raw3 = temp.p4; + result.valid = true; + + return result; + } + + public uint ToNet(ControllerState state) + { + var temp = new ServerInputSnapShot(); + temp.p1 = (byte)state.raw0; + temp.p2 = (byte)state.raw1; + temp.p3 = (byte)state.raw2; + temp.p4 = (byte)state.raw3; + return (uint)temp.all; + } + + [StructLayout(LayoutKind.Explicit, Size = 8)] + struct ServerInputSnapShot + { + [FieldOffset(0)] + public UInt64 all; + [FieldOffset(0)] + public byte p1; + [FieldOffset(1)] + public byte p2; + [FieldOffset(2)] + public byte p3; + [FieldOffset(3)] + public byte p4; + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/NesEmulator/NesEmulator.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/NesEmulator/NesEmulator.cs index e5f8062b..38b31b2b 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/NesEmulator/NesEmulator.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/NesEmulator/NesEmulator.cs @@ -1,137 +1,137 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugProtobuf; -using AxiReplay; -using System; -using System.Diagnostics; -using System.Globalization; -using System.Xml.Linq; -using UnityEngine; -using UnityEngine.UI; -using VirtualNes.Core; -using VirtualNes.Core.Debug; - -namespace AxibugEmuOnline.Client -{ - public class NesEmulator : EmuCore - { - public VideoProvider VideoProvider; - public AudioProvider AudioProvider; - - //模拟器核心实例化对象 - public NES NesCore { get; private set; } - - /// 是否暂停 - public bool IsPause { get; private set; } - public NesControllerMapper ControllerMapper { get; private set; } - - private void Awake() - { - ControllerMapper = new NesControllerMapper(); - } - - private void Start() - { - App.tick.SetFrameRate(60); - VideoProvider.NesEmu = this; - AudioProvider.NesEmu = this; - } - - public override RomPlatformType Platform => RomPlatformType.Nes; - private CoreSupporter m_coreSupporter; - /// - /// 指定ROM开始游戏 - /// - public override MsgBool StartGame(RomFile rom) - { - StopGame(); - - m_coreSupporter = new CoreSupporter(); - Supporter.Setup(m_coreSupporter); - Debuger.Setup(new CoreDebuger()); - - App.GetRomLib(RomPlatformType.Nes).AddRomFile(rom); - - try - { - NesCore = new NES(rom.FileName); - return true; - } - catch (Exception ex) - { - NesCore = null; - App.log.Error(ex.ToString()); - return ex.Message; - } - } - - public override void Pause() - { - IsPause = true; - } - - public override void Resume() - { - IsPause = false; - } - - - public override void DoReset() - { - NesCore.Reset(); - } - - public override void LoadState(object state) - { - NesCore.LoadState((State)state); - } - - public override object GetState() - { - return NesCore.GetState(); - } - - /// - /// 获取即时存档 - /// - /// - public override byte[] GetStateBytes() - { - return NesCore.GetState().ToBytes(); - } - - /// - /// 加载即时存档 - /// - /// - /// - public override void LoadStateFromBytes(byte[] data) - { - var st = new State(); - st.FromByte(data); - NesCore.LoadState(st); - } - - public override uint Frame => NesCore.FrameCount; - - /// - /// 停止游戏 - /// - public void StopGame() - { - NesCore?.Dispose(); - NesCore = null; - } - - //推进帧 - protected override bool OnPushEmulatorFrame(ControllerState inputData) - { - if (NesCore == null || IsPause) return false; - - NesCore.pad.Sync(inputData); - NesCore.EmulateFrame(true); - - return true; +using AxibugEmuOnline.Client.ClientCore; +using AxibugProtobuf; +using AxiReplay; +using System; +using System.Diagnostics; +using System.Globalization; +using System.Xml.Linq; +using UnityEngine; +using UnityEngine.UI; +using VirtualNes.Core; +using VirtualNes.Core.Debug; + +namespace AxibugEmuOnline.Client +{ + public class NesEmulator : EmuCore + { + public VideoProvider VideoProvider; + public AudioProvider AudioProvider; + + //模拟器核心实例化对象 + public NES NesCore { get; private set; } + + /// 是否暂停 + public bool IsPause { get; private set; } + public NesControllerMapper ControllerMapper { get; private set; } + + private void Awake() + { + ControllerMapper = new NesControllerMapper(); + } + + private void Start() + { + App.tick.SetFrameRate(60); + VideoProvider.NesEmu = this; + AudioProvider.NesEmu = this; + } + + public override RomPlatformType Platform => RomPlatformType.Nes; + private CoreSupporter m_coreSupporter; + /// + /// 指定ROM开始游戏 + /// + public override MsgBool StartGame(RomFile rom) + { + StopGame(); + + m_coreSupporter = new CoreSupporter(); + Supporter.Setup(m_coreSupporter); + Debuger.Setup(new CoreDebuger()); + + App.GetRomLib(RomPlatformType.Nes).AddRomFile(rom); + + try + { + NesCore = new NES(rom.FileName); + return true; + } + catch (Exception ex) + { + NesCore = null; + App.log.Error(ex.ToString()); + return ex.Message; + } + } + + public override void Pause() + { + IsPause = true; + } + + public override void Resume() + { + IsPause = false; + } + + + public override void DoReset() + { + NesCore.Reset(); + } + + public override void LoadState(object state) + { + NesCore.LoadState((State)state); + } + + public override object GetState() + { + return NesCore.GetState(); + } + + /// + /// 获取即时存档 + /// + /// + public override byte[] GetStateBytes() + { + return NesCore.GetState().ToBytes(); + } + + /// + /// 加载即时存档 + /// + /// + /// + public override void LoadStateFromBytes(byte[] data) + { + var st = new State(); + st.FromByte(data); + NesCore.LoadState(st); + } + + public override uint Frame => NesCore.FrameCount; + + /// + /// 停止游戏 + /// + public void StopGame() + { + NesCore?.Dispose(); + NesCore = null; + } + + //推进帧 + protected override bool OnPushEmulatorFrame(ControllerState inputData) + { + if (NesCore == null || IsPause) return false; + + NesCore.pad.Sync(inputData); + NesCore.EmulateFrame(true); + + return true; } protected override ControllerState ConvertInputDataFromNet(ReplayStep step) @@ -153,16 +153,16 @@ namespace AxibugEmuOnline.Client { var screenBuffer = NesCore.ppu.GetScreenPtr(); VideoProvider.SetDrawData(screenBuffer); - } - - public override IControllerSetuper GetControllerSetuper() - { - return ControllerMapper; - } - - public override void Dispose() - { - StopGame(); + } + + public override IControllerSetuper GetControllerSetuper() + { + return ControllerMapper; + } + + public override void Dispose() + { + StopGame(); } public override Texture OutputPixel => VideoProvider.OutputPixel; @@ -170,37 +170,37 @@ namespace AxibugEmuOnline.Client public override void GetAudioParams(out int frequency, out int channels) { AudioProvider.GetAudioParams(out frequency, out channels); - } - -#if UNITY_EDITOR - /// - /// 编辑器用 - /// - [Conditional("UNITY_EDITOR")] - [ContextMenu("ImportNesDB")] - public void ImportNesDB() - { - var db = Resources.Load("NES/ROMDB"); - db.Clear(); - - var xmlStr = System.IO.File.ReadAllText("nes20db.xml"); - var xml = XDocument.Parse(xmlStr); - var games = xml.Element("nes20db")?.Elements("game"); - System.Diagnostics.Debug.Assert(games != null, nameof(games) + " != null"); - foreach (var game in games) - { - var crcStr = game.Element("rom")?.Attribute("crc32")?.Value; - var crc = uint.Parse($"{crcStr}", NumberStyles.HexNumber); - - var mapper = int.Parse($"{game.Element("pcb")?.Attribute("mapper")?.Value}"); - - if (mapper > 255) continue; - db.AddInfo(new RomDB.RomInfo { CRC = crc, Mapper = mapper }); - } - - UnityEditor.EditorUtility.SetDirty(db); - UnityEditor.AssetDatabase.SaveAssets(); } -#endif - } + +#if UNITY_EDITOR + /// + /// 编辑器用 + /// + [Conditional("UNITY_EDITOR")] + [ContextMenu("ImportNesDB")] + public void ImportNesDB() + { + var db = Resources.Load("NES/ROMDB"); + db.Clear(); + + var xmlStr = System.IO.File.ReadAllText("nes20db.xml"); + var xml = XDocument.Parse(xmlStr); + var games = xml.Element("nes20db")?.Elements("game"); + System.Diagnostics.Debug.Assert(games != null, nameof(games) + " != null"); + foreach (var game in games) + { + var crcStr = game.Element("rom")?.Attribute("crc32")?.Value; + var crc = uint.Parse($"{crcStr}", NumberStyles.HexNumber); + + var mapper = int.Parse($"{game.Element("pcb")?.Attribute("mapper")?.Value}"); + + if (mapper > 255) continue; + db.AddInfo(new RomDB.RomInfo { CRC = crc, Mapper = mapper }); + } + + UnityEditor.EditorUtility.SetDirty(db); + UnityEditor.AssetDatabase.SaveAssets(); + } +#endif + } } \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/StoicGooseEmulator/UStoicGoose.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/StoicGooseEmulator/UStoicGoose.cs index 5d1705e3..6c15d6c3 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/StoicGooseEmulator/UStoicGoose.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/StoicGooseEmulator/UStoicGoose.cs @@ -1,130 +1,130 @@ -using AxibugEmuOnline.Client; -using AxibugEmuOnline.Client.ClientCore; -using AxibugProtobuf; -using AxiReplay; -using StoicGoose.Common.Utilities; -using StoicGoose.Core.Machines; -using System; -using System.Collections.Generic; -using System.IO.Compression; -using System.Linq; -using UnityEngine; -using UnityEngine.UI; -using CartridgeMetadata = StoicGoose.Core.Cartridges.Metadata; - -public class UStoicGoose : EmuCore -{ - public static UStoicGoose instance; - public static System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew(); - - /* Constants */ - readonly static int maxScreenSizeFactor = 5; - readonly static int maxRecentFiles = 15; - readonly static int statusIconSize = 12; - - readonly static List<(string description, string extension, Func streamReadFunc)> supportedFileInformation = new() - { - ("WonderSwan ROMs", ".ws", GetStreamFromFile), - ("WonderSwan Color ROMs", ".wsc", GetStreamFromFile), - ("Zip Archives", ".zip", GetStreamFromFirstZippedFile) - }; - - /* Various handlers */ - DatabaseHandler databaseHandler = default; - SGVideoPlayer graphicsHandler = default; - SGSoundPlayer soundHandler = default; - SGKeyboard inputHandler = default; - SGLogger loggerHandler = default; - public EmulatorHandler emulatorHandler = default; - private RomPlatformType mPlatform = RomPlatformType.WonderSwan; - - /* Misc. windows */ - //SoundRecorderForm soundRecorderForm = default; - //CheatsForm cheatsForm = default; - - /* Misc. runtime variables */ - Type machineType = default; - bool isVerticalOrientation = false; - string internalEepromPath = string.Empty; - - public string CurrRomName { get; private set; } - - #region 实现IEmuCore - public override RomPlatformType Platform => mPlatform; - - public override uint Frame => (uint)emulatorHandler.AxiEmuRunFrame; - - public override Texture OutputPixel => graphicsHandler.rawBufferWarper; - - public override RawImage DrawCanvas => graphicsHandler.DrawCanvas; - public override object GetState() - { - throw new NotImplementedException(); - } - - public override byte[] GetStateBytes() - { - throw new NotImplementedException(); - } - - public override void LoadState(object state) - { - throw new NotImplementedException(); - } - - public override void LoadStateFromBytes(byte[] data) - { - throw new NotImplementedException(); - } - - public override void Pause() - { - PauseEmulation(); - } - - public override void Resume() - { - UnpauseEmulation(); - } - - public override MsgBool StartGame(RomFile romFile) - { - mPlatform = romFile.Platform; - - Init(); - - - //保存当前正在进行的游戏存档 - if (emulatorHandler != null && !emulatorHandler.IsRunning) - { - SaveAllData(); - } - - if (LoadAndRunCartridge(romFile.LocalFilePath)) - return true; - else - return "Rom加载失败"; - } - - public override void Dispose() - { - //保存当前正在进行的游戏存档 - if (emulatorHandler != null && !emulatorHandler.IsRunning) - { - SaveAllData(); - } - EmuClose(); - } - - public override void DoReset() - { - ResetEmulation(); - } - - public override IControllerSetuper GetControllerSetuper() - { - throw new NotImplementedException(); - } +using AxibugEmuOnline.Client; +using AxibugEmuOnline.Client.ClientCore; +using AxibugProtobuf; +using AxiReplay; +using StoicGoose.Common.Utilities; +using StoicGoose.Core.Machines; +using System; +using System.Collections.Generic; +using System.IO.Compression; +using System.Linq; +using UnityEngine; +using UnityEngine.UI; +using CartridgeMetadata = StoicGoose.Core.Cartridges.Metadata; + +public class UStoicGoose : EmuCore +{ + public static UStoicGoose instance; + public static System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew(); + + /* Constants */ + readonly static int maxScreenSizeFactor = 5; + readonly static int maxRecentFiles = 15; + readonly static int statusIconSize = 12; + + readonly static List<(string description, string extension, Func streamReadFunc)> supportedFileInformation = new() + { + ("WonderSwan ROMs", ".ws", GetStreamFromFile), + ("WonderSwan Color ROMs", ".wsc", GetStreamFromFile), + ("Zip Archives", ".zip", GetStreamFromFirstZippedFile) + }; + + /* Various handlers */ + DatabaseHandler databaseHandler = default; + SGVideoPlayer graphicsHandler = default; + SGSoundPlayer soundHandler = default; + SGKeyboard inputHandler = default; + SGLogger loggerHandler = default; + public EmulatorHandler emulatorHandler = default; + private RomPlatformType mPlatform = RomPlatformType.WonderSwan; + + /* Misc. windows */ + //SoundRecorderForm soundRecorderForm = default; + //CheatsForm cheatsForm = default; + + /* Misc. runtime variables */ + Type machineType = default; + bool isVerticalOrientation = false; + string internalEepromPath = string.Empty; + + public string CurrRomName { get; private set; } + + #region 实现IEmuCore + public override RomPlatformType Platform => mPlatform; + + public override uint Frame => (uint)emulatorHandler.AxiEmuRunFrame; + + public override Texture OutputPixel => graphicsHandler.rawBufferWarper; + + public override RawImage DrawCanvas => graphicsHandler.DrawCanvas; + public override object GetState() + { + throw new NotImplementedException(); + } + + public override byte[] GetStateBytes() + { + throw new NotImplementedException(); + } + + public override void LoadState(object state) + { + throw new NotImplementedException(); + } + + public override void LoadStateFromBytes(byte[] data) + { + throw new NotImplementedException(); + } + + public override void Pause() + { + PauseEmulation(); + } + + public override void Resume() + { + UnpauseEmulation(); + } + + public override MsgBool StartGame(RomFile romFile) + { + mPlatform = romFile.Platform; + + Init(); + + + //保存当前正在进行的游戏存档 + if (emulatorHandler != null && !emulatorHandler.IsRunning) + { + SaveAllData(); + } + + if (LoadAndRunCartridge(romFile.LocalFilePath)) + return true; + else + return "Rom加载失败"; + } + + public override void Dispose() + { + //保存当前正在进行的游戏存档 + if (emulatorHandler != null && !emulatorHandler.IsRunning) + { + SaveAllData(); + } + EmuClose(); + } + + public override void DoReset() + { + ResetEmulation(); + } + + public override IControllerSetuper GetControllerSetuper() + { + throw new NotImplementedException(); + } protected override bool OnPushEmulatorFrame(ulong InputData) { throw new NotImplementedException(); @@ -144,606 +144,606 @@ public class UStoicGoose : EmuCore { throw new NotImplementedException(); } - - protected override void AfterPushFrame() - { - throw new NotImplementedException(); - } - - public override void GetAudioParams(out int frequency, out int channels) - { - throw new NotImplementedException(); - } - #endregion - - //Cheat[] cheats = default; - - #region Unity 生命周期 - - void Awake() - { - //关闭垂直同步 - QualitySettings.vSyncCount = 0; - //设为60帧 - Application.targetFrameRate = 60; - - instance = this; - loggerHandler = new SGLogger(); - graphicsHandler = this.gameObject.GetComponent(); - soundHandler = this.gameObject.GetComponent(); - inputHandler = this.gameObject.GetComponent(); - Log.Initialize(loggerHandler); - Program.InitPath(Application.persistentDataPath); - //Init(); - //LoadAndRunCartridge("G:/BaiduNetdiskDownload/Rockman & Forte - Mirai Kara no Chousen Sha (J) [M][!].ws"); - } - private void Update() - { - if (!emulatorHandler.IsRunning) - return; - - inputHandler.Update_InputData(); - - emulatorHandler.Frame_Update(); - } - void OnDestroy() - { - EmuClose(); - } - #endregion - private void Init() - { - Log.WriteEvent(LogSeverity.Information, this, "Initializing emulator and UI..."); - - machineType = Program.Configuration.General.PreferOriginalWS ? typeof(WonderSwan) : typeof(WonderSwanColor); - - InitializeEmulatorHandler(); - VerifyConfiguration(); - InitializeOtherHandlers(); - //InitializeWindows(); - - //SizeAndPositionWindow(); - SetWindowTitleAndStatus(); - Log.WriteEvent(LogSeverity.Information, this, "Initialization done!"); - } - - - private void EmuClose() - { - SaveAllData(); - emulatorHandler.Shutdown(); - - Program.SaveConfiguration(); - } - - - private void InitializeEmulatorHandler() - { - emulatorHandler = new EmulatorHandler(machineType); - emulatorHandler.SetFpsLimiter(Program.Configuration.General.LimitFps); - } - - private void VerifyConfiguration() - { - foreach (var button in emulatorHandler.Machine.GameControls.Replace(" ", "").Split(',')) - { - if (!Program.Configuration.Input.GameControls.ContainsKey(button)) - Program.Configuration.Input.GameControls[button] = new(); - } - - foreach (var button in emulatorHandler.Machine.HardwareControls.Replace(" ", "").Split(',')) - { - if (!Program.Configuration.Input.SystemControls.ContainsKey(button)) - Program.Configuration.Input.SystemControls[button] = new(); - } - - if (Program.Configuration.Video.ScreenSize < 2 || Program.Configuration.Video.ScreenSize > maxScreenSizeFactor) - Program.Configuration.Video.ResetToDefault(nameof(Program.Configuration.Video.ScreenSize)); - - //if (string.IsNullOrEmpty(Program.Configuration.Video.Shader) || (graphicsHandler != null && !graphicsHandler.AvailableShaders.Contains(Program.Configuration.Video.Shader))) - // Program.Configuration.Video.Shader = GraphicsHandler.DefaultShaderName; - } - - private void InitializeOtherHandlers() - { - databaseHandler = new DatabaseHandler(); - - //statusIconsLocation = machineType == typeof(WonderSwan) ? new(0, DisplayControllerCommon.ScreenHeight) : new(DisplayControllerCommon.ScreenWidth, 0); - - //TODO graphicsHandler基本参数,可能需要补上 - //graphicsHandler = new GraphicsHandler(machineType, new(emulatorHandler.Machine.ScreenWidth, emulatorHandler.Machine.ScreenHeight), statusIconsLocation, statusIconSize, machineType != typeof(WonderSwan), Program.Configuration.Video.Shader) - //{ - // IsVerticalOrientation = isVerticalOrientation - //}; - - //TODO 声音基本参数,可能需要补上 - //soundHandler = new SoundHandler(44100, 2); - //soundHandler.SetVolume(1.0f); - //soundHandler.SetMute(Program.Configuration.Sound.Mute); - //soundHandler.SetLowPassFilter(Program.Configuration.Sound.LowPassFilter); - - //TODO Input基本参数,可能需要补上 - //inputHandler = new InputHandler(renderControl); - //inputHandler.SetKeyMapping(Program.Configuration.Input.GameControls, Program.Configuration.Input.SystemControls); - //inputHandler.SetVerticalOrientation(isVerticalOrientation); - //inputHandler.SetEnableRemapping(Program.Configuration.Input.AutoRemap); - //inputHandler.SetVerticalRemapping(emulatorHandler.Machine.VerticalControlRemap - // .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) - // .Select(x => x.Split('=', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)) - // .ToDictionary(x => x[0], x => x[1])); - - - emulatorHandler.Machine.DisplayController.SendFramebuffer = graphicsHandler.UpdateScreen; - emulatorHandler.Machine.SoundController.SendSamples = (s) => - { - soundHandler.EnqueueSamples(s); - //soundRecorderForm.EnqueueSamples(s); - }; - - emulatorHandler.Machine.ReceiveInput += () => - { - //var buttonsPressed = new List(); - //var buttonsHeld = new List(); - - //inputHandler.PollInput(ref buttonsPressed, ref buttonsHeld); - long buttonsHeld = 0; - inputHandler.PollInput(ref buttonsHeld); - return buttonsHeld; - //if (buttonsPressed.Contains("Volume")) - // emulatorHandler.Machine.SoundController.ChangeMasterVolume(); - - //return (buttonsPressed, buttonsHeld); - }; - - //renderControl.Resize += (s, e) => { if (s is Control control) graphicsHandler.Resize(control.ClientRectangle); }; - //renderControl.Paint += (s, e) => - //{ - // graphicsHandler.SetClearColor(Color.Black); - - // graphicsHandler.ClearFrame(); - - // if (emulatorHandler.Machine is MachineCommon machine) - // { - // var activeIcons = new List() { "Power" }; - - // if (machine.BuiltInSelfTestOk) activeIcons.Add("Initialized"); - - // if (machine.DisplayController.IconSleep) activeIcons.Add("Sleep"); - // if (machine.DisplayController.IconVertical) activeIcons.Add("Vertical"); - // if (machine.DisplayController.IconHorizontal) activeIcons.Add("Horizontal"); - // if (machine.DisplayController.IconAux1) activeIcons.Add("Aux1"); - // if (machine.DisplayController.IconAux2) activeIcons.Add("Aux2"); - // if (machine.DisplayController.IconAux3) activeIcons.Add("Aux3"); - - // if (machine.SoundController.HeadphonesConnected) activeIcons.Add("Headphones"); - // if (machine.SoundController.MasterVolume == 0) activeIcons.Add("Volume0"); - // if (machine.SoundController.MasterVolume == 1) activeIcons.Add("Volume1"); - // if (machine.SoundController.MasterVolume == 2) activeIcons.Add("Volume2"); - // if (machine.SoundController.MasterVolume == 3 && machine is WonderSwanColor) activeIcons.Add("Volume3"); - - // graphicsHandler.UpdateStatusIcons(activeIcons); - // } - // graphicsHandler.DrawFrame(); - //}; - - internalEepromPath = System.IO.Path.Combine(Program.InternalDataPath, $"{machineType.Name}.eep"); - } - - //private void InitializeWindows() - //{ - // soundRecorderForm = new(soundHandler.SampleRate, soundHandler.NumChannels); - // cheatsForm = new() - // { - // Callback = (c) => - // { - // if (emulatorHandler.IsRunning) - // cheats = (Cheat[])c.Clone(); - // } - // }; - //} - - private void SizeAndPositionWindow() - { - graphicsHandler.SetSize(emulatorHandler.Machine.ScreenWidth, emulatorHandler.Machine.ScreenHeight); - //if (WindowState == For emulatorHandler.Machine.ScreenHeight;mWindowState.Maximized) - // WindowState = FormWindowState.Normal; - - //MinimumSize = SizeFromClientSize(CalculateRequiredClientSize(2)); - //Size = SizeFromClientSize(CalculateRequiredClientSize(Program.Configuration.Video.ScreenSize)); - //var screen = Screen.FromControl(this); - //var workingArea = screen.WorkingArea; - //Location = new Point() - //{ - // X = Math.Max(workingArea.X, workingArea.X + (workingArea.Width - Width) / 2), - // Y = Math.Max(workingArea.Y, workingArea.Y + (workingArea.Height - Height) / 2) - //}; - } - - - //TODO 设置屏幕宽高 看是否需要 - //private Size CalculateRequiredClientSize(int screenSize) - //{ - // if (emulatorHandler == null || graphicsHandler == null) - // return ClientSize; - - // var statusIconsOnRight = statusIconsLocation.X > statusIconsLocation.Y; - - // int screenWidth, screenHeight; - - // if (!isVerticalOrientation) - // { - // screenWidth = emulatorHandler.Machine.ScreenWidth; - // screenHeight = emulatorHandler.Machine.ScreenHeight; - // if (statusIconsOnRight) screenWidth += statusIconSize; - // if (!statusIconsOnRight) screenHeight += statusIconSize; - // } - // else - // { - // screenWidth = emulatorHandler.Machine.ScreenHeight; - // screenHeight = emulatorHandler.Machine.ScreenWidth; - // if (!statusIconsOnRight) screenWidth += statusIconSize; - // if (statusIconsOnRight) screenHeight += statusIconSize; - // } - - // return new(screenWidth * screenSize, (screenHeight * screenSize) + menuStrip.Height + statusStrip.Height); - //} - - private void SetWindowTitleAndStatus() - { - //TODO 修改为状态字符串,显示在某个地方 - - //var titleStringBuilder = new StringBuilder(); - - //titleStringBuilder.Append($"{Application.ProductName} {Program.GetVersionString(false)}"); - - //if (emulatorHandler.Machine.Cartridge.IsLoaded) - //{ - // titleStringBuilder.Append($" - [{Path.GetFileName(Program.Configuration.General.RecentFiles.First())}]"); - - // var statusStringBuilder = new StringBuilder(); - // statusStringBuilder.Append($"Emulating {emulatorHandler.Machine.Manufacturer} {emulatorHandler.Machine.Model}, "); - // statusStringBuilder.Append($"playing {databaseHandler.GetGameTitle(emulatorHandler.Machine.Cartridge.Crc32, emulatorHandler.Machine.Cartridge.SizeInBytes)} ({emulatorHandler.Machine.Cartridge.Metadata.GameIdString})"); - - // tsslStatus.Text = statusStringBuilder.ToString(); - // tsslEmulationStatus.Text = emulatorHandler.IsRunning ? (emulatorHandler.IsPaused ? "Paused" : "Running") : "Stopped"; - //} - //else - //{ - // tsslStatus.Text = "Ready"; - // tsslEmulationStatus.Text = "Stopped"; - //} - - //Text = titleStringBuilder.ToString(); - } - - private void LoadBootstrap(string filename) - { - if (GlobalVariables.EnableSkipBootstrapIfFound) return; - - if (!emulatorHandler.IsRunning) - { - if (AxiIO.File.Exists(filename)) - { - //using var stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - //var data = new byte[stream.Length]; - //stream.Read(data, 0, data.Length); - - var data = AxiIO.File.ReadAllBytes(filename); - - emulatorHandler.Machine.LoadBootstrap(data); - } - emulatorHandler.Machine.UseBootstrap = Program.Configuration.General.UseBootstrap; - } - } - - private void LoadInternalEeprom() - { - if (!emulatorHandler.IsRunning && AxiIO.File.Exists(internalEepromPath)) - { - //using var stream = new FileStream(internalEepromPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - //var data = new byte[stream.Length]; - //stream.Read(data, 0, data.Length); - - var data = AxiIO.File.ReadAllBytes(internalEepromPath); - - emulatorHandler.Machine.LoadInternalEeprom(data); - } - } - - private static System.IO.Stream GetStreamFromFile(string filename) - { - //return new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - byte[] data = AxiIO.File.ReadAllBytes(filename); - return new System.IO.MemoryStream(data); - } - - private static System.IO.Stream GetStreamFromFirstZippedFile(string filename) - { - //return new ZipArchive(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)).Entries.FirstOrDefault()?.Open(); - - byte[] data = AxiIO.File.ReadAllBytes(filename); - return new ZipArchive(new System.IO.MemoryStream(data)).Entries.FirstOrDefault()?.Open(); - } - - private bool LoadAndRunCartridge(string filename) - { - try - { - if (emulatorHandler.IsRunning) - { - SaveAllData(); - emulatorHandler.Shutdown(); - } - - using var inputStream = supportedFileInformation.FirstOrDefault(x => x.extension == System.IO.Path.GetExtension(filename)).streamReadFunc(filename) ?? GetStreamFromFile(filename); - using var stream = new System.IO.MemoryStream(); - inputStream.CopyTo(stream); - stream.Position = 0; - - var data = new byte[stream.Length]; - stream.Read(data, 0, data.Length); - emulatorHandler.Machine.LoadRom(data); - - graphicsHandler.IsVerticalOrientation = isVerticalOrientation = emulatorHandler.Machine.Cartridge.Metadata.Orientation == CartridgeMetadata.Orientations.Vertical; - inputHandler.SetVerticalOrientation(isVerticalOrientation); - - CurrRomName = System.IO.Path.GetFileName(filename); - - LoadRam(); - - LoadBootstrap(emulatorHandler.Machine is WonderSwan ? Program.Configuration.General.BootstrapFile : Program.Configuration.General.BootstrapFileWSC); - LoadInternalEeprom(); - - //初始化音频 - soundHandler.Initialize(); - - emulatorHandler.Startup(); - - SizeAndPositionWindow(); - SetWindowTitleAndStatus(); - - Program.SaveConfiguration(); - return true; - } - catch (Exception ex) when (!AppEnvironment.DebugMode) - { - App.log.Error("ex=>"+ex.ToString()); - return false; - } - } - - private void LoadRam() - { - //var path = Path.Combine(Program.SaveDataPath, $"{Path.GetFileNameWithoutExtension(Program.Configuration.General.RecentFiles.First())}.sav"); - var path = System.IO.Path.Combine(Program.SaveDataPath, $"{CurrRomName}.sav"); - //if (!File.Exists(path)) return; - if (!AxiIO.File.Exists(path)) return; - - //using var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - //var data = new byte[stream.Length]; - //stream.Read(data, 0, data.Length); - - var data = AxiIO.File.ReadAllBytes(path); - if (data.Length != 0) - emulatorHandler.Machine.LoadSaveData(data); - } - - private void SaveAllData() - { - SaveInternalEeprom(); - SaveRam(); - } - - private void SaveInternalEeprom() - { - var data = emulatorHandler.Machine.GetInternalEeprom(); - if (data.Length == 0) return; - - //using var stream = new FileStream(internalEepromPath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite); - //stream.Write(data, 0, data.Length); - - AxiIO.File.WriteAllBytes(internalEepromPath, data); - } - - private void SaveRam() - { - var data = emulatorHandler.Machine.GetSaveData(); - if (data.Length == 0) return; - - //var path = Path.Combine(Program.SaveDataPath, $"{Path.GetFileNameWithoutExtension(Program.Configuration.General.RecentFiles.First())}.sav"); - var path = System.IO.Path.Combine(Program.SaveDataPath, $"{CurrRomName}.sav"); - - //using var stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite); - //stream.Write(data, 0, data.Length); - - AxiIO.File.WriteAllBytes(path, data); - } - - - private void PauseEmulation() - { - if (!emulatorHandler.IsRunning) return; - - emulatorHandler.Pause(); - soundHandler.Pause(); - - SetWindowTitleAndStatus(); - } - - private void UnpauseEmulation() - { - if (!emulatorHandler.IsRunning) return; - - emulatorHandler.Unpause(); - soundHandler.Unpause(); - - SetWindowTitleAndStatus(); - } - - private void ResetEmulation() - { - SaveAllData(); - emulatorHandler.Reset(); - - Program.SaveConfiguration(); - } - -} - -static class Program -{ - static string jsonConfigFileName;//= "Config.json"; - static string logFileName;//= "Log.txt"; - static string internalDataDirectoryName;//= "Internal"; - static string saveDataDirectoryName;//= "Saves"; - static string cheatDataDirectoryName;//= "Cheats"; - static string debuggingDataDirectoryName;//= "Debugging"; - static string assetsDirectoryName;//= "Assets"; - static string shaderDirectoryName;//= "Shaders"; - static string noIntroDatDirectoryName;//= "No-Intro"; - static string mutexName;//= $"Unity_{GetVersionDetails()}"; - static string programDataDirectory;//= Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), Application.ProductName); - static string programConfigPath;//= Path.Combine(programDataDirectory, jsonConfigFileName); - - public static Configuration Configuration;// { get; private set; } = LoadConfiguration(programConfigPath); - - public static string DataPath;//{ get; } = string.Empty; - public static string InternalDataPath;//{ get; } = string.Empty; - public static string SaveDataPath;//{ get; } = string.Empty; - public static string CheatsDataPath;//{ get; } = string.Empty; - public static string DebuggingDataPath;//{ get; } = string.Empty; - - static string programApplicationDirectory;// = AppDomain.CurrentDomain.BaseDirectory; - static string programAssetsDirectory;// = Path.Combine(programApplicationDirectory, assetsDirectoryName); - - //public static string ShaderPath { get; } = string.Empty; - public static string NoIntroDatPath;// { get; } = string.Empty; - - //static MainForm mainForm = default; - - public static void InitPath(string CustonDataDir) - { - try - { - jsonConfigFileName = "Config.json"; - logFileName = "Log.txt"; - internalDataDirectoryName = "Internal"; - saveDataDirectoryName = "Saves"; - cheatDataDirectoryName = "Cheats"; - debuggingDataDirectoryName = "Debugging"; - assetsDirectoryName = "Assets"; - shaderDirectoryName = "Shaders"; - noIntroDatDirectoryName = "No-Intro"; - mutexName = $"Unity_{GetVersionDetails()}"; - programDataDirectory = System.IO.Path.Combine(CustonDataDir, "AxibugEmu"); - programConfigPath = System.IO.Path.Combine(programDataDirectory, jsonConfigFileName); - Configuration = LoadConfiguration(programConfigPath); - Log.WriteLine(System.IO.Path.Combine(programDataDirectory, logFileName)); - programApplicationDirectory = AppDomain.CurrentDomain.BaseDirectory; - programAssetsDirectory = System.IO.Path.Combine(programApplicationDirectory, assetsDirectoryName); - AxiIO.Directory.CreateDirectory(DataPath = programDataDirectory); - AxiIO.Directory.CreateDirectory(InternalDataPath = System.IO.Path.Combine(programDataDirectory, internalDataDirectoryName)); - AxiIO.Directory.CreateDirectory(SaveDataPath = System.IO.Path.Combine(programDataDirectory, saveDataDirectoryName)); - AxiIO.Directory.CreateDirectory(CheatsDataPath = System.IO.Path.Combine(programDataDirectory, cheatDataDirectoryName)); - AxiIO.Directory.CreateDirectory(DebuggingDataPath = System.IO.Path.Combine(programDataDirectory, debuggingDataDirectoryName)); - - //if (!Directory.Exists(ShaderPath = Path.Combine(programAssetsDirectory, shaderDirectoryName))) - // throw new DirectoryNotFoundException("Shader directory missing"); - - if (!AxiIO.Directory.Exists(NoIntroDatPath = System.IO.Path.Combine(programAssetsDirectory, noIntroDatDirectoryName))) - throw new Exception("No-Intro .dat directory missing"); - } - catch (Exception e) - { - } - } - - //[STAThread] - //static void Main() - //{ - // using var mutex = new Mutex(true, mutexName, out bool newInstance); - // if (!newInstance) - // { - // MessageBox.Show($"Another instance of {Application.ProductName} is already running.\n\nThis instance will now shut down.", - // $"{Application.ProductName} Startup Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - // Environment.Exit(-1); - // } - - // Application.SetHighDpiMode(HighDpiMode.SystemAware); - // Application.EnableVisualStyles(); - // Application.SetCompatibleTextRenderingDefault(false); - - // if (!Debugger.IsAttached) - // { - // Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException); - // Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); - // AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); - // } - - // Application.Run(mainForm = new MainForm()); - //} - - //static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) - //{ - // if (e.Exception is GLFWException glEx) - // { - // var renderControl = mainForm.Controls["renderControl"] as OpenGL.RenderControl; - // MessageBox.Show($"{glEx.Message.EnsureEndsWithPeriod()}\n\n{Application.ProductName} requires GPU and drivers supporting OpenGL {renderControl.APIVersion.Major}.{renderControl.APIVersion.Minor}.", $"{Application.ProductName} Startup Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - // } - // else - // { - // MessageBox.Show(e.Exception.Message.EnsureEndsWithPeriod(), $"{Application.ProductName} Startup Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - // } - - // Environment.Exit(-1); - //} - - //static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) - //{ - // MessageBox.Show((e.ExceptionObject as Exception).Message, $"{Application.ProductName} Startup Error"); - // Environment.Exit(-1); - //} - - private static Configuration LoadConfiguration(string filename) - { - AxiIO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(filename)); - - Configuration configuration; - //if (!File.Exists(filename) || (configuration = filename.DeserializeFromFile()) == null) - //{ - // configuration = new Configuration(); - // configuration.SerializeToFile(filename); - //} - - configuration = new Configuration(); - - return configuration; - } - - public static void ReplaceConfiguration(Configuration newConfig) - { - ConfigurationBase.CopyConfiguration(newConfig, Configuration); - SaveConfiguration(); - } - - public static void SaveConfiguration() - { - //Configuration?.SerializeToFile(programConfigPath); - } - - private static string GetVersionDetails() - { - //return $"{ThisAssembly.Git.Branch}-{ThisAssembly.Git.Commit}{(ThisAssembly.Git.IsDirty ? "-dirty" : string.Empty)}{(GlobalVariables.IsDebugBuild ? "+debug" : string.Empty)}"; - return $"{(GlobalVariables.IsDebugBuild ? "+debug" : string.Empty)}"; - } - - //public static string GetVersionString(bool detailed) - //{ - // var version = new Version(Application.ProductVersion); - // var stringBuilder = new StringBuilder(); - // stringBuilder.Append($"v{version.Major:D3}{(version.Minor != 0 ? $".{version.Minor}" : string.Empty)}"); - // if (detailed) stringBuilder.Append($" ({GetVersionDetails()})"); - // return stringBuilder.ToString(); - //} -} - + + protected override void AfterPushFrame() + { + throw new NotImplementedException(); + } + + public override void GetAudioParams(out int frequency, out int channels) + { + throw new NotImplementedException(); + } + #endregion + + //Cheat[] cheats = default; + + #region Unity 生命周期 + + void Awake() + { + //关闭垂直同步 + QualitySettings.vSyncCount = 0; + //设为60帧 + Application.targetFrameRate = 60; + + instance = this; + loggerHandler = new SGLogger(); + graphicsHandler = this.gameObject.GetComponent(); + soundHandler = this.gameObject.GetComponent(); + inputHandler = this.gameObject.GetComponent(); + Log.Initialize(loggerHandler); + Program.InitPath(Application.persistentDataPath); + //Init(); + //LoadAndRunCartridge("G:/BaiduNetdiskDownload/Rockman & Forte - Mirai Kara no Chousen Sha (J) [M][!].ws"); + } + private void Update() + { + if (!emulatorHandler.IsRunning) + return; + + inputHandler.Update_InputData(); + + emulatorHandler.Frame_Update(); + } + void OnDestroy() + { + EmuClose(); + } + #endregion + private void Init() + { + Log.WriteEvent(LogSeverity.Information, this, "Initializing emulator and UI..."); + + machineType = Program.Configuration.General.PreferOriginalWS ? typeof(WonderSwan) : typeof(WonderSwanColor); + + InitializeEmulatorHandler(); + VerifyConfiguration(); + InitializeOtherHandlers(); + //InitializeWindows(); + + //SizeAndPositionWindow(); + SetWindowTitleAndStatus(); + Log.WriteEvent(LogSeverity.Information, this, "Initialization done!"); + } + + + private void EmuClose() + { + SaveAllData(); + emulatorHandler.Shutdown(); + + Program.SaveConfiguration(); + } + + + private void InitializeEmulatorHandler() + { + emulatorHandler = new EmulatorHandler(machineType); + emulatorHandler.SetFpsLimiter(Program.Configuration.General.LimitFps); + } + + private void VerifyConfiguration() + { + foreach (var button in emulatorHandler.Machine.GameControls.Replace(" ", "").Split(',')) + { + if (!Program.Configuration.Input.GameControls.ContainsKey(button)) + Program.Configuration.Input.GameControls[button] = new(); + } + + foreach (var button in emulatorHandler.Machine.HardwareControls.Replace(" ", "").Split(',')) + { + if (!Program.Configuration.Input.SystemControls.ContainsKey(button)) + Program.Configuration.Input.SystemControls[button] = new(); + } + + if (Program.Configuration.Video.ScreenSize < 2 || Program.Configuration.Video.ScreenSize > maxScreenSizeFactor) + Program.Configuration.Video.ResetToDefault(nameof(Program.Configuration.Video.ScreenSize)); + + //if (string.IsNullOrEmpty(Program.Configuration.Video.Shader) || (graphicsHandler != null && !graphicsHandler.AvailableShaders.Contains(Program.Configuration.Video.Shader))) + // Program.Configuration.Video.Shader = GraphicsHandler.DefaultShaderName; + } + + private void InitializeOtherHandlers() + { + databaseHandler = new DatabaseHandler(); + + //statusIconsLocation = machineType == typeof(WonderSwan) ? new(0, DisplayControllerCommon.ScreenHeight) : new(DisplayControllerCommon.ScreenWidth, 0); + + //TODO graphicsHandler基本参数,可能需要补上 + //graphicsHandler = new GraphicsHandler(machineType, new(emulatorHandler.Machine.ScreenWidth, emulatorHandler.Machine.ScreenHeight), statusIconsLocation, statusIconSize, machineType != typeof(WonderSwan), Program.Configuration.Video.Shader) + //{ + // IsVerticalOrientation = isVerticalOrientation + //}; + + //TODO 声音基本参数,可能需要补上 + //soundHandler = new SoundHandler(44100, 2); + //soundHandler.SetVolume(1.0f); + //soundHandler.SetMute(Program.Configuration.Sound.Mute); + //soundHandler.SetLowPassFilter(Program.Configuration.Sound.LowPassFilter); + + //TODO Input基本参数,可能需要补上 + //inputHandler = new InputHandler(renderControl); + //inputHandler.SetKeyMapping(Program.Configuration.Input.GameControls, Program.Configuration.Input.SystemControls); + //inputHandler.SetVerticalOrientation(isVerticalOrientation); + //inputHandler.SetEnableRemapping(Program.Configuration.Input.AutoRemap); + //inputHandler.SetVerticalRemapping(emulatorHandler.Machine.VerticalControlRemap + // .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) + // .Select(x => x.Split('=', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)) + // .ToDictionary(x => x[0], x => x[1])); + + + emulatorHandler.Machine.DisplayController.SendFramebuffer = graphicsHandler.UpdateScreen; + emulatorHandler.Machine.SoundController.SendSamples = (s) => + { + soundHandler.EnqueueSamples(s); + //soundRecorderForm.EnqueueSamples(s); + }; + + emulatorHandler.Machine.ReceiveInput += () => + { + //var buttonsPressed = new List(); + //var buttonsHeld = new List(); + + //inputHandler.PollInput(ref buttonsPressed, ref buttonsHeld); + long buttonsHeld = 0; + inputHandler.PollInput(ref buttonsHeld); + return buttonsHeld; + //if (buttonsPressed.Contains("Volume")) + // emulatorHandler.Machine.SoundController.ChangeMasterVolume(); + + //return (buttonsPressed, buttonsHeld); + }; + + //renderControl.Resize += (s, e) => { if (s is Control control) graphicsHandler.Resize(control.ClientRectangle); }; + //renderControl.Paint += (s, e) => + //{ + // graphicsHandler.SetClearColor(Color.Black); + + // graphicsHandler.ClearFrame(); + + // if (emulatorHandler.Machine is MachineCommon machine) + // { + // var activeIcons = new List() { "Power" }; + + // if (machine.BuiltInSelfTestOk) activeIcons.Add("Initialized"); + + // if (machine.DisplayController.IconSleep) activeIcons.Add("Sleep"); + // if (machine.DisplayController.IconVertical) activeIcons.Add("Vertical"); + // if (machine.DisplayController.IconHorizontal) activeIcons.Add("Horizontal"); + // if (machine.DisplayController.IconAux1) activeIcons.Add("Aux1"); + // if (machine.DisplayController.IconAux2) activeIcons.Add("Aux2"); + // if (machine.DisplayController.IconAux3) activeIcons.Add("Aux3"); + + // if (machine.SoundController.HeadphonesConnected) activeIcons.Add("Headphones"); + // if (machine.SoundController.MasterVolume == 0) activeIcons.Add("Volume0"); + // if (machine.SoundController.MasterVolume == 1) activeIcons.Add("Volume1"); + // if (machine.SoundController.MasterVolume == 2) activeIcons.Add("Volume2"); + // if (machine.SoundController.MasterVolume == 3 && machine is WonderSwanColor) activeIcons.Add("Volume3"); + + // graphicsHandler.UpdateStatusIcons(activeIcons); + // } + // graphicsHandler.DrawFrame(); + //}; + + internalEepromPath = System.IO.Path.Combine(Program.InternalDataPath, $"{machineType.Name}.eep"); + } + + //private void InitializeWindows() + //{ + // soundRecorderForm = new(soundHandler.SampleRate, soundHandler.NumChannels); + // cheatsForm = new() + // { + // Callback = (c) => + // { + // if (emulatorHandler.IsRunning) + // cheats = (Cheat[])c.Clone(); + // } + // }; + //} + + private void SizeAndPositionWindow() + { + graphicsHandler.SetSize(emulatorHandler.Machine.ScreenWidth, emulatorHandler.Machine.ScreenHeight); + //if (WindowState == For emulatorHandler.Machine.ScreenHeight;mWindowState.Maximized) + // WindowState = FormWindowState.Normal; + + //MinimumSize = SizeFromClientSize(CalculateRequiredClientSize(2)); + //Size = SizeFromClientSize(CalculateRequiredClientSize(Program.Configuration.Video.ScreenSize)); + //var screen = Screen.FromControl(this); + //var workingArea = screen.WorkingArea; + //Location = new Point() + //{ + // X = Math.Max(workingArea.X, workingArea.X + (workingArea.Width - Width) / 2), + // Y = Math.Max(workingArea.Y, workingArea.Y + (workingArea.Height - Height) / 2) + //}; + } + + + //TODO 设置屏幕宽高 看是否需要 + //private Size CalculateRequiredClientSize(int screenSize) + //{ + // if (emulatorHandler == null || graphicsHandler == null) + // return ClientSize; + + // var statusIconsOnRight = statusIconsLocation.X > statusIconsLocation.Y; + + // int screenWidth, screenHeight; + + // if (!isVerticalOrientation) + // { + // screenWidth = emulatorHandler.Machine.ScreenWidth; + // screenHeight = emulatorHandler.Machine.ScreenHeight; + // if (statusIconsOnRight) screenWidth += statusIconSize; + // if (!statusIconsOnRight) screenHeight += statusIconSize; + // } + // else + // { + // screenWidth = emulatorHandler.Machine.ScreenHeight; + // screenHeight = emulatorHandler.Machine.ScreenWidth; + // if (!statusIconsOnRight) screenWidth += statusIconSize; + // if (statusIconsOnRight) screenHeight += statusIconSize; + // } + + // return new(screenWidth * screenSize, (screenHeight * screenSize) + menuStrip.Height + statusStrip.Height); + //} + + private void SetWindowTitleAndStatus() + { + //TODO 修改为状态字符串,显示在某个地方 + + //var titleStringBuilder = new StringBuilder(); + + //titleStringBuilder.Append($"{Application.ProductName} {Program.GetVersionString(false)}"); + + //if (emulatorHandler.Machine.Cartridge.IsLoaded) + //{ + // titleStringBuilder.Append($" - [{Path.GetFileName(Program.Configuration.General.RecentFiles.First())}]"); + + // var statusStringBuilder = new StringBuilder(); + // statusStringBuilder.Append($"Emulating {emulatorHandler.Machine.Manufacturer} {emulatorHandler.Machine.Model}, "); + // statusStringBuilder.Append($"playing {databaseHandler.GetGameTitle(emulatorHandler.Machine.Cartridge.Crc32, emulatorHandler.Machine.Cartridge.SizeInBytes)} ({emulatorHandler.Machine.Cartridge.Metadata.GameIdString})"); + + // tsslStatus.Text = statusStringBuilder.ToString(); + // tsslEmulationStatus.Text = emulatorHandler.IsRunning ? (emulatorHandler.IsPaused ? "Paused" : "Running") : "Stopped"; + //} + //else + //{ + // tsslStatus.Text = "Ready"; + // tsslEmulationStatus.Text = "Stopped"; + //} + + //Text = titleStringBuilder.ToString(); + } + + private void LoadBootstrap(string filename) + { + if (GlobalVariables.EnableSkipBootstrapIfFound) return; + + if (!emulatorHandler.IsRunning) + { + if (AxiIO.File.Exists(filename)) + { + //using var stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + //var data = new byte[stream.Length]; + //stream.Read(data, 0, data.Length); + + var data = AxiIO.File.ReadAllBytes(filename); + + emulatorHandler.Machine.LoadBootstrap(data); + } + emulatorHandler.Machine.UseBootstrap = Program.Configuration.General.UseBootstrap; + } + } + + private void LoadInternalEeprom() + { + if (!emulatorHandler.IsRunning && AxiIO.File.Exists(internalEepromPath)) + { + //using var stream = new FileStream(internalEepromPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + //var data = new byte[stream.Length]; + //stream.Read(data, 0, data.Length); + + var data = AxiIO.File.ReadAllBytes(internalEepromPath); + + emulatorHandler.Machine.LoadInternalEeprom(data); + } + } + + private static System.IO.Stream GetStreamFromFile(string filename) + { + //return new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + byte[] data = AxiIO.File.ReadAllBytes(filename); + return new System.IO.MemoryStream(data); + } + + private static System.IO.Stream GetStreamFromFirstZippedFile(string filename) + { + //return new ZipArchive(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)).Entries.FirstOrDefault()?.Open(); + + byte[] data = AxiIO.File.ReadAllBytes(filename); + return new ZipArchive(new System.IO.MemoryStream(data)).Entries.FirstOrDefault()?.Open(); + } + + private bool LoadAndRunCartridge(string filename) + { + try + { + if (emulatorHandler.IsRunning) + { + SaveAllData(); + emulatorHandler.Shutdown(); + } + + using var inputStream = supportedFileInformation.FirstOrDefault(x => x.extension == System.IO.Path.GetExtension(filename)).streamReadFunc(filename) ?? GetStreamFromFile(filename); + using var stream = new System.IO.MemoryStream(); + inputStream.CopyTo(stream); + stream.Position = 0; + + var data = new byte[stream.Length]; + stream.Read(data, 0, data.Length); + emulatorHandler.Machine.LoadRom(data); + + graphicsHandler.IsVerticalOrientation = isVerticalOrientation = emulatorHandler.Machine.Cartridge.Metadata.Orientation == CartridgeMetadata.Orientations.Vertical; + inputHandler.SetVerticalOrientation(isVerticalOrientation); + + CurrRomName = System.IO.Path.GetFileName(filename); + + LoadRam(); + + LoadBootstrap(emulatorHandler.Machine is WonderSwan ? Program.Configuration.General.BootstrapFile : Program.Configuration.General.BootstrapFileWSC); + LoadInternalEeprom(); + + //初始化音频 + soundHandler.Initialize(); + + emulatorHandler.Startup(); + + SizeAndPositionWindow(); + SetWindowTitleAndStatus(); + + Program.SaveConfiguration(); + return true; + } + catch (Exception ex) when (!AppEnvironment.DebugMode) + { + App.log.Error("ex=>"+ex.ToString()); + return false; + } + } + + private void LoadRam() + { + //var path = Path.Combine(Program.SaveDataPath, $"{Path.GetFileNameWithoutExtension(Program.Configuration.General.RecentFiles.First())}.sav"); + var path = System.IO.Path.Combine(Program.SaveDataPath, $"{CurrRomName}.sav"); + //if (!File.Exists(path)) return; + if (!AxiIO.File.Exists(path)) return; + + //using var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + //var data = new byte[stream.Length]; + //stream.Read(data, 0, data.Length); + + var data = AxiIO.File.ReadAllBytes(path); + if (data.Length != 0) + emulatorHandler.Machine.LoadSaveData(data); + } + + private void SaveAllData() + { + SaveInternalEeprom(); + SaveRam(); + } + + private void SaveInternalEeprom() + { + var data = emulatorHandler.Machine.GetInternalEeprom(); + if (data.Length == 0) return; + + //using var stream = new FileStream(internalEepromPath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite); + //stream.Write(data, 0, data.Length); + + AxiIO.File.WriteAllBytes(internalEepromPath, data); + } + + private void SaveRam() + { + var data = emulatorHandler.Machine.GetSaveData(); + if (data.Length == 0) return; + + //var path = Path.Combine(Program.SaveDataPath, $"{Path.GetFileNameWithoutExtension(Program.Configuration.General.RecentFiles.First())}.sav"); + var path = System.IO.Path.Combine(Program.SaveDataPath, $"{CurrRomName}.sav"); + + //using var stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite); + //stream.Write(data, 0, data.Length); + + AxiIO.File.WriteAllBytes(path, data); + } + + + private void PauseEmulation() + { + if (!emulatorHandler.IsRunning) return; + + emulatorHandler.Pause(); + soundHandler.Pause(); + + SetWindowTitleAndStatus(); + } + + private void UnpauseEmulation() + { + if (!emulatorHandler.IsRunning) return; + + emulatorHandler.Unpause(); + soundHandler.Unpause(); + + SetWindowTitleAndStatus(); + } + + private void ResetEmulation() + { + SaveAllData(); + emulatorHandler.Reset(); + + Program.SaveConfiguration(); + } + +} + +static class Program +{ + static string jsonConfigFileName;//= "Config.json"; + static string logFileName;//= "Log.txt"; + static string internalDataDirectoryName;//= "Internal"; + static string saveDataDirectoryName;//= "Saves"; + static string cheatDataDirectoryName;//= "Cheats"; + static string debuggingDataDirectoryName;//= "Debugging"; + static string assetsDirectoryName;//= "Assets"; + static string shaderDirectoryName;//= "Shaders"; + static string noIntroDatDirectoryName;//= "No-Intro"; + static string mutexName;//= $"Unity_{GetVersionDetails()}"; + static string programDataDirectory;//= Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), Application.ProductName); + static string programConfigPath;//= Path.Combine(programDataDirectory, jsonConfigFileName); + + public static Configuration Configuration;// { get; private set; } = LoadConfiguration(programConfigPath); + + public static string DataPath;//{ get; } = string.Empty; + public static string InternalDataPath;//{ get; } = string.Empty; + public static string SaveDataPath;//{ get; } = string.Empty; + public static string CheatsDataPath;//{ get; } = string.Empty; + public static string DebuggingDataPath;//{ get; } = string.Empty; + + static string programApplicationDirectory;// = AppDomain.CurrentDomain.BaseDirectory; + static string programAssetsDirectory;// = Path.Combine(programApplicationDirectory, assetsDirectoryName); + + //public static string ShaderPath { get; } = string.Empty; + public static string NoIntroDatPath;// { get; } = string.Empty; + + //static MainForm mainForm = default; + + public static void InitPath(string CustonDataDir) + { + try + { + jsonConfigFileName = "Config.json"; + logFileName = "Log.txt"; + internalDataDirectoryName = "Internal"; + saveDataDirectoryName = "Saves"; + cheatDataDirectoryName = "Cheats"; + debuggingDataDirectoryName = "Debugging"; + assetsDirectoryName = "Assets"; + shaderDirectoryName = "Shaders"; + noIntroDatDirectoryName = "No-Intro"; + mutexName = $"Unity_{GetVersionDetails()}"; + programDataDirectory = System.IO.Path.Combine(CustonDataDir, "AxibugEmu"); + programConfigPath = System.IO.Path.Combine(programDataDirectory, jsonConfigFileName); + Configuration = LoadConfiguration(programConfigPath); + Log.WriteLine(System.IO.Path.Combine(programDataDirectory, logFileName)); + programApplicationDirectory = AppDomain.CurrentDomain.BaseDirectory; + programAssetsDirectory = System.IO.Path.Combine(programApplicationDirectory, assetsDirectoryName); + AxiIO.Directory.CreateDirectory(DataPath = programDataDirectory); + AxiIO.Directory.CreateDirectory(InternalDataPath = System.IO.Path.Combine(programDataDirectory, internalDataDirectoryName)); + AxiIO.Directory.CreateDirectory(SaveDataPath = System.IO.Path.Combine(programDataDirectory, saveDataDirectoryName)); + AxiIO.Directory.CreateDirectory(CheatsDataPath = System.IO.Path.Combine(programDataDirectory, cheatDataDirectoryName)); + AxiIO.Directory.CreateDirectory(DebuggingDataPath = System.IO.Path.Combine(programDataDirectory, debuggingDataDirectoryName)); + + //if (!Directory.Exists(ShaderPath = Path.Combine(programAssetsDirectory, shaderDirectoryName))) + // throw new DirectoryNotFoundException("Shader directory missing"); + + if (!AxiIO.Directory.Exists(NoIntroDatPath = System.IO.Path.Combine(programAssetsDirectory, noIntroDatDirectoryName))) + throw new Exception("No-Intro .dat directory missing"); + } + catch (Exception e) + { + } + } + + //[STAThread] + //static void Main() + //{ + // using var mutex = new Mutex(true, mutexName, out bool newInstance); + // if (!newInstance) + // { + // MessageBox.Show($"Another instance of {Application.ProductName} is already running.\n\nThis instance will now shut down.", + // $"{Application.ProductName} Startup Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + // Environment.Exit(-1); + // } + + // Application.SetHighDpiMode(HighDpiMode.SystemAware); + // Application.EnableVisualStyles(); + // Application.SetCompatibleTextRenderingDefault(false); + + // if (!Debugger.IsAttached) + // { + // Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException); + // Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); + // AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); + // } + + // Application.Run(mainForm = new MainForm()); + //} + + //static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) + //{ + // if (e.Exception is GLFWException glEx) + // { + // var renderControl = mainForm.Controls["renderControl"] as OpenGL.RenderControl; + // MessageBox.Show($"{glEx.Message.EnsureEndsWithPeriod()}\n\n{Application.ProductName} requires GPU and drivers supporting OpenGL {renderControl.APIVersion.Major}.{renderControl.APIVersion.Minor}.", $"{Application.ProductName} Startup Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + // } + // else + // { + // MessageBox.Show(e.Exception.Message.EnsureEndsWithPeriod(), $"{Application.ProductName} Startup Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + // } + + // Environment.Exit(-1); + //} + + //static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) + //{ + // MessageBox.Show((e.ExceptionObject as Exception).Message, $"{Application.ProductName} Startup Error"); + // Environment.Exit(-1); + //} + + private static Configuration LoadConfiguration(string filename) + { + AxiIO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(filename)); + + Configuration configuration; + //if (!File.Exists(filename) || (configuration = filename.DeserializeFromFile()) == null) + //{ + // configuration = new Configuration(); + // configuration.SerializeToFile(filename); + //} + + configuration = new Configuration(); + + return configuration; + } + + public static void ReplaceConfiguration(Configuration newConfig) + { + ConfigurationBase.CopyConfiguration(newConfig, Configuration); + SaveConfiguration(); + } + + public static void SaveConfiguration() + { + //Configuration?.SerializeToFile(programConfigPath); + } + + private static string GetVersionDetails() + { + //return $"{ThisAssembly.Git.Branch}-{ThisAssembly.Git.Commit}{(ThisAssembly.Git.IsDirty ? "-dirty" : string.Empty)}{(GlobalVariables.IsDebugBuild ? "+debug" : string.Empty)}"; + return $"{(GlobalVariables.IsDebugBuild ? "+debug" : string.Empty)}"; + } + + //public static string GetVersionString(bool detailed) + //{ + // var version = new Version(Application.ProductVersion); + // var stringBuilder = new StringBuilder(); + // stringBuilder.Append($"v{version.Major:D3}{(version.Minor != 0 ? $".{version.Minor}" : string.Empty)}"); + // if (detailed) stringBuilder.Append($" ({GetVersionDetails()})"); + // return stringBuilder.ToString(); + //} +} + diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Event/EEvent.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Event/EEvent.cs index b4534999..c800f240 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Event/EEvent.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Event/EEvent.cs @@ -1,73 +1,73 @@ -namespace AxibugEmuOnline.Client.Event -{ - public enum EEvent - { - // 添加你自己需要的事件类型 - - - /// - /// 登录成功 - /// - OnLoginSucceed, +namespace AxibugEmuOnline.Client.Event +{ + public enum EEvent + { + // 添加你自己需要的事件类型 + + + /// + /// 登录成功 + /// + OnLoginSucceed, /// /// 当登录被置为false时 - /// - OnLossLoginState, - /// - /// 登录失败 - /// - OnLoginFailed, - - OnChatMsg, - - //自己的信息更新(比如改名更新) - OnSelfInfoUpdate, - //更新其他用户信息 - OnOtherUserInfoUpdate, - - - //用户列表,登录和离开 - OnUserListAllUpdate, - OnUserLogin, - OnUserLoginOut, - - OnRoomListAllUpdate,//房间列表全量刷新 - OnRoomListSingleAdd,//房间列表中新增房间 - OnRoomListSingleUpdate,//房间列表中单个更新 - OnRoomListSingleClose,//房间关闭 - OnRoomGetRoomScreen,//获取到房间数据 - - /// - /// 我的房间创建成功 - /// - OnMineRoomCreated, - /// - /// 我进入房间 - /// - OnMineJoinRoom, - /// - /// 我离开房间 - /// - OnMineLeavnRoom, - - /// - /// 其他人进入房间 - /// - OnOtherPlayerJoinRoom, - - /// - /// 其他人离开房间 - /// - OnOtherPlayerLeavnRoom, - - /// - /// 服务器等待Step更新 - /// + /// + OnLossLoginState, + /// + /// 登录失败 + /// + OnLoginFailed, + + OnChatMsg, + + //自己的信息更新(比如改名更新) + OnSelfInfoUpdate, + //更新其他用户信息 + OnOtherUserInfoUpdate, + + + //用户列表,登录和离开 + OnUserListAllUpdate, + OnUserLogin, + OnUserLoginOut, + + OnRoomListAllUpdate,//房间列表全量刷新 + OnRoomListSingleAdd,//房间列表中新增房间 + OnRoomListSingleUpdate,//房间列表中单个更新 + OnRoomListSingleClose,//房间关闭 + OnRoomGetRoomScreen,//获取到房间数据 + + /// + /// 我的房间创建成功 + /// + OnMineRoomCreated, + /// + /// 我进入房间 + /// + OnMineJoinRoom, + /// + /// 我离开房间 + /// + OnMineLeavnRoom, + + /// + /// 其他人进入房间 + /// + OnOtherPlayerJoinRoom, + + /// + /// 其他人离开房间 + /// + OnOtherPlayerLeavnRoom, + + /// + /// 服务器等待Step更新 + /// OnRoomWaitStepChange, - /// - /// 当房间中手柄位信息发生任何变化时触发,进入房间后也应该触发 - /// + /// + /// 当房间中手柄位信息发生任何变化时触发,进入房间后也应该触发 + /// OnRoomSlotDataChanged, /// /// 当手柄连接设置发生变化时触发 @@ -92,5 +92,5 @@ /// 网络即时存档删除 /// OnNetGameSavDeleted, - } -} + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppEmu.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppEmu.cs index 52332280..50682b78 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppEmu.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppEmu.cs @@ -1,66 +1,66 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugEmuOnline.Client.Event; -using AxibugProtobuf; -using UnityEngine; - -namespace AxibugEmuOnline.Client.Manager -{ - public class AppEmu - { - /// - /// unity的c#实现有bug,以接口类型保存的monobehaviour引用,!=和==运算符没有调用到monobehaviour重写过的运算符 - /// 但是Equals方法可以,所以,这个接口判断为空请使用Equals - /// - private EmuCore m_emuCore; - - private IControllerSetuper m_controllerSetuper; - - /// - /// unity的c#实现有bug,以接口类型保存的monobehaviour引用,!=和==运算符没有调用到monobehaviour重写过的运算符 - /// 但是Equals方法可以,所以,这个接口判断为空请使用Equals - /// - public EmuCore Core => m_emuCore; - - public AppEmu() - { - Eventer.Instance.RegisterEvent(EEvent.OnMineJoinRoom, OnSelfJoinRoom); - } - - private void OnSelfJoinRoom() - { - //如果当前正在游戏中,就先结束游戏 - if (m_emuCore != null) StopGame(); - - var roomInfo = App.roomMgr.mineRoomMiniInfo; - roomInfo.FetchRomFileInRoomInfo((_, romFile) => - { - if (!romFile.RomReady) //这个rom并没有下载,所以取消进入房间 - { - App.roomMgr.SendLeavnRoom(); - } - else - { - BeginGame(romFile); - } - }); - } - - - public void BeginGame(RomFile romFile) - { - if (m_emuCore != null) return; - - switch (romFile.Platform) - { - case RomPlatformType.Nes: - m_emuCore = GameObject.Instantiate(Resources.Load("NES/NesEmulator")).GetComponent(); +using AxibugEmuOnline.Client.ClientCore; +using AxibugEmuOnline.Client.Event; +using AxibugProtobuf; +using UnityEngine; + +namespace AxibugEmuOnline.Client.Manager +{ + public class AppEmu + { + /// + /// unity的c#实现有bug,以接口类型保存的monobehaviour引用,!=和==运算符没有调用到monobehaviour重写过的运算符 + /// 但是Equals方法可以,所以,这个接口判断为空请使用Equals + /// + private EmuCore m_emuCore; + + private IControllerSetuper m_controllerSetuper; + + /// + /// unity的c#实现有bug,以接口类型保存的monobehaviour引用,!=和==运算符没有调用到monobehaviour重写过的运算符 + /// 但是Equals方法可以,所以,这个接口判断为空请使用Equals + /// + public EmuCore Core => m_emuCore; + + public AppEmu() + { + Eventer.Instance.RegisterEvent(EEvent.OnMineJoinRoom, OnSelfJoinRoom); + } + + private void OnSelfJoinRoom() + { + //如果当前正在游戏中,就先结束游戏 + if (m_emuCore != null) StopGame(); + + var roomInfo = App.roomMgr.mineRoomMiniInfo; + roomInfo.FetchRomFileInRoomInfo((_, romFile) => + { + if (!romFile.RomReady) //这个rom并没有下载,所以取消进入房间 + { + App.roomMgr.SendLeavnRoom(); + } + else + { + BeginGame(romFile); + } + }); + } + + + public void BeginGame(RomFile romFile) + { + if (m_emuCore != null) return; + + switch (romFile.Platform) + { + case RomPlatformType.Nes: + m_emuCore = GameObject.Instantiate(Resources.Load("NES/NesEmulator")).GetComponent(); break; case RomPlatformType.Cps1: case RomPlatformType.Cps2: case RomPlatformType.Igs: case RomPlatformType.Neogeo: - case RomPlatformType.ArcadeOld: - m_emuCore = GameObject.Instantiate(Resources.Load("MAME/UMAME")).GetComponent(); + case RomPlatformType.ArcadeOld: + m_emuCore = GameObject.Instantiate(Resources.Load("MAME/UMAME")).GetComponent(); break; case RomPlatformType.MasterSystem: case RomPlatformType.GameGear: @@ -68,22 +68,22 @@ namespace AxibugEmuOnline.Client.Manager case RomPlatformType.GameBoyColor: case RomPlatformType.ColecoVision: case RomPlatformType.Sc3000: - case RomPlatformType.Sg1000: - m_emuCore = GameObject.Instantiate(Resources.Load("EssgeeUnity/EssgeeUnity")).GetComponent(); + case RomPlatformType.Sg1000: + m_emuCore = GameObject.Instantiate(Resources.Load("EssgeeUnity/EssgeeUnity")).GetComponent(); break; - case RomPlatformType.WonderSwan: + case RomPlatformType.WonderSwan: case RomPlatformType.WonderSwanColor: m_emuCore = GameObject.Instantiate(Resources.Load("StoicGooseUnity/StoicGooseUnity")).GetComponent(); break; - } - - var result = m_emuCore.StartGame(romFile); + } + + var result = m_emuCore.StartGame(romFile); if (result) { LaunchUI.Instance.HideMainMenu(); InGameUI.Instance.Show(romFile, m_emuCore); - CommandDispatcher.Instance.Mode = CommandListener.ScheduleType.Gaming; + CommandDispatcher.Instance.Mode = CommandListener.ScheduleType.Gaming; m_controllerSetuper = m_emuCore.GetControllerSetuper(); @@ -91,17 +91,17 @@ namespace AxibugEmuOnline.Client.Manager m_controllerSetuper.SetConnect(con0ToSlot: 0); Eventer.Instance.PostEvent(EEvent.OnControllerConnectChanged); - Eventer.Instance.RegisterEvent(EEvent.OnRoomSlotDataChanged, OnSlotDataChanged); - } + Eventer.Instance.RegisterEvent(EEvent.OnRoomSlotDataChanged, OnSlotDataChanged); + } else { StopGame(); OverlayManager.PopTip(result); - } - } - - private void OnSlotDataChanged() - { + } + } + + private void OnSlotDataChanged() + { long selfUID = App.user.userdata.UID; uint? con0Slot; uint? con1Slot; @@ -113,29 +113,29 @@ namespace AxibugEmuOnline.Client.Manager App.roomMgr.mineRoomMiniInfo.GetPlayerSlotIdxByUid(selfUID, 2, out con2Slot); App.roomMgr.mineRoomMiniInfo.GetPlayerSlotIdxByUid(selfUID, 3, out con3Slot); - m_controllerSetuper.SetConnect(con0Slot, con1Slot, con2Slot, con3Slot); - - Eventer.Instance.PostEvent(EEvent.OnControllerConnectChanged); - } - - public void StopGame() - { - if (m_emuCore == null) return; - m_emuCore.Dispose(); - GameObject.Destroy(m_emuCore.gameObject); - m_emuCore = null; - - InGameUI.Instance.Hide(); - LaunchUI.Instance.ShowMainMenu(); - m_controllerSetuper = null; - Eventer.Instance.UnregisterEvent(EEvent.OnRoomSlotDataChanged, OnSlotDataChanged); - } - - public void ResetGame() - { - if (m_emuCore == null) return; - - m_emuCore.DoReset(); - } - } + m_controllerSetuper.SetConnect(con0Slot, con1Slot, con2Slot, con3Slot); + + Eventer.Instance.PostEvent(EEvent.OnControllerConnectChanged); + } + + public void StopGame() + { + if (m_emuCore == null) return; + m_emuCore.Dispose(); + GameObject.Destroy(m_emuCore.gameObject); + m_emuCore = null; + + InGameUI.Instance.Hide(); + LaunchUI.Instance.ShowMainMenu(); + m_controllerSetuper = null; + Eventer.Instance.UnregisterEvent(EEvent.OnRoomSlotDataChanged, OnSlotDataChanged); + } + + public void ResetGame() + { + if (m_emuCore == null) return; + + m_emuCore.DoReset(); + } + } } \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppRoom.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppRoom.cs index 043a14d6..efff978f 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppRoom.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppRoom.cs @@ -1,353 +1,353 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugEmuOnline.Client.Common; -using AxibugEmuOnline.Client.Event; -using AxibugEmuOnline.Client.Network; -using AxibugProtobuf; -using AxiReplay; -using Google.Protobuf; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace AxibugEmuOnline.Client.Manager -{ - public class AppRoom - { - public Protobuf_Room_MiniInfo mineRoomMiniInfo { get; private set; } = null; - public bool InRoom => App.user.IsLoggedIn && mineRoomMiniInfo != null; - public bool IsHost => mineRoomMiniInfo?.HostPlayerUID == App.user.userdata.UID; - public bool IsScreenProviderUID => mineRoomMiniInfo?.ScreenProviderUID == App.user.userdata.UID; - public RoomGameState RoomState => mineRoomMiniInfo.GameState; - public int WaitStep { get; private set; } = -1; - public byte[] RawData { get; private set; } = null; - public NetReplay netReplay { get; private set; } - - Dictionary dictRoomListID2Info = new Dictionary(); - - struct S_PlayerMiniInfo - { - public long UID; - public string NickName; - } - - Protobuf_Room_List _Protobuf_Room_List = new Protobuf_Room_List(); - Protobuf_Room_Get_Screen _Protobuf_Room_Get_Screen = new Protobuf_Room_Get_Screen(); - Protobuf_Room_Create _Protobuf_Room_Create = new Protobuf_Room_Create(); - Protobuf_Room_Join _Protobuf_Room_Join = new Protobuf_Room_Join(); - Protobuf_Room_Leave _Protobuf_Room_Leave = new Protobuf_Room_Leave(); - Protobuf_Room_Change_PlaySlotWithJoy _Protobuf_Room_Change_PlaySlotWithJoy = new Protobuf_Room_Change_PlaySlotWithJoy(); - Protobuf_Room_Player_Ready _Protobuf_Room_Player_Ready = new Protobuf_Room_Player_Ready(); - Protobuf_Room_SinglePlayerInputData _Protobuf_Room_SinglePlayerInputData = new Protobuf_Room_SinglePlayerInputData(); - Protobuf_Screnn_Frame _Protobuf_Screnn_Frame = new Protobuf_Screnn_Frame(); - public AppRoom() - { - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomList, RecvGetRoomList); - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomListUpdate, RecvGetRoomListUpdate); - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomGetScreen, RecvRoomGetScreen); - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomCreate, RecvCreateRoom); - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomJoin, RecvJoinRoom); - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomLeave, RecvLeavnRoom); - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomMyRoomStateChanged, RecvRoomMyRoomStateChange); - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomWaitStep, RecvRoom_WaitStep); - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomHostPlayerUpdateStateRaw, RecvHostPlayer_UpdateStateRaw); - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomSynPlayerInput, RecvHostSyn_RoomFrameAllInputData); - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdScreen, OnScreen); - } - - #region 房间列表管理 - bool AddOrUpdateRoomList(Protobuf_Room_MiniInfo roomInfo) - { - bool bNew = !dictRoomListID2Info.ContainsKey(roomInfo.RoomID); - dictRoomListID2Info[roomInfo.RoomID] = roomInfo; - return bNew; - } - bool RemoveRoomList(int roomId) - { - if (dictRoomListID2Info.ContainsKey(roomId)) - { - dictRoomListID2Info.Remove(roomId); - return true; - } - return false; - } - /// - /// 获取单个房间MiniInfo - /// - /// - /// - /// - public bool GetRoomListMiniInfo(int roomId, out Protobuf_Room_MiniInfo MiniInfo) - { - if (dictRoomListID2Info.ContainsKey(roomId)) - { - MiniInfo = dictRoomListID2Info[roomId]; - return true; - } - MiniInfo = null; - return false; - } - public List GetRoomList() - { - List result = new List(); - foreach (var item in dictRoomListID2Info) - { - result.Add(item.Value); - } - return result; - } - #endregion - - #region Replay - public void InitRePlay() - { - netReplay = new NetReplay(); - netReplay.ResetData(); - } - public void ReleaseRePlay() - { - netReplay.ResetData(); - } - #endregion - - #region 房间管理 - List GetMinePlayerSlotInfo() - { - if (mineRoomMiniInfo == null) - return null; - return mineRoomMiniInfo.GamePlaySlotList.Where(w => w.PlayerUID == App.user.userdata.UID).ToList(); - } - - long[] GetRoom4PlayerUIDs() - { - if (mineRoomMiniInfo == null) - return null; - long[] result = new long[mineRoomMiniInfo.GamePlaySlotList.Count]; - for (int i = 0; i < mineRoomMiniInfo.GamePlaySlotList.Count; i++) - { - if (mineRoomMiniInfo.GamePlaySlotList[i].PlayerUID > 0) - result[i] = mineRoomMiniInfo.GamePlaySlotList[i].PlayerUID; - } - return result; - } - - Protobuf_Room_GamePlaySlot[] GetRoom4GameSlotMiniInfos() - { - if (mineRoomMiniInfo == null) - return null; - return mineRoomMiniInfo.GamePlaySlotList.ToArray(); - } - - #endregion - - /// - /// 获取所有房间列表 - /// - /// - public void SendGetRoomList() - { - App.log.Info("拉取房间列表"); - App.network.SendToServer((int)CommandID.CmdRoomList, ProtoBufHelper.Serizlize(_Protobuf_Room_List)); - } - - /// - /// 获取所有房间列表 - /// - /// - void RecvGetRoomList(byte[] reqData) - { - App.log.Info("取得完整房间列表"); - Protobuf_Room_List_RESP msg = ProtoBufHelper.DeSerizlize(reqData); - dictRoomListID2Info.Clear(); - for (int i = 0; i < msg.RoomMiniInfoList.Count; i++) - AddOrUpdateRoomList(msg.RoomMiniInfoList[i]); - Eventer.Instance.PostEvent(EEvent.OnRoomListAllUpdate); - } - - /// - /// 获取单个列表更新 - /// - /// - void RecvGetRoomListUpdate(byte[] reqData) - { - App.log.Debug("单个房间状态更新"); - Protobuf_Room_Update_RESP msg = ProtoBufHelper.DeSerizlize(reqData); - if (msg.UpdateType == 0) - { - if (AddOrUpdateRoomList(msg.RoomMiniInfo)) - { - Eventer.Instance.PostEvent(EEvent.OnRoomListSingleAdd, msg.RoomMiniInfo.RoomID); - } - else - { - Eventer.Instance.PostEvent(EEvent.OnRoomListSingleUpdate, msg.RoomMiniInfo.RoomID); - } - } - else - { - RemoveRoomList(msg.RoomMiniInfo.RoomID); - Eventer.Instance.PostEvent(EEvent.OnRoomListSingleClose, msg.RoomMiniInfo.RoomID); - } - } - - /// - /// 获取房间画面快照 - /// - /// - public void SendGetRoomScreen(int RoomID) - { - _Protobuf_Room_Get_Screen.RoomID = RoomID; - App.log.Info($"获取房间画面快照"); - App.network.SendToServer((int)CommandID.CmdRoomGetScreen, ProtoBufHelper.Serizlize(_Protobuf_Room_Get_Screen)); - } - /// - /// 获取单个房间画面 - /// - /// - void RecvRoomGetScreen(byte[] reqData) - { - App.log.Debug("单个房间状态更新"); - Protobuf_Room_Get_Screen_RESP msg = ProtoBufHelper.DeSerizlize(reqData); - //解压 - byte[] data = Helper.DecompressByteArray(msg.RawBitmap.ToArray()); - Eventer.Instance.PostEvent(EEvent.OnRoomGetRoomScreen, msg.RoomID, data); - } - - /// - /// 创建房间 - /// - /// - /// - /// - public void SendCreateRoom(int GameRomID, string GameRomHash = null) - { - _Protobuf_Room_Create.GameRomID = GameRomID; - _Protobuf_Room_Create.GameRomHash = GameRomHash; - App.log.Info($"创建房间"); - App.network.SendToServer((int)CommandID.CmdRoomCreate, ProtoBufHelper.Serizlize(_Protobuf_Room_Create)); - } - - /// - /// 创建房间成功 - /// - /// - void RecvCreateRoom(byte[] reqData) - { - App.log.Debug("创建房间成功"); - Protobuf_Room_Create_RESP msg = ProtoBufHelper.DeSerizlize(reqData); - mineRoomMiniInfo = msg.RoomMiniInfo; - InitRePlay(); - Eventer.Instance.PostEvent(EEvent.OnMineRoomCreated); - OverlayManager.PopTip($"房间创建成功"); - - } - - /// - /// 创建房间 - /// - /// - /// 加入时所在SlotIdx - /// 加入时候本地对应JoyIdx - public void SendJoinRoom(int RoomID) - { - _Protobuf_Room_Join.RoomID = RoomID; - App.log.Info($"加入房间"); - App.network.SendToServer((int)CommandID.CmdRoomJoin, ProtoBufHelper.Serizlize(_Protobuf_Room_Join)); - } - - /// - /// 加入房间成功 - /// - /// - void RecvJoinRoom(byte[] reqData) - { - App.log.Debug("加入房间成功"); - Protobuf_Room_Join_RESP msg = ProtoBufHelper.DeSerizlize(reqData); - mineRoomMiniInfo = msg.RoomMiniInfo; - InitRePlay(); - { - Eventer.Instance.PostEvent(EEvent.OnMineJoinRoom); - OverlayManager.PopTip($"已进入[{msg.RoomMiniInfo.GetHostNickName()}]的房间"); - } - } - - /// - /// 离开房间 - /// - /// - public void SendLeavnRoom() - { - if (!InRoom) - return; - _Protobuf_Room_Leave.RoomID = mineRoomMiniInfo.RoomID; - App.log.Info($"LeavnRoom"); - App.network.SendToServer((int)CommandID.CmdRoomLeave, ProtoBufHelper.Serizlize(_Protobuf_Room_Leave)); - } - - /// - /// 离开房间成功 - /// - /// - void RecvLeavnRoom(byte[] reqData) - { - App.log.Debug("离开房间成功"); - Protobuf_Room_Leave_RESP msg = ProtoBufHelper.DeSerizlize(reqData); - ReleaseRePlay(); - mineRoomMiniInfo = null; - Eventer.Instance.PostEvent(EEvent.OnMineLeavnRoom); - OverlayManager.PopTip($"你已经离开房间"); - } - - void RecvRoomMyRoomStateChange(byte[] reqData) - { +using AxibugEmuOnline.Client.ClientCore; +using AxibugEmuOnline.Client.Common; +using AxibugEmuOnline.Client.Event; +using AxibugEmuOnline.Client.Network; +using AxibugProtobuf; +using AxiReplay; +using Google.Protobuf; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace AxibugEmuOnline.Client.Manager +{ + public class AppRoom + { + public Protobuf_Room_MiniInfo mineRoomMiniInfo { get; private set; } = null; + public bool InRoom => App.user.IsLoggedIn && mineRoomMiniInfo != null; + public bool IsHost => mineRoomMiniInfo?.HostPlayerUID == App.user.userdata.UID; + public bool IsScreenProviderUID => mineRoomMiniInfo?.ScreenProviderUID == App.user.userdata.UID; + public RoomGameState RoomState => mineRoomMiniInfo.GameState; + public int WaitStep { get; private set; } = -1; + public byte[] RawData { get; private set; } = null; + public NetReplay netReplay { get; private set; } + + Dictionary dictRoomListID2Info = new Dictionary(); + + struct S_PlayerMiniInfo + { + public long UID; + public string NickName; + } + + Protobuf_Room_List _Protobuf_Room_List = new Protobuf_Room_List(); + Protobuf_Room_Get_Screen _Protobuf_Room_Get_Screen = new Protobuf_Room_Get_Screen(); + Protobuf_Room_Create _Protobuf_Room_Create = new Protobuf_Room_Create(); + Protobuf_Room_Join _Protobuf_Room_Join = new Protobuf_Room_Join(); + Protobuf_Room_Leave _Protobuf_Room_Leave = new Protobuf_Room_Leave(); + Protobuf_Room_Change_PlaySlotWithJoy _Protobuf_Room_Change_PlaySlotWithJoy = new Protobuf_Room_Change_PlaySlotWithJoy(); + Protobuf_Room_Player_Ready _Protobuf_Room_Player_Ready = new Protobuf_Room_Player_Ready(); + Protobuf_Room_SinglePlayerInputData _Protobuf_Room_SinglePlayerInputData = new Protobuf_Room_SinglePlayerInputData(); + Protobuf_Screnn_Frame _Protobuf_Screnn_Frame = new Protobuf_Screnn_Frame(); + public AppRoom() + { + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomList, RecvGetRoomList); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomListUpdate, RecvGetRoomListUpdate); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomGetScreen, RecvRoomGetScreen); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomCreate, RecvCreateRoom); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomJoin, RecvJoinRoom); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomLeave, RecvLeavnRoom); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomMyRoomStateChanged, RecvRoomMyRoomStateChange); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomWaitStep, RecvRoom_WaitStep); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomHostPlayerUpdateStateRaw, RecvHostPlayer_UpdateStateRaw); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomSynPlayerInput, RecvHostSyn_RoomFrameAllInputData); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdScreen, OnScreen); + } + + #region 房间列表管理 + bool AddOrUpdateRoomList(Protobuf_Room_MiniInfo roomInfo) + { + bool bNew = !dictRoomListID2Info.ContainsKey(roomInfo.RoomID); + dictRoomListID2Info[roomInfo.RoomID] = roomInfo; + return bNew; + } + bool RemoveRoomList(int roomId) + { + if (dictRoomListID2Info.ContainsKey(roomId)) + { + dictRoomListID2Info.Remove(roomId); + return true; + } + return false; + } + /// + /// 获取单个房间MiniInfo + /// + /// + /// + /// + public bool GetRoomListMiniInfo(int roomId, out Protobuf_Room_MiniInfo MiniInfo) + { + if (dictRoomListID2Info.ContainsKey(roomId)) + { + MiniInfo = dictRoomListID2Info[roomId]; + return true; + } + MiniInfo = null; + return false; + } + public List GetRoomList() + { + List result = new List(); + foreach (var item in dictRoomListID2Info) + { + result.Add(item.Value); + } + return result; + } + #endregion + + #region Replay + public void InitRePlay() + { + netReplay = new NetReplay(); + netReplay.ResetData(); + } + public void ReleaseRePlay() + { + netReplay.ResetData(); + } + #endregion + + #region 房间管理 + List GetMinePlayerSlotInfo() + { if (mineRoomMiniInfo == null) - { - App.log.Error("RecvRoomMyRoomStateChange 时 mineRoomMiniInfo 为空"); - return; - } - - Protobuf_Room_MyRoom_State_Change msg = ProtoBufHelper.DeSerizlize(reqData); - long[] oldRoomPlayer = GetRoom4PlayerUIDs(); - Protobuf_Room_GamePlaySlot[] oldslotArr = GetRoom4GameSlotMiniInfos(); - mineRoomMiniInfo = msg.RoomMiniInfo; - long[] newRoomPlayer = GetRoom4PlayerUIDs(); - Protobuf_Room_GamePlaySlot[] newslotArr = GetRoom4GameSlotMiniInfos(); - - oldRoomPlayer = oldRoomPlayer.Where(w => w > 0).Distinct().ToArray(); - newRoomPlayer = newRoomPlayer.Where(w => w > 0).Distinct().ToArray(); - //离开用户 - foreach (var leavn in oldRoomPlayer.Where(w => !newRoomPlayer.Contains(w))) - { - UserDataBase oldplayer = App.user.GetUserByUid(leavn); - string oldPlayName = oldplayer != null ? oldplayer.NickName : "Player"; - OverlayManager.PopTip($"[{oldPlayName}]离开房间"); - Eventer.Instance.PostEvent(EEvent.OnOtherPlayerLeavnRoom, leavn); - } - //新加入用户 - foreach (var newJoin in newRoomPlayer.Where(w => !oldRoomPlayer.Contains(w))) - { - UserDataBase newplayer = App.user.GetUserByUid(newJoin); - string newplayerName = newplayer != null ? newplayer.NickName : "Player"; - OverlayManager.PopTip($"[{newplayer.NickName}]进入房间"); - Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, newJoin); - } - - for (int i = 0; i < 4; i++) - { - var oldSlot = oldslotArr[i]; - var newSlot = newslotArr[i]; - if (oldSlot.PlayerUID <= 0 && newSlot.PlayerUID <= 0) - continue; - if ( - oldSlot.PlayerUID != newSlot.PlayerUID - || - oldSlot.PlayerLocalJoyIdx != newSlot.PlayerLocalJoyIdx - ) - { - if (newSlot.PlayerUID > 0) - { - OverlayManager.PopTip($"[{newSlot.PlayerNickName}]使用:P{i}"); - } - } + return null; + return mineRoomMiniInfo.GamePlaySlotList.Where(w => w.PlayerUID == App.user.userdata.UID).ToList(); + } + + long[] GetRoom4PlayerUIDs() + { + if (mineRoomMiniInfo == null) + return null; + long[] result = new long[mineRoomMiniInfo.GamePlaySlotList.Count]; + for (int i = 0; i < mineRoomMiniInfo.GamePlaySlotList.Count; i++) + { + if (mineRoomMiniInfo.GamePlaySlotList[i].PlayerUID > 0) + result[i] = mineRoomMiniInfo.GamePlaySlotList[i].PlayerUID; + } + return result; + } + + Protobuf_Room_GamePlaySlot[] GetRoom4GameSlotMiniInfos() + { + if (mineRoomMiniInfo == null) + return null; + return mineRoomMiniInfo.GamePlaySlotList.ToArray(); + } + + #endregion + + /// + /// 获取所有房间列表 + /// + /// + public void SendGetRoomList() + { + App.log.Info("拉取房间列表"); + App.network.SendToServer((int)CommandID.CmdRoomList, ProtoBufHelper.Serizlize(_Protobuf_Room_List)); + } + + /// + /// 获取所有房间列表 + /// + /// + void RecvGetRoomList(byte[] reqData) + { + App.log.Info("取得完整房间列表"); + Protobuf_Room_List_RESP msg = ProtoBufHelper.DeSerizlize(reqData); + dictRoomListID2Info.Clear(); + for (int i = 0; i < msg.RoomMiniInfoList.Count; i++) + AddOrUpdateRoomList(msg.RoomMiniInfoList[i]); + Eventer.Instance.PostEvent(EEvent.OnRoomListAllUpdate); + } + + /// + /// 获取单个列表更新 + /// + /// + void RecvGetRoomListUpdate(byte[] reqData) + { + App.log.Debug("单个房间状态更新"); + Protobuf_Room_Update_RESP msg = ProtoBufHelper.DeSerizlize(reqData); + if (msg.UpdateType == 0) + { + if (AddOrUpdateRoomList(msg.RoomMiniInfo)) + { + Eventer.Instance.PostEvent(EEvent.OnRoomListSingleAdd, msg.RoomMiniInfo.RoomID); + } + else + { + Eventer.Instance.PostEvent(EEvent.OnRoomListSingleUpdate, msg.RoomMiniInfo.RoomID); + } + } + else + { + RemoveRoomList(msg.RoomMiniInfo.RoomID); + Eventer.Instance.PostEvent(EEvent.OnRoomListSingleClose, msg.RoomMiniInfo.RoomID); + } + } + + /// + /// 获取房间画面快照 + /// + /// + public void SendGetRoomScreen(int RoomID) + { + _Protobuf_Room_Get_Screen.RoomID = RoomID; + App.log.Info($"获取房间画面快照"); + App.network.SendToServer((int)CommandID.CmdRoomGetScreen, ProtoBufHelper.Serizlize(_Protobuf_Room_Get_Screen)); + } + /// + /// 获取单个房间画面 + /// + /// + void RecvRoomGetScreen(byte[] reqData) + { + App.log.Debug("单个房间状态更新"); + Protobuf_Room_Get_Screen_RESP msg = ProtoBufHelper.DeSerizlize(reqData); + //解压 + byte[] data = Helper.DecompressByteArray(msg.RawBitmap.ToArray()); + Eventer.Instance.PostEvent(EEvent.OnRoomGetRoomScreen, msg.RoomID, data); + } + + /// + /// 创建房间 + /// + /// + /// + /// + public void SendCreateRoom(int GameRomID, string GameRomHash = null) + { + _Protobuf_Room_Create.GameRomID = GameRomID; + _Protobuf_Room_Create.GameRomHash = GameRomHash; + App.log.Info($"创建房间"); + App.network.SendToServer((int)CommandID.CmdRoomCreate, ProtoBufHelper.Serizlize(_Protobuf_Room_Create)); + } + + /// + /// 创建房间成功 + /// + /// + void RecvCreateRoom(byte[] reqData) + { + App.log.Debug("创建房间成功"); + Protobuf_Room_Create_RESP msg = ProtoBufHelper.DeSerizlize(reqData); + mineRoomMiniInfo = msg.RoomMiniInfo; + InitRePlay(); + Eventer.Instance.PostEvent(EEvent.OnMineRoomCreated); + OverlayManager.PopTip($"房间创建成功"); + + } + + /// + /// 创建房间 + /// + /// + /// 加入时所在SlotIdx + /// 加入时候本地对应JoyIdx + public void SendJoinRoom(int RoomID) + { + _Protobuf_Room_Join.RoomID = RoomID; + App.log.Info($"加入房间"); + App.network.SendToServer((int)CommandID.CmdRoomJoin, ProtoBufHelper.Serizlize(_Protobuf_Room_Join)); + } + + /// + /// 加入房间成功 + /// + /// + void RecvJoinRoom(byte[] reqData) + { + App.log.Debug("加入房间成功"); + Protobuf_Room_Join_RESP msg = ProtoBufHelper.DeSerizlize(reqData); + mineRoomMiniInfo = msg.RoomMiniInfo; + InitRePlay(); + { + Eventer.Instance.PostEvent(EEvent.OnMineJoinRoom); + OverlayManager.PopTip($"已进入[{msg.RoomMiniInfo.GetHostNickName()}]的房间"); + } + } + + /// + /// 离开房间 + /// + /// + public void SendLeavnRoom() + { + if (!InRoom) + return; + _Protobuf_Room_Leave.RoomID = mineRoomMiniInfo.RoomID; + App.log.Info($"LeavnRoom"); + App.network.SendToServer((int)CommandID.CmdRoomLeave, ProtoBufHelper.Serizlize(_Protobuf_Room_Leave)); + } + + /// + /// 离开房间成功 + /// + /// + void RecvLeavnRoom(byte[] reqData) + { + App.log.Debug("离开房间成功"); + Protobuf_Room_Leave_RESP msg = ProtoBufHelper.DeSerizlize(reqData); + ReleaseRePlay(); + mineRoomMiniInfo = null; + Eventer.Instance.PostEvent(EEvent.OnMineLeavnRoom); + OverlayManager.PopTip($"你已经离开房间"); + } + + void RecvRoomMyRoomStateChange(byte[] reqData) + { + if (mineRoomMiniInfo == null) + { + App.log.Error("RecvRoomMyRoomStateChange 时 mineRoomMiniInfo 为空"); + return; + } + + Protobuf_Room_MyRoom_State_Change msg = ProtoBufHelper.DeSerizlize(reqData); + long[] oldRoomPlayer = GetRoom4PlayerUIDs(); + Protobuf_Room_GamePlaySlot[] oldslotArr = GetRoom4GameSlotMiniInfos(); + mineRoomMiniInfo = msg.RoomMiniInfo; + long[] newRoomPlayer = GetRoom4PlayerUIDs(); + Protobuf_Room_GamePlaySlot[] newslotArr = GetRoom4GameSlotMiniInfos(); + + oldRoomPlayer = oldRoomPlayer.Where(w => w > 0).Distinct().ToArray(); + newRoomPlayer = newRoomPlayer.Where(w => w > 0).Distinct().ToArray(); + //离开用户 + foreach (var leavn in oldRoomPlayer.Where(w => !newRoomPlayer.Contains(w))) + { + UserDataBase oldplayer = App.user.GetUserByUid(leavn); + string oldPlayName = oldplayer != null ? oldplayer.NickName : "Player"; + OverlayManager.PopTip($"[{oldPlayName}]离开房间"); + Eventer.Instance.PostEvent(EEvent.OnOtherPlayerLeavnRoom, leavn); + } + //新加入用户 + foreach (var newJoin in newRoomPlayer.Where(w => !oldRoomPlayer.Contains(w))) + { + UserDataBase newplayer = App.user.GetUserByUid(newJoin); + string newplayerName = newplayer != null ? newplayer.NickName : "Player"; + OverlayManager.PopTip($"[{newplayer.NickName}]进入房间"); + Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, newJoin); + } + + for (int i = 0; i < 4; i++) + { + var oldSlot = oldslotArr[i]; + var newSlot = newslotArr[i]; + if (oldSlot.PlayerUID <= 0 && newSlot.PlayerUID <= 0) + continue; + if ( + oldSlot.PlayerUID != newSlot.PlayerUID + || + oldSlot.PlayerLocalJoyIdx != newSlot.PlayerLocalJoyIdx + ) + { + if (newSlot.PlayerUID > 0) + { + OverlayManager.PopTip($"[{newSlot.PlayerNickName}]使用:P{i}"); + } + } } Eventer.Instance.PostEvent(EEvent.OnRoomSlotDataChanged); @@ -404,10 +404,10 @@ namespace AxibugEmuOnline.Client.Manager //} } - /// - /// 发送修改玩家槽位,但是增量 - /// - /// 玩家占用房间GamePlaySlot和LocalJoyIdx字典 + /// + /// 发送修改玩家槽位,但是增量 + /// + /// 玩家占用房间GamePlaySlot和LocalJoyIdx字典 public void SendChangePlaySlotIdxWithJoyIdx(uint localJoyIndex, uint slotIndex, GamePadType localGamePadType) { if (!App.roomMgr.InRoom) return; @@ -423,210 +423,210 @@ namespace AxibugEmuOnline.Client.Manager temp[slotIndex] = new ValueTuple(localJoyIndex, localGamePadType); SendChangePlaySlotIdxWithJoyIdx(temp); - } - /// - /// 发送修改玩家槽位,全量 - /// - /// 玩家占用房间GamePlaySlot和LocalJoyIdx字典 - public void SendChangePlaySlotIdxWithJoyIdx(Dictionary> dictSlotIdx2LocalJoyIdx) - { - if (!InRoom) - return; - - _Protobuf_Room_Change_PlaySlotWithJoy.SlotWithJoy.Clear(); - - foreach (var slotdata in dictSlotIdx2LocalJoyIdx) - { - _Protobuf_Room_Change_PlaySlotWithJoy.SlotWithJoy.Add(new Protobuf_PlaySlotIdxWithJoyIdx() - { - PlayerSlotIdx = (int)slotdata.Key, - PlayerLocalJoyIdx = (int)slotdata.Value.Item1, - PlayerLocalGamePadType = slotdata.Value.Item2, - }); - } - - App.log.Info($"SendChangePlaySlotIdxWithJoyIdx"); - App.network.SendToServer((int)CommandID.CmdRoomChangePlayerWithJoy, ProtoBufHelper.Serizlize(_Protobuf_Room_Change_PlaySlotWithJoy)); - } - /// - /// 上报即时存档 - /// - /// - public void SendHostRaw(byte[] RawData) - { - //压缩 - byte[] compressRawData = Helper.CompressByteArray(RawData); - Protobuf_Room_HostPlayer_UpdateStateRaw msg = new Protobuf_Room_HostPlayer_UpdateStateRaw() - { - LoadStateRaw = Google.Protobuf.ByteString.CopyFrom(compressRawData) - }; - App.log.Info($"上报即时存档数据 原数据大小:{RawData.Length},压缩后;{compressRawData.Length}"); - App.network.SendToServer((int)CommandID.CmdRoomHostPlayerUpdateStateRaw, ProtoBufHelper.Serizlize(msg)); - } - - void RecvRoom_WaitStep(byte[] reqData) - { - Protobuf_Room_WaitStep_RESP msg = ProtoBufHelper.DeSerizlize(reqData); - if (WaitStep != msg.WaitStep) - { - WaitStep = msg.WaitStep; - if (WaitStep == 1) - { - byte[] decompressRawData = Helper.DecompressByteArray(msg.LoadStateRaw.ToByteArray()); - App.log.Info($"收到即时存档数据 解压后;{decompressRawData.Length}"); - RawData = decompressRawData; - ReleaseRePlay(); - } - Eventer.Instance.PostEvent(EEvent.OnRoomWaitStepChange, WaitStep); - } - } - - void RecvHostPlayer_UpdateStateRaw(byte[] reqData) - { - Protobuf_Room_HostPlayer_UpdateStateRaw_RESP msg = ProtoBufHelper.DeSerizlize(reqData); - App.log.Info($"鸡翅孙当上报成功"); - } - + } + /// + /// 发送修改玩家槽位,全量 + /// + /// 玩家占用房间GamePlaySlot和LocalJoyIdx字典 + public void SendChangePlaySlotIdxWithJoyIdx(Dictionary> dictSlotIdx2LocalJoyIdx) + { + if (!InRoom) + return; + + _Protobuf_Room_Change_PlaySlotWithJoy.SlotWithJoy.Clear(); + + foreach (var slotdata in dictSlotIdx2LocalJoyIdx) + { + _Protobuf_Room_Change_PlaySlotWithJoy.SlotWithJoy.Add(new Protobuf_PlaySlotIdxWithJoyIdx() + { + PlayerSlotIdx = (int)slotdata.Key, + PlayerLocalJoyIdx = (int)slotdata.Value.Item1, + PlayerLocalGamePadType = slotdata.Value.Item2, + }); + } + + App.log.Info($"SendChangePlaySlotIdxWithJoyIdx"); + App.network.SendToServer((int)CommandID.CmdRoomChangePlayerWithJoy, ProtoBufHelper.Serizlize(_Protobuf_Room_Change_PlaySlotWithJoy)); + } + /// + /// 上报即时存档 + /// + /// + public void SendHostRaw(byte[] RawData) + { + //压缩 + byte[] compressRawData = Helper.CompressByteArray(RawData); + Protobuf_Room_HostPlayer_UpdateStateRaw msg = new Protobuf_Room_HostPlayer_UpdateStateRaw() + { + LoadStateRaw = Google.Protobuf.ByteString.CopyFrom(compressRawData) + }; + App.log.Info($"上报即时存档数据 原数据大小:{RawData.Length},压缩后;{compressRawData.Length}"); + App.network.SendToServer((int)CommandID.CmdRoomHostPlayerUpdateStateRaw, ProtoBufHelper.Serizlize(msg)); + } + + void RecvRoom_WaitStep(byte[] reqData) + { + Protobuf_Room_WaitStep_RESP msg = ProtoBufHelper.DeSerizlize(reqData); + if (WaitStep != msg.WaitStep) + { + WaitStep = msg.WaitStep; + if (WaitStep == 1) + { + byte[] decompressRawData = Helper.DecompressByteArray(msg.LoadStateRaw.ToByteArray()); + App.log.Info($"收到即时存档数据 解压后;{decompressRawData.Length}"); + RawData = decompressRawData; + ReleaseRePlay(); + } + Eventer.Instance.PostEvent(EEvent.OnRoomWaitStepChange, WaitStep); + } + } + + void RecvHostPlayer_UpdateStateRaw(byte[] reqData) + { + Protobuf_Room_HostPlayer_UpdateStateRaw_RESP msg = ProtoBufHelper.DeSerizlize(reqData); + App.log.Info($"鸡翅孙当上报成功"); + } + /// /// 即时存档加载完毕 /// /// push帧所需平均时间(微秒) /// 加载即时存档所需平均时间(微秒) /// 视频一帧所需时间(微秒) - /// 音频处理一帧所需时间(微秒) - public void SendRoomPlayerReady(float PushFrameNeedTimeUs, float LoadStateNeedTimeUs, float VideoFrameShowNeedTimeUs, float AudioFramePlayNeedTimeUs) - { - App.log.Debug("上报准备完毕"); - _Protobuf_Room_Player_Ready.PushFrameNeedTimeUs = PushFrameNeedTimeUs; - _Protobuf_Room_Player_Ready.LoadStateNeedTimeUs = LoadStateNeedTimeUs; - _Protobuf_Room_Player_Ready.VideoFrameShowNeedTimeUs = VideoFrameShowNeedTimeUs; - _Protobuf_Room_Player_Ready.AudioFramePlayNeedTimeUs = AudioFramePlayNeedTimeUs; - App.network.SendToServer((int)CommandID.CmdRoomPlayerReady, ProtoBufHelper.Serizlize(_Protobuf_Room_Player_Ready)); - } - - /// - /// 同步上行 - /// - public void SendRoomSingelPlayerInput(uint FrameID, ulong InputData) - { - _Protobuf_Room_SinglePlayerInputData.FrameID = FrameID; - _Protobuf_Room_SinglePlayerInputData.InputData = InputData; - App.network.SendToServer((int)CommandID.CmdRoomSingelPlayerInput, ProtoBufHelper.Serizlize(_Protobuf_Room_SinglePlayerInputData)); - } - - ulong TestAllData = 0; - void RecvHostSyn_RoomFrameAllInputData(byte[] reqData) - { - Protobuf_Room_Syn_RoomFrameAllInputData msg = ProtoBufHelper.DeSerizlize(reqData); - if (TestAllData != msg.InputData) - { - TestAllData = msg.InputData; - App.log.Debug($"ServerFrameID->{msg.ServerFrameID} FrameID->{msg.FrameID} ClientFrame->{netReplay.mCurrClientFrameIdx} InputData->{msg.InputData}"); - } - netReplay.InData(new ReplayStep() { FrameStartID = (int)msg.FrameID, InPut = msg.InputData }, (int)msg.ServerFrameID, msg.ServerForwardCount); - } - - public void SendScreen(byte[] RenderBuffer) - { - //压缩 - byte[] comData = Helper.CompressByteArray(RenderBuffer); - _Protobuf_Screnn_Frame.FrameID = 0; - _Protobuf_Screnn_Frame.RawBitmap = ByteString.CopyFrom(comData); - App.network.SendToServer((int)CommandID.CmdScreen, ProtoBufHelper.Serizlize(_Protobuf_Screnn_Frame)); - } - - public void OnScreen(byte[] reqData) - { - Protobuf_Screnn_Frame msg = ProtoBufHelper.DeSerizlize(reqData); - //解压 - byte[] data = Helper.DecompressByteArray(msg.RawBitmap.ToArray()); - } - - public void ChangeCurrRoomPlayerName(long uid) - { - UserDataBase userdata = App.user.GetUserByUid(uid); - if (userdata == null) - return; - - if (mineRoomMiniInfo == null) - { - foreach (var gameslot in mineRoomMiniInfo.GamePlaySlotList) - { - if (gameslot.PlayerUID == uid) - gameslot.PlayerNickName = userdata.NickName; - } - } - } - } - - public static class RoomEX - { - /// - /// 获取房间空闲席位下标 (返回True表示由余位) - /// - /// - /// - /// - public static bool GetFreeSlot(this Protobuf_Room_MiniInfo roomMiniInfo, ref List freeSlots) - { - freeSlots.Clear(); - for (int i = 0; i < roomMiniInfo.GamePlaySlotList.Count; i++) - { - if (roomMiniInfo.GamePlaySlotList[i].PlayerUID <= 0) - freeSlots.Add(i); - } - return freeSlots.Count > 0; - } - - /// - /// 指定uid和该uid的本地手柄序号,获取占用的手柄位 - /// - public static bool GetPlayerSlotIdxByUid(this Protobuf_Room_MiniInfo roomMiniInfo, long uid, int joyIdx, out uint? slotIdx) - { - slotIdx = null; - - for (int i = 0; i < roomMiniInfo.GamePlaySlotList.Count; i++) - { - if (roomMiniInfo.GamePlaySlotList[i].PlayerUID == uid && roomMiniInfo.GamePlaySlotList[i].PlayerLocalJoyIdx == joyIdx) - { - slotIdx = (uint)i; - return true; - } - } - return false; - } - - /// - /// 按照房间玩家下标获取昵称 - /// - /// - /// - /// - /// - public static bool GetPlayerNameByPlayerIdx(this Protobuf_Room_MiniInfo roomMiniInfo, uint GameSlotIdx, out string PlayerName) - { - PlayerName = string.Empty; - if (roomMiniInfo.GamePlaySlotList[(int)GameSlotIdx].PlayerUID > 0) - PlayerName = roomMiniInfo.GamePlaySlotList[(int)GameSlotIdx].PlayerNickName; - return string.IsNullOrEmpty(PlayerName); + /// 音频处理一帧所需时间(微秒) + public void SendRoomPlayerReady(float PushFrameNeedTimeUs, float LoadStateNeedTimeUs, float VideoFrameShowNeedTimeUs, float AudioFramePlayNeedTimeUs) + { + App.log.Debug("上报准备完毕"); + _Protobuf_Room_Player_Ready.PushFrameNeedTimeUs = PushFrameNeedTimeUs; + _Protobuf_Room_Player_Ready.LoadStateNeedTimeUs = LoadStateNeedTimeUs; + _Protobuf_Room_Player_Ready.VideoFrameShowNeedTimeUs = VideoFrameShowNeedTimeUs; + _Protobuf_Room_Player_Ready.AudioFramePlayNeedTimeUs = AudioFramePlayNeedTimeUs; + App.network.SendToServer((int)CommandID.CmdRoomPlayerReady, ProtoBufHelper.Serizlize(_Protobuf_Room_Player_Ready)); } - + + /// + /// 同步上行 + /// + public void SendRoomSingelPlayerInput(uint FrameID, ulong InputData) + { + _Protobuf_Room_SinglePlayerInputData.FrameID = FrameID; + _Protobuf_Room_SinglePlayerInputData.InputData = InputData; + App.network.SendToServer((int)CommandID.CmdRoomSingelPlayerInput, ProtoBufHelper.Serizlize(_Protobuf_Room_SinglePlayerInputData)); + } + + ulong TestAllData = 0; + void RecvHostSyn_RoomFrameAllInputData(byte[] reqData) + { + Protobuf_Room_Syn_RoomFrameAllInputData msg = ProtoBufHelper.DeSerizlize(reqData); + if (TestAllData != msg.InputData) + { + TestAllData = msg.InputData; + App.log.Debug($"ServerFrameID->{msg.ServerFrameID} FrameID->{msg.FrameID} ClientFrame->{netReplay.mCurrClientFrameIdx} InputData->{msg.InputData}"); + } + netReplay.InData(new ReplayStep() { FrameStartID = (int)msg.FrameID, InPut = msg.InputData }, (int)msg.ServerFrameID, msg.ServerForwardCount); + } + + public void SendScreen(byte[] RenderBuffer) + { + //压缩 + byte[] comData = Helper.CompressByteArray(RenderBuffer); + _Protobuf_Screnn_Frame.FrameID = 0; + _Protobuf_Screnn_Frame.RawBitmap = ByteString.CopyFrom(comData); + App.network.SendToServer((int)CommandID.CmdScreen, ProtoBufHelper.Serizlize(_Protobuf_Screnn_Frame)); + } + + public void OnScreen(byte[] reqData) + { + Protobuf_Screnn_Frame msg = ProtoBufHelper.DeSerizlize(reqData); + //解压 + byte[] data = Helper.DecompressByteArray(msg.RawBitmap.ToArray()); + } + + public void ChangeCurrRoomPlayerName(long uid) + { + UserDataBase userdata = App.user.GetUserByUid(uid); + if (userdata == null) + return; + + if (mineRoomMiniInfo == null) + { + foreach (var gameslot in mineRoomMiniInfo.GamePlaySlotList) + { + if (gameslot.PlayerUID == uid) + gameslot.PlayerNickName = userdata.NickName; + } + } + } + } + + public static class RoomEX + { + /// + /// 获取房间空闲席位下标 (返回True表示由余位) + /// + /// + /// + /// + public static bool GetFreeSlot(this Protobuf_Room_MiniInfo roomMiniInfo, ref List freeSlots) + { + freeSlots.Clear(); + for (int i = 0; i < roomMiniInfo.GamePlaySlotList.Count; i++) + { + if (roomMiniInfo.GamePlaySlotList[i].PlayerUID <= 0) + freeSlots.Add(i); + } + return freeSlots.Count > 0; + } + + /// + /// 指定uid和该uid的本地手柄序号,获取占用的手柄位 + /// + public static bool GetPlayerSlotIdxByUid(this Protobuf_Room_MiniInfo roomMiniInfo, long uid, int joyIdx, out uint? slotIdx) + { + slotIdx = null; + + for (int i = 0; i < roomMiniInfo.GamePlaySlotList.Count; i++) + { + if (roomMiniInfo.GamePlaySlotList[i].PlayerUID == uid && roomMiniInfo.GamePlaySlotList[i].PlayerLocalJoyIdx == joyIdx) + { + slotIdx = (uint)i; + return true; + } + } + return false; + } + + /// + /// 按照房间玩家下标获取昵称 + /// + /// + /// + /// + /// + public static bool GetPlayerNameByPlayerIdx(this Protobuf_Room_MiniInfo roomMiniInfo, uint GameSlotIdx, out string PlayerName) + { + PlayerName = string.Empty; + if (roomMiniInfo.GamePlaySlotList[(int)GameSlotIdx].PlayerUID > 0) + PlayerName = roomMiniInfo.GamePlaySlotList[(int)GameSlotIdx].PlayerNickName; + return string.IsNullOrEmpty(PlayerName); + } + /// /// 获取玩家手柄类型 /// /// /// /// - /// - public static bool GetPlayerGamePadTypeByPlayerIdx(this Protobuf_Room_MiniInfo roomMiniInfo, uint GameSlotIdx, out GamePadType gamePadType) - { + /// + public static bool GetPlayerGamePadTypeByPlayerIdx(this Protobuf_Room_MiniInfo roomMiniInfo, uint GameSlotIdx, out GamePadType gamePadType) + { if (roomMiniInfo.GamePlaySlotList[(int)GameSlotIdx].PlayerUID > 0) { - gamePadType = roomMiniInfo.GamePlaySlotList[(int)GameSlotIdx].PlayerLocalGamePadType; - return true; - } - gamePadType = GamePadType.GlobalGamePad; - return false; - } - } + gamePadType = roomMiniInfo.GamePlaySlotList[(int)GameSlotIdx].PlayerLocalGamePadType; + return true; + } + gamePadType = GamePadType.GlobalGamePad; + return false; + } + } } \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/AppSettings.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/AppSettings.cs index 6cd99397..aaa9f6f5 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/AppSettings.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/AppSettings.cs @@ -1,24 +1,24 @@ -using AxibugEmuOnline.Client.Settings; - -namespace AxibugEmuOnline.Client -{ - public class AppSettings - { - /// 背景颜色设定 - public BgColorSettings BgColor { get; private set; } - /// 滤镜设置 - public FilterManager Filter { get; private set; } - /// 画面比例设置 +using AxibugEmuOnline.Client.Settings; + +namespace AxibugEmuOnline.Client +{ + public class AppSettings + { + /// 背景颜色设定 + public BgColorSettings BgColor { get; private set; } + /// 滤镜设置 + public FilterManager Filter { get; private set; } + /// 画面比例设置 public ScreenScaler ScreenScaler { get; private set; } - /// 键位设置 + /// 键位设置 public KeyMapperSetting KeyMapper { get; private set; } public AppSettings() { BgColor = new BgColorSettings(); - Filter = new FilterManager(); - ScreenScaler = new ScreenScaler(); - KeyMapper = new KeyMapperSetting(); - } - } -} + Filter = new FilterManager(); + ScreenScaler = new ScreenScaler(); + KeyMapper = new KeyMapperSetting(); + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/1990-esque/Filter1990_esque.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/1990-esque/Filter1990_esque.cs index 46a6f012..b67accea 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/1990-esque/Filter1990_esque.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/1990-esque/Filter1990_esque.cs @@ -1,16 +1,16 @@ -using UnityEngine; - +using UnityEngine; + namespace AxibugEmuOnline.Client.Filters -{ - public class Filter1990_esque : FilterEffect - { - public override string Name => "1990-esque"; - - protected override string ShaderName => "Filter/1990-esque"; - - protected override void OnRenderer(Material renderMat, Texture src, RenderTexture result) - { - Graphics.Blit(src, result, renderMat, 1); - } - } +{ + public class Filter1990_esque : FilterEffect + { + public override string Name => "1990-esque"; + + protected override string ShaderName => "Filter/1990-esque"; + + protected override void OnRenderer(Material renderMat, Texture src, RenderTexture result) + { + Graphics.Blit(src, result, renderMat, 1); + } + } } diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/FilterEffect.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/FilterEffect.cs index feb1eb88..d1ceaf70 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/FilterEffect.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/FilterEffect.cs @@ -1,139 +1,139 @@ -using Assets.Script.AppMain.Filter; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Reflection; -using UnityEngine; - -namespace AxibugEmuOnline.Client -{ - public abstract class FilterEffect - { - public bool Enable { get; set; } - - [Range(0.1f, 4f)] - public FloatParameter RenderScale; - - public abstract string Name { get; } - public IReadOnlyCollection EditableParam => m_editableParamList.AsReadOnly(); - - List m_editableParamList; - Material m_material; - protected virtual float m_defaultRenderScale { get => 1f; } - protected abstract string ShaderName { get; } - private static int m_iResolutionID = Shader.PropertyToID("_iResolution"); - - public FilterEffect() - { - RenderScale = new FloatParameter(m_defaultRenderScale); - GetEditableFilterParamters(); - - Init(); - } - +using Assets.Script.AppMain.Filter; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Reflection; +using UnityEngine; + +namespace AxibugEmuOnline.Client +{ + public abstract class FilterEffect + { + public bool Enable { get; set; } + + [Range(0.1f, 4f)] + public FloatParameter RenderScale; + + public abstract string Name { get; } + public IReadOnlyCollection EditableParam => m_editableParamList.AsReadOnly(); + + List m_editableParamList; + Material m_material; + protected virtual float m_defaultRenderScale { get => 1f; } + protected abstract string ShaderName { get; } + private static int m_iResolutionID = Shader.PropertyToID("_iResolution"); + + public FilterEffect() + { + RenderScale = new FloatParameter(m_defaultRenderScale); + GetEditableFilterParamters(); + + Init(); + } + protected virtual void Init() { if (ShaderName != null) { var shader = Shader.Find(ShaderName); - if (shader != null) m_material = new Material(Shader.Find(ShaderName)); + if (shader != null) m_material = new Material(Shader.Find(ShaderName)); } - + OnInit(m_material); - } - - protected virtual void OnInit(Material renderMat) { } - - void GetEditableFilterParamters() - { - var parameters = (from t in GetType().GetFields(BindingFlags.Instance | BindingFlags.Public) - where t.FieldType.IsSubclassOf(typeof(FilterParameter)) - orderby t.MetadataToken - select t); - - m_editableParamList = new List(); - foreach (var param in parameters) - { - var paramObj = (FilterParameter)param.GetValue(this); - var rangeAtt = param.GetCustomAttribute(); - float min = 0; - float max = 10; + } + + protected virtual void OnInit(Material renderMat) { } + + void GetEditableFilterParamters() + { + var parameters = (from t in GetType().GetFields(BindingFlags.Instance | BindingFlags.Public) + where t.FieldType.IsSubclassOf(typeof(FilterParameter)) + orderby t.MetadataToken + select t); + + m_editableParamList = new List(); + foreach (var param in parameters) + { + var paramObj = (FilterParameter)param.GetValue(this); + var rangeAtt = param.GetCustomAttribute(); + float min = 0; + float max = 10; if (rangeAtt != null) { min = rangeAtt.min; max = rangeAtt.max; } - var descrip = param.GetCustomAttribute(); - string name = descrip != null ? descrip.Description : param.Name; - - var editableParam = new EditableParamerter(name, paramObj, min, max); - m_editableParamList.Add(editableParam); - } - } - - public virtual void Render(Texture src, RenderTexture result) - { - if (m_material != null) m_material.SetVector(m_iResolutionID, new Vector4(result.width, result.height)); - OnRenderer(m_material, src, result); - } - - protected abstract void OnRenderer(Material renderMat, Texture src, RenderTexture result); - - public class EditableParamerter - { - private FilterParameter m_paramObject; - - public Type ValueType => m_paramObject.ValueType; - public string Name { get; private set; } - public object Value - { - get => m_paramObject.Value; - set => m_paramObject.Value = value; - } - - public object MinValue { get; private set; } - public object MaxValue { get; private set; } - - public EditableParamerter(string name, FilterParameter paramObject, float minValue, float maxValue) - { - m_paramObject = paramObject; - Name = name; - - var paramType = paramObject.GetType(); - + var descrip = param.GetCustomAttribute(); + string name = descrip != null ? descrip.Description : param.Name; + + var editableParam = new EditableParamerter(name, paramObj, min, max); + m_editableParamList.Add(editableParam); + } + } + + public virtual void Render(Texture src, RenderTexture result) + { + if (m_material != null) m_material.SetVector(m_iResolutionID, new Vector4(result.width, result.height)); + OnRenderer(m_material, src, result); + } + + protected abstract void OnRenderer(Material renderMat, Texture src, RenderTexture result); + + public class EditableParamerter + { + private FilterParameter m_paramObject; + + public Type ValueType => m_paramObject.ValueType; + public string Name { get; private set; } + public object Value + { + get => m_paramObject.Value; + set => m_paramObject.Value = value; + } + + public object MinValue { get; private set; } + public object MaxValue { get; private set; } + + public EditableParamerter(string name, FilterParameter paramObject, float minValue, float maxValue) + { + m_paramObject = paramObject; + Name = name; + + var paramType = paramObject.GetType(); + if (paramObject.ValueType == typeof(int)) { MinValue = (int)minValue; - MaxValue = (int)maxValue; - } + MaxValue = (int)maxValue; + } else if (paramObject.ValueType == typeof(float)) { MinValue = minValue; MaxValue = maxValue; - } - } - - public void ResetToDefault() => m_paramObject.Value = null; - - - public void Apply(object overrideValue) - { - Value = overrideValue; - } - } - - [AttributeUsage(AttributeTargets.Class)] - internal class StripAttribute : Attribute - { - HashSet m_stripPlats; - /// - /// 指示一个滤镜是否会在指定的平台被剔除 - /// - /// 会被剔除的平台 - public StripAttribute(params RuntimePlatform[] stripPlatform) - { - m_stripPlats = new HashSet(stripPlatform); - } - - public bool NeedStrip => m_stripPlats.Contains(Application.platform); - } - } -} + } + } + + public void ResetToDefault() => m_paramObject.Value = null; + + + public void Apply(object overrideValue) + { + Value = overrideValue; + } + } + + [AttributeUsage(AttributeTargets.Class)] + internal class StripAttribute : Attribute + { + HashSet m_stripPlats; + /// + /// 指示一个滤镜是否会在指定的平台被剔除 + /// + /// 会被剔除的平台 + public StripAttribute(params RuntimePlatform[] stripPlatform) + { + m_stripPlats = new HashSet(stripPlatform); + } + + public bool NeedStrip => m_stripPlats.Contains(Application.platform); + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/FilterManager.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/FilterManager.cs index 84b3a4b9..ed60f1df 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/FilterManager.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/FilterManager.cs @@ -1,14 +1,14 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugProtobuf; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using UnityEngine; -using UnityEngine.UI; -using static AxibugEmuOnline.Client.FilterEffect; - -namespace AxibugEmuOnline.Client.Settings +using AxibugEmuOnline.Client.ClientCore; +using AxibugProtobuf; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEngine; +using UnityEngine.UI; +using static AxibugEmuOnline.Client.FilterEffect; + +namespace AxibugEmuOnline.Client.Settings { public class FilterManager { @@ -17,9 +17,9 @@ namespace AxibugEmuOnline.Client.Settings private AlphaWraper m_previewFilterWraper; FilterRomSetting m_filterRomSetting; - /// - /// 滤镜列表 - /// + /// + /// 滤镜列表 + /// public IReadOnlyList Filters => m_filters; public FilterManager() @@ -104,24 +104,24 @@ namespace AxibugEmuOnline.Client.Settings } - /// 关闭滤镜预览 + /// 关闭滤镜预览 public void ShutDownFilterPreview() { if (m_previewFilterWraper == null) m_previewFilterWraper = new AlphaWraper(Initer.XMBBg, Initer.FilterPreview, false); m_previewFilterWraper.On = false; } - /// 开启滤镜预览 + /// 开启滤镜预览 public void EnableFilterPreview() { if (m_previewFilterWraper == null) m_previewFilterWraper = new AlphaWraper(Initer.XMBBg, Initer.FilterPreview, false); m_previewFilterWraper.On = true; } - /// - /// 打开滤镜 - /// - /// + /// + /// 打开滤镜 + /// + /// public void EnableFilter(Filter filter) { foreach (var selfFiler in Filters) @@ -131,9 +131,9 @@ namespace AxibugEmuOnline.Client.Settings } } - /// - /// 关闭滤镜效果 - /// + /// + /// 关闭滤镜效果 + /// public void ShutDownFilter() { //关闭所有后处理效果 @@ -141,12 +141,12 @@ namespace AxibugEmuOnline.Client.Settings filter.m_setting.Enable = false; } - /// - /// 为指定rom设置滤镜以及滤镜的预设 - /// - /// rom对象 - /// 滤镜 - /// 滤镜预设 + /// + /// 为指定rom设置滤镜以及滤镜的预设 + /// + /// rom对象 + /// 滤镜 + /// 滤镜预设 public void SetupFilter(RomFile rom, Filter filter, FilterPreset preset) { m_filterRomSetting.Setup(rom, filter, preset); @@ -155,11 +155,11 @@ namespace AxibugEmuOnline.Client.Settings AxiPlayerPrefs.SetString(nameof(FilterRomSetting), json); } - /// - /// 获得指定rom配置的滤镜设置 - /// - /// rom对象 - /// 此元组任意内任意成员都有可能为空 + /// + /// 获得指定rom配置的滤镜设置 + /// + /// rom对象 + /// 此元组任意内任意成员都有可能为空 public GetFilterSetting_result GetFilterSetting(RomFile rom) { var value = m_filterRomSetting.Get(rom); @@ -198,9 +198,9 @@ namespace AxibugEmuOnline.Client.Settings { public string Name => m_setting.Name; public IReadOnlyCollection Paramerters => m_setting.EditableParam; - /// 滤镜预设 + /// 滤镜预设 public List Presets = new List(); - /// 滤镜默认预设 + /// 滤镜默认预设 public FilterPreset DefaultPreset = new FilterPreset("DEFAULT"); internal FilterEffect m_setting; @@ -445,5 +445,5 @@ namespace AxibugEmuOnline.Client.Settings public string PresetName; } } - } -} + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/FilterParamerter.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/FilterParamerter.cs index 5195dd56..f80a23d4 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/FilterParamerter.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/FilterParamerter.cs @@ -1,33 +1,33 @@ -using System; -using UnityEngine; - -namespace Assets.Script.AppMain.Filter -{ - public abstract class FilterParameter - { - public abstract Type ValueType { get; } - - object m_overrideValue; - protected object m_defaultValue; - public object Value - { - get => m_overrideValue ?? m_defaultValue; - set => m_overrideValue = value; +using System; +using UnityEngine; + +namespace Assets.Script.AppMain.Filter +{ + public abstract class FilterParameter + { + public abstract Type ValueType { get; } + + object m_overrideValue; + protected object m_defaultValue; + public object Value + { + get => m_overrideValue ?? m_defaultValue; + set => m_overrideValue = value; } - } - - public class FilterParameter : FilterParameter - { - public override Type ValueType => typeof(T); - public void Override(T value) - { - Value = value; - } - public T GetValue() => (T)Value; - - public FilterParameter(T defaultValue) - { - m_defaultValue = defaultValue; + } + + public class FilterParameter : FilterParameter + { + public override Type ValueType => typeof(T); + public void Override(T value) + { + Value = value; + } + public T GetValue() => (T)Value; + + public FilterParameter(T defaultValue) + { + m_defaultValue = defaultValue; } public static implicit operator T(FilterParameter value) @@ -38,26 +38,26 @@ namespace Assets.Script.AppMain.Filter public static implicit operator FilterParameter(T value) { return new FilterParameter(value); - } - } - - public class BoolParameter : FilterParameter - { - public BoolParameter(bool defaultValue) : base(defaultValue) { } - + } + } + + public class BoolParameter : FilterParameter + { + public BoolParameter(bool defaultValue) : base(defaultValue) { } + public static implicit operator bool(BoolParameter value) { return value.GetValue(); - } - + } + public static implicit operator BoolParameter(bool value) { return new BoolParameter(value); - } - } - - public class Vector2Parameter : FilterParameter - { + } + } + + public class Vector2Parameter : FilterParameter + { public Vector2Parameter(Vector2 defaultValue) : base(defaultValue) { } public static implicit operator Vector2(Vector2Parameter value) @@ -68,13 +68,13 @@ namespace Assets.Script.AppMain.Filter public static implicit operator Vector2Parameter(Vector2 value) { return new Vector2Parameter(value); - } - } - - public class FloatParameter : FilterParameter - { - public FloatParameter(float defaultValue) : base(defaultValue) { } - + } + } + + public class FloatParameter : FilterParameter + { + public FloatParameter(float defaultValue) : base(defaultValue) { } + public static implicit operator float(FloatParameter value) { return value.GetValue(); @@ -83,9 +83,9 @@ namespace Assets.Script.AppMain.Filter public static implicit operator FloatParameter(float value) { return new FloatParameter(value); - } - } - + } + } + public class IntParameter : FilterParameter { public IntParameter(int defaultValue) : base(defaultValue) { } @@ -99,5 +99,5 @@ namespace Assets.Script.AppMain.Filter { return new IntParameter(value); } - } + } } \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/LCDPostEffect/LCDPostEffect.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/LCDPostEffect/LCDPostEffect.cs index e9492b80..2cd02e92 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/LCDPostEffect/LCDPostEffect.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/LCDPostEffect/LCDPostEffect.cs @@ -1,16 +1,16 @@ -using UnityEngine; - +using UnityEngine; + namespace AxibugEmuOnline.Client.Filters -{ - public sealed class LCDPostEffect : FilterEffect - { - public override string Name => nameof(LCDPostEffect); - - protected override string ShaderName => "Filter/LCDPostEffect"; - - protected override void OnRenderer(Material renderMat, Texture src, RenderTexture result) - { - Graphics.Blit(src, result, renderMat); - } - } +{ + public sealed class LCDPostEffect : FilterEffect + { + public override string Name => nameof(LCDPostEffect); + + protected override string ShaderName => "Filter/LCDPostEffect"; + + protected override void OnRenderer(Material renderMat, Texture src, RenderTexture result) + { + Graphics.Blit(src, result, renderMat); + } + } } diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/MattiasCRT/MattiasCRT.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/MattiasCRT/MattiasCRT.cs index 24e3b862..ee67ad26 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/MattiasCRT/MattiasCRT.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/MattiasCRT/MattiasCRT.cs @@ -1,16 +1,16 @@ -using Assets.Script.AppMain.Filter; -using AxibugEmuOnline.Client; -using UnityEngine; -using UnityEngine.Rendering; +using Assets.Script.AppMain.Filter; +using AxibugEmuOnline.Client; +using UnityEngine; +using UnityEngine.Rendering; namespace AxibugEmuOnline.Client.Filters { - public sealed class MattiasCRT : FilterEffect - { - public override string Name => nameof(MattiasCRT); - - protected override string ShaderName => "Filter/MattiasCRT"; - + public sealed class MattiasCRT : FilterEffect + { + public override string Name => nameof(MattiasCRT); + + protected override string ShaderName => "Filter/MattiasCRT"; + public FilterParameter Quality = new FilterParameter(EnumQuality.High); private LocalKeyword _kw_qualityLow; private LocalKeyword _kw_qualityMid; @@ -18,31 +18,31 @@ namespace AxibugEmuOnline.Client.Filters protected override void OnInit(Material renderMat) { - _kw_qualityLow = new LocalKeyword(renderMat.shader, "_QUALITY_LOW"); + _kw_qualityLow = new LocalKeyword(renderMat.shader, "_QUALITY_LOW"); _kw_qualityMid = new LocalKeyword(renderMat.shader, "_QUALITY_MID"); _kw_qualityHigh = new LocalKeyword(renderMat.shader, "_QUALITY_HIGH"); - } - - protected override void OnRenderer(Material renderMat, Texture src, RenderTexture result) - { - renderMat.DisableKeyword(_kw_qualityLow); - renderMat.DisableKeyword(_kw_qualityMid); - renderMat.DisableKeyword(_kw_qualityHigh); + } + + protected override void OnRenderer(Material renderMat, Texture src, RenderTexture result) + { + renderMat.DisableKeyword(_kw_qualityLow); + renderMat.DisableKeyword(_kw_qualityMid); + renderMat.DisableKeyword(_kw_qualityHigh); switch (Quality.GetValue()) { case EnumQuality.Low: renderMat.EnableKeyword(_kw_qualityLow); break; case EnumQuality.Mid: renderMat.EnableKeyword(_kw_qualityMid); break; case EnumQuality.High: renderMat.EnableKeyword(_kw_qualityHigh); break; - } - - Graphics.Blit(src, result, renderMat); - } - + } + + Graphics.Blit(src, result, renderMat); + } + public enum EnumQuality { Low, Mid, High - } + } } } \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RetroArch_Glow/RetroArchMattiasCRTGlow.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RetroArch_Glow/RetroArchMattiasCRTGlow.cs index 6d4719d6..5d1ffb79 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RetroArch_Glow/RetroArchMattiasCRTGlow.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/Filter/RetroArch_Glow/RetroArchMattiasCRTGlow.cs @@ -1,71 +1,71 @@ -using Assets.Script.AppMain.Filter; -using UnityEngine; -using UnityEngine.Rendering; - +using Assets.Script.AppMain.Filter; +using UnityEngine; +using UnityEngine.Rendering; + namespace AxibugEmuOnline.Client.Filters -{ - [Strip(RuntimePlatform.PSP2)] - public class RetroArchMattiasCRTGlow : FilterEffect - { - public override string Name => nameof(RetroArchMattiasCRTGlow); - protected override string ShaderName => "Filter/RetroArch/MattiasCRTWithGlow"; - - [Range(0.02f, 20f)] - public FloatParameter InputGamma = new FloatParameter(11); - [Range(0.02f, 1f)] - public FloatParameter GaussianWidth = new FloatParameter(0.4f); - [Range(0.02f, 1f)] - public FloatParameter ColorBoost = new FloatParameter(0.4f); - [Range(0.02f, 1f)] - public FloatParameter GlowWhitePoint = new FloatParameter(0.4f); - [Range(0.1f, 6f)] - public FloatParameter GlowRolloff = new FloatParameter(2.2f); - [Range(0.05f, 0.8f)] - public FloatParameter GlowStrength = new FloatParameter(0.45f); - [Range(0.02f, 2.6f)] - public FloatParameter MonitorGamma = new FloatParameter(2.2f); - - int m_gamma_ID = Shader.PropertyToID("_gamma"); - int m_horiz_gauss_width_ID = Shader.PropertyToID("_horiz_gauss_width"); - int m_BOOST_ID = Shader.PropertyToID("_BOOST"); - int m_GLOW_WHITEPOINT_ID = Shader.PropertyToID("_GLOW_WHITEPOINT"); - int m_GLOW_ROLLOFF_ID = Shader.PropertyToID("_GLOW_ROLLOFF"); - int m_BLOOM_STRENGTH_ID = Shader.PropertyToID("_BLOOM_STRENGTH"); - int m_OUTPUT_GAMMA_ID = Shader.PropertyToID("_OUTPUT_GAMMA"); - - - CommandBuffer m_multipPassCmd; - int m_wrapRT; - - protected override void OnInit(Material renderMat) - { - m_multipPassCmd = new CommandBuffer(); - m_wrapRT = Shader.PropertyToID($"{Name}.WrapRT"); - } - - protected override void OnRenderer(Material renderMat, Texture src, RenderTexture result) - { - m_multipPassCmd.Clear(); - - m_multipPassCmd.GetTemporaryRT(m_wrapRT, result.width, result.height); - - renderMat.SetFloat(m_gamma_ID, InputGamma.GetValue()); - renderMat.SetFloat(m_horiz_gauss_width_ID, GaussianWidth.GetValue()); - renderMat.SetFloat(m_BOOST_ID, ColorBoost.GetValue()); - renderMat.SetFloat(m_GLOW_WHITEPOINT_ID, GlowWhitePoint.GetValue()); - renderMat.SetFloat(m_GLOW_ROLLOFF_ID, GlowRolloff.GetValue()); - renderMat.SetFloat(m_BLOOM_STRENGTH_ID, GlowStrength.GetValue()); - renderMat.SetFloat(m_OUTPUT_GAMMA_ID, MonitorGamma.GetValue()); - - m_multipPassCmd.Blit(src, result); - for (int i = 0; i < renderMat.shader.passCount; i++) - { - m_multipPassCmd.Blit(result, m_wrapRT, renderMat, i); - m_multipPassCmd.Blit(m_wrapRT, result); - } - - m_multipPassCmd.ReleaseTemporaryRT(m_wrapRT); - Graphics.ExecuteCommandBuffer(m_multipPassCmd); - } - } +{ + [Strip(RuntimePlatform.PSP2)] + public class RetroArchMattiasCRTGlow : FilterEffect + { + public override string Name => nameof(RetroArchMattiasCRTGlow); + protected override string ShaderName => "Filter/RetroArch/MattiasCRTWithGlow"; + + [Range(0.02f, 20f)] + public FloatParameter InputGamma = new FloatParameter(11); + [Range(0.02f, 1f)] + public FloatParameter GaussianWidth = new FloatParameter(0.4f); + [Range(0.02f, 1f)] + public FloatParameter ColorBoost = new FloatParameter(0.4f); + [Range(0.02f, 1f)] + public FloatParameter GlowWhitePoint = new FloatParameter(0.4f); + [Range(0.1f, 6f)] + public FloatParameter GlowRolloff = new FloatParameter(2.2f); + [Range(0.05f, 0.8f)] + public FloatParameter GlowStrength = new FloatParameter(0.45f); + [Range(0.02f, 2.6f)] + public FloatParameter MonitorGamma = new FloatParameter(2.2f); + + int m_gamma_ID = Shader.PropertyToID("_gamma"); + int m_horiz_gauss_width_ID = Shader.PropertyToID("_horiz_gauss_width"); + int m_BOOST_ID = Shader.PropertyToID("_BOOST"); + int m_GLOW_WHITEPOINT_ID = Shader.PropertyToID("_GLOW_WHITEPOINT"); + int m_GLOW_ROLLOFF_ID = Shader.PropertyToID("_GLOW_ROLLOFF"); + int m_BLOOM_STRENGTH_ID = Shader.PropertyToID("_BLOOM_STRENGTH"); + int m_OUTPUT_GAMMA_ID = Shader.PropertyToID("_OUTPUT_GAMMA"); + + + CommandBuffer m_multipPassCmd; + int m_wrapRT; + + protected override void OnInit(Material renderMat) + { + m_multipPassCmd = new CommandBuffer(); + m_wrapRT = Shader.PropertyToID($"{Name}.WrapRT"); + } + + protected override void OnRenderer(Material renderMat, Texture src, RenderTexture result) + { + m_multipPassCmd.Clear(); + + m_multipPassCmd.GetTemporaryRT(m_wrapRT, result.width, result.height); + + renderMat.SetFloat(m_gamma_ID, InputGamma.GetValue()); + renderMat.SetFloat(m_horiz_gauss_width_ID, GaussianWidth.GetValue()); + renderMat.SetFloat(m_BOOST_ID, ColorBoost.GetValue()); + renderMat.SetFloat(m_GLOW_WHITEPOINT_ID, GlowWhitePoint.GetValue()); + renderMat.SetFloat(m_GLOW_ROLLOFF_ID, GlowRolloff.GetValue()); + renderMat.SetFloat(m_BLOOM_STRENGTH_ID, GlowStrength.GetValue()); + renderMat.SetFloat(m_OUTPUT_GAMMA_ID, MonitorGamma.GetValue()); + + m_multipPassCmd.Blit(src, result); + for (int i = 0; i < renderMat.shader.passCount; i++) + { + m_multipPassCmd.Blit(result, m_wrapRT, renderMat, i); + m_multipPassCmd.Blit(m_wrapRT, result); + } + + m_multipPassCmd.ReleaseTemporaryRT(m_wrapRT); + Graphics.ExecuteCommandBuffer(m_multipPassCmd); + } + } } diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/KeyMapperSetting/EssgeeKeyBinding.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/KeyMapperSetting/EssgeeKeyBinding.cs index ba3ee6da..eed4b20a 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/KeyMapperSetting/EssgeeKeyBinding.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/KeyMapperSetting/EssgeeKeyBinding.cs @@ -147,6 +147,25 @@ namespace AxibugEmuOnline.Client.Settings controller.SetBinding(EssgeeSingleKey.LEFT, device.JOYSTICK.Left, 1); controller.SetBinding(EssgeeSingleKey.RIGHT, device.JOYSTICK.Right, 1); } + + public override void Bind(SwitchJoyCon_D device, ControllerBinder controller) + { + controller.SetBinding(EssgeeSingleKey.OPTION_1, device.Plus, 0); + controller.SetBinding(EssgeeSingleKey.OPTION_2, device.Minus, 0); + controller.SetBinding(EssgeeSingleKey.UP, device.Up, 0); + controller.SetBinding(EssgeeSingleKey.DOWN, device.Down, 0); + controller.SetBinding(EssgeeSingleKey.LEFT, device.Left, 0); + controller.SetBinding(EssgeeSingleKey.RIGHT, device.Right, 0); + controller.SetBinding(EssgeeSingleKey.BTN_1, device.A, 0); + controller.SetBinding(EssgeeSingleKey.BTN_2, device.B, 0); + controller.SetBinding(EssgeeSingleKey.BTN_3, device.X, 0); + controller.SetBinding(EssgeeSingleKey.BTN_4, device.Y, 0); + + controller.SetBinding(EssgeeSingleKey.UP, device.LeftStick.Up, 1); + controller.SetBinding(EssgeeSingleKey.DOWN, device.LeftStick.Down, 1); + controller.SetBinding(EssgeeSingleKey.LEFT, device.LeftStick.Left, 1); + controller.SetBinding(EssgeeSingleKey.RIGHT, device.LeftStick.Right, 1); + } } public class MasterSystemKeyBinding : EssgeeKeyBinding diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/KeyMapperSetting/MAMEKeyBinding.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/KeyMapperSetting/MAMEKeyBinding.cs index 7c6d6175..fbdd79ac 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/KeyMapperSetting/MAMEKeyBinding.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/KeyMapperSetting/MAMEKeyBinding.cs @@ -158,6 +158,27 @@ namespace AxibugEmuOnline.Client.Settings controller.SetBinding(UMAMEKSingleKey.LEFT, device.JOYSTICK.Left, 1); controller.SetBinding(UMAMEKSingleKey.RIGHT, device.JOYSTICK.Right, 1); } + + public override void Bind(SwitchJoyCon_D device, ControllerBinder controller) + { + controller.SetBinding(UMAMEKSingleKey.INSERT_COIN, device.Minus, 0); + controller.SetBinding(UMAMEKSingleKey.GAMESTART, device.Plus, 0); + controller.SetBinding(UMAMEKSingleKey.UP, device.Up, 0); + controller.SetBinding(UMAMEKSingleKey.DOWN, device.Down, 0); + controller.SetBinding(UMAMEKSingleKey.LEFT, device.Left, 0); + controller.SetBinding(UMAMEKSingleKey.RIGHT, device.Right, 0); + controller.SetBinding(UMAMEKSingleKey.BTN_A, device.A, 0); + controller.SetBinding(UMAMEKSingleKey.BTN_B, device.B, 0); + controller.SetBinding(UMAMEKSingleKey.BTN_C, device.X, 0); + controller.SetBinding(UMAMEKSingleKey.BTN_D, device.Y, 0); + controller.SetBinding(UMAMEKSingleKey.BTN_E, device.LeftSL, 0); + controller.SetBinding(UMAMEKSingleKey.BTN_F, device.RightSL, 0); + + controller.SetBinding(UMAMEKSingleKey.UP, device.LeftStick.Up, 1); + controller.SetBinding(UMAMEKSingleKey.DOWN, device.LeftStick.Down, 1); + controller.SetBinding(UMAMEKSingleKey.LEFT, device.LeftStick.Left, 1); + controller.SetBinding(UMAMEKSingleKey.RIGHT, device.LeftStick.Right, 1); + } } public class NEOGEOKeyBinding : MAMEKeyBinding diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/KeyMapperSetting/Model/EmuCoreBinder.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/KeyMapperSetting/Model/EmuCoreBinder.cs index 7d8098cd..30803537 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/KeyMapperSetting/Model/EmuCoreBinder.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/KeyMapperSetting/Model/EmuCoreBinder.cs @@ -16,7 +16,8 @@ public abstract class EmuCoreBinder : InternalEmuCoreBinder, IDeviceBinder, IDeviceBinder, IDeviceBinder, - IDeviceBinder + IDeviceBinder, + IDeviceBinder where T : Enum { //每一个实例代表一个对应模拟器平台的控制器索引 @@ -83,6 +84,7 @@ public abstract class EmuCoreBinder : InternalEmuCoreBinder, else if (device is XboxController_D xbC) Bind(xbC, binding); else if (device is PSVController_D psvC) Bind(psvC, binding); else if (device is ScreenGamepad_D screenGamepad) Bind(screenGamepad, binding); + else if (device is SwitchJoyCon_D nsJoyCon) Bind(nsJoyCon, binding); else throw new NotImplementedException($"{device.GetType()}"); } @@ -305,4 +307,5 @@ public abstract class EmuCoreBinder : InternalEmuCoreBinder, public abstract void Bind(XboxController_D device, ControllerBinder controller); public abstract void Bind(PSVController_D device, ControllerBinder controller); public abstract void Bind(ScreenGamepad_D device, ControllerBinder controller); + public abstract void Bind(SwitchJoyCon_D device, ControllerBinder controller); } \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/KeyMapperSetting/NesKeyBinding.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/KeyMapperSetting/NesKeyBinding.cs index 8a743318..6aff8044 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/KeyMapperSetting/NesKeyBinding.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/KeyMapperSetting/NesKeyBinding.cs @@ -121,5 +121,22 @@ namespace AxibugEmuOnline.Client.Settings controller.SetBinding(EnumButtonType.UP, device.JOYSTICK.Up, 1); controller.SetBinding(EnumButtonType.DOWN, device.JOYSTICK.Down, 1); } + public override void Bind(SwitchJoyCon_D device, ControllerBinder controller) + { + controller.SetBinding(EnumButtonType.LEFT, device.Left, 0); + controller.SetBinding(EnumButtonType.RIGHT, device.Right, 0); + controller.SetBinding(EnumButtonType.UP, device.Up, 0); + controller.SetBinding(EnumButtonType.DOWN, device.Down, 0); + controller.SetBinding(EnumButtonType.A, device.A, 0); + controller.SetBinding(EnumButtonType.B, device.B, 0); + controller.SetBinding(EnumButtonType.SELECT, device.Minus, 0); + controller.SetBinding(EnumButtonType.START, device.Plus, 0); + controller.SetBinding(EnumButtonType.MIC, device.RightSL, 0); + + controller.SetBinding(EnumButtonType.LEFT, device.LeftStick.Left, 1); + controller.SetBinding(EnumButtonType.RIGHT, device.LeftStick.Right, 1); + controller.SetBinding(EnumButtonType.UP, device.LeftStick.Up, 1); + controller.SetBinding(EnumButtonType.DOWN, device.LeftStick.Down, 1); + } } } \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/KeyMapperSetting/XMBKeyBinding.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/KeyMapperSetting/XMBKeyBinding.cs index a7bce802..c4135c76 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/KeyMapperSetting/XMBKeyBinding.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppSettings/KeyMapperSetting/XMBKeyBinding.cs @@ -112,5 +112,20 @@ namespace AxibugEmuOnline.Client controller.SetBinding(EnumCommand.SelectItemRight, device.JOYSTICK.Right, 1); controller.SetBinding(EnumCommand.SelectItemUp, device.JOYSTICK.Up, 1); } + public override void Bind(SwitchJoyCon_D device, ControllerBinder controller) + { + controller.SetBinding(EnumCommand.Back, device.A, 0); + controller.SetBinding(EnumCommand.Enter, device.B, 0); + controller.SetBinding(EnumCommand.OptionMenu, device.Plus, 0); + controller.SetBinding(EnumCommand.SelectItemDown, device.Down, 0); + controller.SetBinding(EnumCommand.SelectItemLeft, device.Left, 0); + controller.SetBinding(EnumCommand.SelectItemRight, device.Right, 0); + controller.SetBinding(EnumCommand.SelectItemUp, device.Up, 0); + + controller.SetBinding(EnumCommand.SelectItemDown, device.LeftStick.Down, 1); + controller.SetBinding(EnumCommand.SelectItemLeft, device.LeftStick.Left, 1); + controller.SetBinding(EnumCommand.SelectItemRight, device.LeftStick.Right, 1); + controller.SetBinding(EnumCommand.SelectItemUp, device.LeftStick.Up, 1); + } } } \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/CacheManager.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/CacheManager.cs index f997b216..a8cd3f32 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/CacheManager.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/CacheManager.cs @@ -1,136 +1,136 @@ -using AxibugEmuOnline.Client.ClientCore; -using System; -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -namespace AxibugEmuOnline.Client -{ - public class CacheManager - { - static readonly string CacheDirPath = $"{App.PersistentDataRoot()}/Caches"; - static readonly string TextureCacheDirPath = $"{CacheDirPath}/Texture"; - - public void GetSpriteCache(string url, Action callback) - { - GetCacheData(url, TextureCacheDirPath, callback); - } - - /// 移除文件缓存 - public void ClearCaches() - { - if (AxiIO.Directory.Exists(CacheDirPath)) - AxiIO.Directory.Delete(CacheDirPath, true); - } - - IEnumerator DownloadFromURL(string url, string path, Action callback) +using AxibugEmuOnline.Client.ClientCore; +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace AxibugEmuOnline.Client +{ + public class CacheManager + { + static readonly string CacheDirPath = $"{App.PersistentDataRoot()}/Caches"; + static readonly string TextureCacheDirPath = $"{CacheDirPath}/Texture"; + + public void GetSpriteCache(string url, Action callback) { - AxiHttpProxy.SendDownLoadProxy request = AxiHttpProxy.GetDownLoad($"{App.httpAPI.WebHost}/{url}"); - - while (!request.downloadHandler.isDone) - { - yield return null; - //Debug.Log($"下载进度:{respInfo.DownLoadPr} ->{respInfo.loadedLenght}/{respInfo.NeedloadedLenght}"); - } + GetCacheData(url, TextureCacheDirPath, callback); + } + + /// 移除文件缓存 + public void ClearCaches() + { + if (AxiIO.Directory.Exists(CacheDirPath)) + AxiIO.Directory.Delete(CacheDirPath, true); + } + + IEnumerator DownloadFromURL(string url, string path, Action callback) + { + AxiHttpProxy.SendDownLoadProxy request = AxiHttpProxy.GetDownLoad($"{App.httpAPI.WebHost}/{url}"); + + while (!request.downloadHandler.isDone) + { + yield return null; + //Debug.Log($"下载进度:{respInfo.DownLoadPr} ->{respInfo.loadedLenght}/{respInfo.NeedloadedLenght}"); + } AxiHttpProxy.ShowAxiHttpDebugInfo(request.downloadHandler); - if (!request.downloadHandler.bHadErr) - { + if (!request.downloadHandler.bHadErr) + { AxiIO.Directory.CreateDirectory(path); - AxiIO.File.WriteAllBytes($"{path}/{url.GetHashCode()}", request.downloadHandler.data, false); - callback.Invoke(request.downloadHandler.data); - } + AxiIO.File.WriteAllBytes($"{path}/{url.GetHashCode()}", request.downloadHandler.data, false); + callback.Invoke(request.downloadHandler.data); + } else { - callback.Invoke(null); - } - - /* - var request = UnityWebRequest.Get($"{App.httpAPI.WebHost}/{url}"); - yield return request.SendWebRequest(); - - if (request.result == UnityWebRequest.Result.Success) - { - Directory.CreateDirectory(path); - File.WriteAllBytes($"{path}/{url.GetHashCode()}", request.downloadHandler.data); - callback.Invoke(request.downloadHandler.data); - } - else - callback.Invoke(null); - */ - } - - private Dictionary cachesInMemory = new Dictionary(); + callback.Invoke(null); + } + + /* + var request = UnityWebRequest.Get($"{App.httpAPI.WebHost}/{url}"); + yield return request.SendWebRequest(); + + if (request.result == UnityWebRequest.Result.Success) + { + Directory.CreateDirectory(path); + File.WriteAllBytes($"{path}/{url.GetHashCode()}", request.downloadHandler.data); + callback.Invoke(request.downloadHandler.data); + } + else + callback.Invoke(null); + */ + } + + private Dictionary cachesInMemory = new Dictionary(); void GetCacheData(string url, string path, Action callback) where T : class - { + { object cacheObj; - if (cachesInMemory.TryGetValue(url, out cacheObj) && cacheObj is T) - { + if (cachesInMemory.TryGetValue(url, out cacheObj) && cacheObj is T) + { T obj = (T)cacheObj; - callback.Invoke(obj, url); - return; - } - - var fileName = $"{url.GetHashCode()}"; - byte[] rawData = null; - - var filePath = $"{path}/{fileName}"; - if (AxiIO.File.Exists(filePath)) - { - rawData = AxiIO.File.ReadAllBytes(filePath); - var @out = RawDataConvert(rawData); - cachesInMemory[url] = @out; - callback.Invoke(@out, url); - } - else - { - App.StartCoroutine(DownloadFromURL(url, path, (data) => - { - var @out = RawDataConvert(data); - cachesInMemory[url] = @out; - callback.Invoke(@out, url); - })); - } - } - - Type t_texture2d = typeof(Texture2D); - Type t_sprite = typeof(Sprite); - Type t_byteArray = typeof(byte[]); - Type t_object = typeof(object); - - T RawDataConvert(byte[] data) where T : class - { - var vt = typeof(T); - - if (vt == t_texture2d || vt == t_sprite) - { - Texture2D texture = new Texture2D(2, 2); + callback.Invoke(obj, url); + return; + } + + var fileName = $"{url.GetHashCode()}"; + byte[] rawData = null; + + var filePath = $"{path}/{fileName}"; + if (AxiIO.File.Exists(filePath)) + { + rawData = AxiIO.File.ReadAllBytes(filePath); + var @out = RawDataConvert(rawData); + cachesInMemory[url] = @out; + callback.Invoke(@out, url); + } + else + { + App.StartCoroutine(DownloadFromURL(url, path, (data) => + { + var @out = RawDataConvert(data); + cachesInMemory[url] = @out; + callback.Invoke(@out, url); + })); + } + } + + Type t_texture2d = typeof(Texture2D); + Type t_sprite = typeof(Sprite); + Type t_byteArray = typeof(byte[]); + Type t_object = typeof(object); + + T RawDataConvert(byte[] data) where T : class + { + var vt = typeof(T); + + if (vt == t_texture2d || vt == t_sprite) + { + Texture2D texture = new Texture2D(2, 2); if (data == null) { var errorSpr = Resources.Load("UIImage/error"); if (vt == t_texture2d) return errorSpr.texture as T; else return errorSpr as T; - } + } else { texture.LoadImage(data); if (vt == t_texture2d) return texture as T; - else return Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f)) as T; - } - } - else if (vt == t_byteArray) - { - return data as T; - } - else - { - return data as T; - } - - throw new NotImplementedException($"{vt.Name}"); - } - } -} + else return Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f)) as T; + } + } + else if (vt == t_byteArray) + { + return data as T; + } + else + { + return data as T; + } + + throw new NotImplementedException($"{vt.Name}"); + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/HttpAPI.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/HttpAPI.cs index 59722154..22f7623a 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/HttpAPI.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/HttpAPI.cs @@ -1,298 +1,298 @@ -using AxibugEmuOnline.Client.ClientCore; -using System; -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -namespace AxibugEmuOnline.Client -{ - public class HttpAPI - { - public string WebHost = "http://emu.axibug.com"; - public string WebSiteApi => WebHost + "/api"; - - public delegate void GetRomListAPI(Action callback, AxibugProtobuf.RomPlatformType Platform, int page, int pageSize = 10); +using AxibugEmuOnline.Client.ClientCore; +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace AxibugEmuOnline.Client +{ + public class HttpAPI + { + public string WebHost = "http://emu.axibug.com"; + public string WebSiteApi => WebHost + "/api"; + + public delegate void GetRomListAPI(Action callback, AxibugProtobuf.RomPlatformType Platform, int page, int pageSize = 10); public delegate void SearchRomListAPI(Action callback, AxibugProtobuf.RomPlatformType Platform, string searchKey, int page, int pageSize = 10); public delegate void GetStarRomListAPI(Action callback, AxibugProtobuf.RomPlatformType platform, int page, int pageSize = 10); - public void GetRomList(Action callback, AxibugProtobuf.RomPlatformType platform, int page, int pageSize = 10) - { - App.StartCoroutine(GetRomListFlow(platform, page, pageSize, callback)); - } - public void SearchRomList(Action callback, AxibugProtobuf.RomPlatformType platform, string searchKey, int page, int pageSize = 10) - { - App.StartCoroutine(SearchRomListFlow(platform, searchKey, page, pageSize, callback)); - } - private IEnumerator SearchRomListFlow(AxibugProtobuf.RomPlatformType platform, string searchKey, int page, int pageSize, Action callback) - { - if (!string.IsNullOrEmpty(searchKey)) - { - string oldsearch = searchKey; - //searchKey = System.Net.WebUtility.UrlEncode(searchKey); - searchKey = AxiHttp.UrlEncode(searchKey); - App.log.Info($"search->{oldsearch} ->{searchKey}"); - //searchKey = HttpUtility.UrlDecode(searchKey); - } - //避免特殊字符和个别文字编码问题 - //byte[] gb2312Bytes = Encoding.Default.GetBytes(searchKey); - //byte[] utf8Bytes = Encoding.Convert(Encoding.Default, Encoding.UTF8, gb2312Bytes); - //// 将UTF-8编码的字节数组转换回字符串(此时是UTF-8编码的字符串) - //string utf8String = Encoding.UTF8.GetString(utf8Bytes); - //searchKey = UrlEncode(utf8String); - //App.log.Info($"search->{utf8String} ->{searchKey}"); - string url = $"{WebSiteApi}/RomList?Page={page}&PageSize={pageSize}&PType={(int)platform}&SearchKey={searchKey}&Token={App.user.Token}"; - App.log.Info($"GetRomList=>{url}"); - AxiHttpProxy.SendWebRequestProxy request = AxiHttpProxy.Get(url); - yield return request.SendWebRequest; - if (!request.downloadHandler.isDone) - { - callback.Invoke(page, null); - yield break; - } - - if (!request.downloadHandler.bHadErr) - { - var resp = JsonUtility.FromJson(request.downloadHandler.text); - callback.Invoke(page, resp); - yield break; - } - - App.log.Error(request.downloadHandler.ErrInfo); - callback.Invoke(page, null); - - /* - UnityWebRequest request = UnityWebRequest.Get($"{WebSiteApi}/NesRomList?Page={page}&PageSize={pageSize}&SearchKey={searchKey}"); - yield return request.SendWebRequest(); - - if (request.result != UnityWebRequest.Result.Success) - { - callback.Invoke(null); - yield break; - }*/ - - } - private IEnumerator GetRomListFlow(AxibugProtobuf.RomPlatformType platform, int page, int pageSize, Action callback) - { - string url = $"{WebSiteApi}/RomList?Page={page}&PageSize={pageSize}&PType={(int)platform}&Token={App.user.Token}"; - App.log.Info($"GetRomList=>{url}"); - AxiHttpProxy.SendWebRequestProxy request = AxiHttpProxy.Get(url); - yield return request.SendWebRequest; - if (!request.downloadHandler.isDone) - { - callback.Invoke(page, null); - yield break; - } - - //请求成功 - if (!request.downloadHandler.bHadErr) - { - var resp = JsonUtility.FromJson(request.downloadHandler.text); - callback.Invoke(page, resp); - yield break; - } - - App.log.Error(request.downloadHandler.ErrInfo); - callback.Invoke(page, null); - /* - UnityWebRequest request = UnityWebRequest.Get($"{WebSiteApi}/NesRomList?Page={page}&PageSize={pageSize}"); - yield return request.SendWebRequest(); - - if (request.result != UnityWebRequest.Result.Success) - { - callback.Invoke(null); - yield break; - } - */ + public void GetRomList(Action callback, AxibugProtobuf.RomPlatformType platform, int page, int pageSize = 10) + { + App.StartCoroutine(GetRomListFlow(platform, page, pageSize, callback)); + } + public void SearchRomList(Action callback, AxibugProtobuf.RomPlatformType platform, string searchKey, int page, int pageSize = 10) + { + App.StartCoroutine(SearchRomListFlow(platform, searchKey, page, pageSize, callback)); + } + private IEnumerator SearchRomListFlow(AxibugProtobuf.RomPlatformType platform, string searchKey, int page, int pageSize, Action callback) + { + if (!string.IsNullOrEmpty(searchKey)) + { + string oldsearch = searchKey; + //searchKey = System.Net.WebUtility.UrlEncode(searchKey); + searchKey = AxiHttp.UrlEncode(searchKey); + App.log.Info($"search->{oldsearch} ->{searchKey}"); + //searchKey = HttpUtility.UrlDecode(searchKey); + } + //避免特殊字符和个别文字编码问题 + //byte[] gb2312Bytes = Encoding.Default.GetBytes(searchKey); + //byte[] utf8Bytes = Encoding.Convert(Encoding.Default, Encoding.UTF8, gb2312Bytes); + //// 将UTF-8编码的字节数组转换回字符串(此时是UTF-8编码的字符串) + //string utf8String = Encoding.UTF8.GetString(utf8Bytes); + //searchKey = UrlEncode(utf8String); + //App.log.Info($"search->{utf8String} ->{searchKey}"); + string url = $"{WebSiteApi}/RomList?Page={page}&PageSize={pageSize}&PType={(int)platform}&SearchKey={searchKey}&Token={App.user.Token}"; + App.log.Info($"GetRomList=>{url}"); + AxiHttpProxy.SendWebRequestProxy request = AxiHttpProxy.Get(url); + yield return request.SendWebRequest; + if (!request.downloadHandler.isDone) + { + callback.Invoke(page, null); + yield break; + } + + if (!request.downloadHandler.bHadErr) + { + var resp = JsonUtility.FromJson(request.downloadHandler.text); + callback.Invoke(page, resp); + yield break; + } + + App.log.Error(request.downloadHandler.ErrInfo); + callback.Invoke(page, null); + + /* + UnityWebRequest request = UnityWebRequest.Get($"{WebSiteApi}/NesRomList?Page={page}&PageSize={pageSize}&SearchKey={searchKey}"); + yield return request.SendWebRequest(); + + if (request.result != UnityWebRequest.Result.Success) + { + callback.Invoke(null); + yield break; + }*/ + + } + private IEnumerator GetRomListFlow(AxibugProtobuf.RomPlatformType platform, int page, int pageSize, Action callback) + { + string url = $"{WebSiteApi}/RomList?Page={page}&PageSize={pageSize}&PType={(int)platform}&Token={App.user.Token}"; + App.log.Info($"GetRomList=>{url}"); + AxiHttpProxy.SendWebRequestProxy request = AxiHttpProxy.Get(url); + yield return request.SendWebRequest; + if (!request.downloadHandler.isDone) + { + callback.Invoke(page, null); + yield break; + } + + //请求成功 + if (!request.downloadHandler.bHadErr) + { + var resp = JsonUtility.FromJson(request.downloadHandler.text); + callback.Invoke(page, resp); + yield break; + } + + App.log.Error(request.downloadHandler.ErrInfo); + callback.Invoke(page, null); + /* + UnityWebRequest request = UnityWebRequest.Get($"{WebSiteApi}/NesRomList?Page={page}&PageSize={pageSize}"); + yield return request.SendWebRequest(); + + if (request.result != UnityWebRequest.Result.Success) + { + callback.Invoke(null); + yield break; + } + */ } - public void GetMarkList(Action callback, AxibugProtobuf.RomPlatformType platform, int page, int pageSize = 10) - { - App.StartCoroutine(GetMarkListFlow(platform, page, pageSize, callback)); - } - public void SearchMarkList(Action callback, AxibugProtobuf.RomPlatformType platform, string searchKey, int page, int pageSize = 10) - { - App.StartCoroutine(SearchMarkListFlow(platform, searchKey, page, pageSize, callback)); - } - private IEnumerator SearchMarkListFlow(AxibugProtobuf.RomPlatformType platform, string searchKey, int page, int pageSize, Action callback) - { - if (!string.IsNullOrEmpty(searchKey)) - { - string oldsearch = searchKey; - //searchKey = System.Net.WebUtility.UrlEncode(searchKey); - searchKey = AxiHttp.UrlEncode(searchKey); - App.log.Info($"search->{oldsearch} ->{searchKey}"); - //searchKey = HttpUtility.UrlDecode(searchKey); - } - //避免特殊字符和个别文字编码问题 - //byte[] gb2312Bytes = Encoding.Default.GetBytes(searchKey); - //byte[] utf8Bytes = Encoding.Convert(Encoding.Default, Encoding.UTF8, gb2312Bytes); - //// 将UTF-8编码的字节数组转换回字符串(此时是UTF-8编码的字符串) - //string utf8String = Encoding.UTF8.GetString(utf8Bytes); - //searchKey = UrlEncode(utf8String); - //App.log.Info($"search->{utf8String} ->{searchKey}"); - string url = $"{WebSiteApi}/MarkList?Page={page}&PageSize={pageSize}&SearchKey={searchKey}&Token={App.user.Token}"; - App.log.Info($"MarkList=>{url}"); - AxiHttpProxy.SendWebRequestProxy request = AxiHttpProxy.Get(url); - yield return request.SendWebRequest; - if (!request.downloadHandler.isDone) - { - callback.Invoke(page, null); - yield break; - } - - if (!request.downloadHandler.bHadErr) - { - var resp = JsonUtility.FromJson(request.downloadHandler.text); - callback.Invoke(page, resp); - yield break; - } - - App.log.Error(request.downloadHandler.ErrInfo); - callback.Invoke(page, null); - - /* - UnityWebRequest request = UnityWebRequest.Get($"{WebSiteApi}/NesRomList?Page={page}&PageSize={pageSize}&SearchKey={searchKey}"); - yield return request.SendWebRequest(); - - if (request.result != UnityWebRequest.Result.Success) - { - callback.Invoke(null); - yield break; - }*/ - - } - private IEnumerator GetMarkListFlow(AxibugProtobuf.RomPlatformType platform, int page, int pageSize, Action callback) - { - string url = $"{WebSiteApi}/MarkList?Page={page}&PageSize={pageSize}&PType={(int)platform}&Token={App.user.Token}"; - App.log.Info($"MarkList=>{url}"); - AxiHttpProxy.SendWebRequestProxy request = AxiHttpProxy.Get(url); - yield return request.SendWebRequest; - if (!request.downloadHandler.isDone) - { - callback.Invoke(page, null); - yield break; - } - - //请求成功 - if (!request.downloadHandler.bHadErr) - { - var resp = JsonUtility.FromJson(request.downloadHandler.text); - callback.Invoke(page, resp); - yield break; - } - - App.log.Error(request.downloadHandler.ErrInfo); - callback.Invoke(page, null); - /* - UnityWebRequest request = UnityWebRequest.Get($"{WebSiteApi}/NesRomList?Page={page}&PageSize={pageSize}"); - yield return request.SendWebRequest(); - - if (request.result != UnityWebRequest.Result.Success) - { - callback.Invoke(null); - yield break; - } - */ - } - - - public IEnumerator GetRomInfo(int RomID, Action callback) - { - - AxiHttpProxy.SendWebRequestProxy request = AxiHttpProxy.Get($"{WebSiteApi}/RomInfo?RomID={RomID}&Token={App.user.Token}"); - yield return request.SendWebRequest; - if (!request.downloadHandler.isDone) - { - callback.Invoke(null); - yield break; - } - - //成功 - if (!request.downloadHandler.bHadErr) - { - var resp = JsonUtility.FromJson(request.downloadHandler.text); - callback.Invoke(resp); - yield break; - } - - App.log.Error(request.downloadHandler.ErrInfo); - callback.Invoke(null); - - /* - UnityWebRequest request = UnityWebRequest.Get($"{WebSiteApi}/RomInfo?PType={PlatformType.Nes}&RomID={RomID}"); - yield return request.SendWebRequest(); - - if (request.result != UnityWebRequest.Result.Success) - { - callback.Invoke(null); - yield break; - }*/ - - } - - enum GameType : byte - { - NONE = 0, - ACT, - ARPG, - AVG, - ETC, - FTG, - PUZ, - RAC, - RPG, - SLG, - SPG, - SRPG, - STG, - TAB, - /// - /// 合卡 - /// - ALLINONE, - } - - [Serializable] - public class Resp_GameList - { - public int page; - public int maxPage; - public int resultAllCount; - public List gameList; - } - - [Serializable] - public class Resp_RomInfo - { + public void GetMarkList(Action callback, AxibugProtobuf.RomPlatformType platform, int page, int pageSize = 10) + { + App.StartCoroutine(GetMarkListFlow(platform, page, pageSize, callback)); + } + public void SearchMarkList(Action callback, AxibugProtobuf.RomPlatformType platform, string searchKey, int page, int pageSize = 10) + { + App.StartCoroutine(SearchMarkListFlow(platform, searchKey, page, pageSize, callback)); + } + private IEnumerator SearchMarkListFlow(AxibugProtobuf.RomPlatformType platform, string searchKey, int page, int pageSize, Action callback) + { + if (!string.IsNullOrEmpty(searchKey)) + { + string oldsearch = searchKey; + //searchKey = System.Net.WebUtility.UrlEncode(searchKey); + searchKey = AxiHttp.UrlEncode(searchKey); + App.log.Info($"search->{oldsearch} ->{searchKey}"); + //searchKey = HttpUtility.UrlDecode(searchKey); + } + //避免特殊字符和个别文字编码问题 + //byte[] gb2312Bytes = Encoding.Default.GetBytes(searchKey); + //byte[] utf8Bytes = Encoding.Convert(Encoding.Default, Encoding.UTF8, gb2312Bytes); + //// 将UTF-8编码的字节数组转换回字符串(此时是UTF-8编码的字符串) + //string utf8String = Encoding.UTF8.GetString(utf8Bytes); + //searchKey = UrlEncode(utf8String); + //App.log.Info($"search->{utf8String} ->{searchKey}"); + string url = $"{WebSiteApi}/MarkList?Page={page}&PageSize={pageSize}&SearchKey={searchKey}&Token={App.user.Token}"; + App.log.Info($"MarkList=>{url}"); + AxiHttpProxy.SendWebRequestProxy request = AxiHttpProxy.Get(url); + yield return request.SendWebRequest; + if (!request.downloadHandler.isDone) + { + callback.Invoke(page, null); + yield break; + } + + if (!request.downloadHandler.bHadErr) + { + var resp = JsonUtility.FromJson(request.downloadHandler.text); + callback.Invoke(page, resp); + yield break; + } + + App.log.Error(request.downloadHandler.ErrInfo); + callback.Invoke(page, null); + + /* + UnityWebRequest request = UnityWebRequest.Get($"{WebSiteApi}/NesRomList?Page={page}&PageSize={pageSize}&SearchKey={searchKey}"); + yield return request.SendWebRequest(); + + if (request.result != UnityWebRequest.Result.Success) + { + callback.Invoke(null); + yield break; + }*/ + + } + private IEnumerator GetMarkListFlow(AxibugProtobuf.RomPlatformType platform, int page, int pageSize, Action callback) + { + string url = $"{WebSiteApi}/MarkList?Page={page}&PageSize={pageSize}&PType={(int)platform}&Token={App.user.Token}"; + App.log.Info($"MarkList=>{url}"); + AxiHttpProxy.SendWebRequestProxy request = AxiHttpProxy.Get(url); + yield return request.SendWebRequest; + if (!request.downloadHandler.isDone) + { + callback.Invoke(page, null); + yield break; + } + + //请求成功 + if (!request.downloadHandler.bHadErr) + { + var resp = JsonUtility.FromJson(request.downloadHandler.text); + callback.Invoke(page, resp); + yield break; + } + + App.log.Error(request.downloadHandler.ErrInfo); + callback.Invoke(page, null); + /* + UnityWebRequest request = UnityWebRequest.Get($"{WebSiteApi}/NesRomList?Page={page}&PageSize={pageSize}"); + yield return request.SendWebRequest(); + + if (request.result != UnityWebRequest.Result.Success) + { + callback.Invoke(null); + yield break; + } + */ + } + + + public IEnumerator GetRomInfo(int RomID, Action callback) + { + + AxiHttpProxy.SendWebRequestProxy request = AxiHttpProxy.Get($"{WebSiteApi}/RomInfo?RomID={RomID}&Token={App.user.Token}"); + yield return request.SendWebRequest; + if (!request.downloadHandler.isDone) + { + callback.Invoke(null); + yield break; + } + + //成功 + if (!request.downloadHandler.bHadErr) + { + var resp = JsonUtility.FromJson(request.downloadHandler.text); + callback.Invoke(resp); + yield break; + } + + App.log.Error(request.downloadHandler.ErrInfo); + callback.Invoke(null); + + /* + UnityWebRequest request = UnityWebRequest.Get($"{WebSiteApi}/RomInfo?PType={PlatformType.Nes}&RomID={RomID}"); + yield return request.SendWebRequest(); + + if (request.result != UnityWebRequest.Result.Success) + { + callback.Invoke(null); + yield break; + }*/ + + } + + enum GameType : byte + { + NONE = 0, + ACT, + ARPG, + AVG, + ETC, + FTG, + PUZ, + RAC, + RPG, + SLG, + SPG, + SRPG, + STG, + TAB, + /// + /// 合卡 + /// + ALLINONE, + } + + [Serializable] + public class Resp_GameList + { + public int page; + public int maxPage; + public int resultAllCount; + public List gameList; + } + + [Serializable] + public class Resp_RomInfo + { public int orderid; - public int id; - //TODO 后续根据ptype,启动游戏时选择核心。和列表设计和UI分组解耦,比如无视平台搜索列表,收藏列表 - public int ptype; - public string romName; - public string gType; - public string desc; - public string url; - public string imgUrl; - public string hash; + public int id; + //TODO 后续根据ptype,启动游戏时选择核心。和列表设计和UI分组解耦,比如无视平台搜索列表,收藏列表 + public int ptype; + public string romName; + public string gType; + public string desc; + public string url; + public string imgUrl; + public string hash; public int stars; /// /// 游玩计数 /// - public int playcount; + public int playcount; /// /// 是否收藏 - /// + /// public int isStar; - public List parentRomIdsList; - } - [Serializable] - public class Resp_CheckStandInfo - { - public int needUpdateClient; - public string serverIp; - public ushort serverPort; - public string clientVersion; - public string downLoadUrl; - } - } -} + public List parentRomIdsList; + } + [Serializable] + public class Resp_CheckStandInfo + { + public int needUpdateClient; + public string serverIp; + public ushort serverPort; + public string clientVersion; + public string downLoadUrl; + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/InputDevicesManager/InputDevicesManager.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/InputDevicesManager/InputDevicesManager.cs index 3c540c77..5a793201 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/InputDevicesManager/InputDevicesManager.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/InputDevicesManager/InputDevicesManager.cs @@ -73,32 +73,48 @@ namespace AxibugEmuOnline.Client.InputDevices { return m_devices.Values; } - + List templog = new List(); /// 由外部驱动的逻辑更新入口 public void Update() { foreach (var device in m_devices.Values) device.Update(); - DebugInputSystem(); - } + //string HadDrive = ""; + //foreach (var device in InputSystem.devices) + //{ + // if (device is Mouse) + // continue; + // bool bhadflag = false; - private static void DebugInputSystem() - { - return; -#if ENABLE_INPUT_SYSTEM - foreach (var device in InputSystem.devices) - { - if (device is Mouse) - continue; - for (int i = 0; i < device.allControls.Count; i++) - { - if (device.allControls[i].IsPressed(0)) - { - Debug.Log($"{device.displayName}| {device.allControls[i].displayName}|{device.allControls[i].name}"); - } - } - } -#endif + // templog.Clear(); + // for (int i = 0; i < device.allControls.Count; i++) + // { + // if (device.allControls[i].IsPressed(0)) + // { + // if (device.allControls[i].name.ToLower() == "anykey") + // continue; + // bhadflag = true; + // string keyname = $"{device.allControls[i].GetType().FullName}|{device.allControls[i].name},"; + // templog.Add(keyname); + // } + // } + + // if (bhadflag) + // { + // HadDrive += $" D:{device.GetType().FullName}|{device.GetType().BaseType.FullName}|{device.name}, K:"; + // foreach (var s in templog) + // { + // HadDrive += s; + // } + // } + + //} + + //if (!string.IsNullOrEmpty(HadDrive)) + //{ + // Debug.Log($"Had Drive: {HadDrive}"); + //} + } } } \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/RomFile.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/RomFile.cs index b6a5f12f..bd0880e1 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/RomFile.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/RomFile.cs @@ -1,22 +1,22 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugEmuOnline.Client.Event; -using AxibugProtobuf; -using ICSharpCode.SharpZipLib.Zip; -using System; -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -namespace AxibugEmuOnline.Client -{ - public class RomFile - { - private HttpAPI.Resp_RomInfo webData; - /// 依赖的Rom文件 - private List dependencies = new List(); +using AxibugEmuOnline.Client.ClientCore; +using AxibugEmuOnline.Client.Event; +using AxibugProtobuf; +using ICSharpCode.SharpZipLib.Zip; +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace AxibugEmuOnline.Client +{ + public class RomFile + { + private HttpAPI.Resp_RomInfo webData; + /// 依赖的Rom文件 + private List dependencies = new List(); RomPlatformType m_defaultPlatform; - - /// 指示该Rom是否是多文件Rom + + /// 指示该Rom是否是多文件Rom public bool MultiFileRom { get @@ -41,10 +41,10 @@ namespace AxibugEmuOnline.Client default: throw new NotImplementedException($"未实现的平台{Platform}"); } } - } - + } + public string FileExtentionName - { + { get { switch (Platform) @@ -63,10 +63,10 @@ namespace AxibugEmuOnline.Client default: throw new NotImplementedException($"未实现的平台{Platform}"); } - } - } - - bool m_hasLocalFile; + } + } + + bool m_hasLocalFile; public bool HasLocalFile { get @@ -80,12 +80,12 @@ namespace AxibugEmuOnline.Client return true; } - } - - /// 指示该Rom文件的存放路径 - public string LocalFilePath => $"{App.PersistentDataPath(Platform)}/RemoteRoms/{FileName}"; - - /// 指示该Rom文件是否已下载完毕 + } + + /// 指示该Rom文件的存放路径 + public string LocalFilePath => $"{App.PersistentDataPath(Platform)}/RemoteRoms/{FileName}"; + + /// 指示该Rom文件是否已下载完毕 public bool RomReady { get @@ -99,8 +99,8 @@ namespace AxibugEmuOnline.Client return true; } - } - /// 指示是否正在下载Rom文件 + } + /// 指示是否正在下载Rom文件 public bool IsDownloading { get @@ -141,10 +141,10 @@ namespace AxibugEmuOnline.Client return progress / (dependencies.Count + 1); } - } - - public RomPlatformType Platform => webData != null ? (RomPlatformType)webData.ptype : m_defaultPlatform; - /// 指示该Rom信息是否已填充 + } + + public RomPlatformType Platform => webData != null ? (RomPlatformType)webData.ptype : m_defaultPlatform; + /// 指示该Rom信息是否已填充 public bool InfoReady { get @@ -158,23 +158,23 @@ namespace AxibugEmuOnline.Client return true; } - } - /// 唯一标识 - public int ID => webData != null ? webData.id : -1; - /// 别名 - public string Alias => webData.romName; - /// 描述 - public string Descript => webData.desc; - /// 游戏类型 - public string GameTypeDes => webData.gType; - /// 小图URL - public string ImageURL => webData.imgUrl; - - /// 文件名 - public string FileName { get; private set; } - /// 在查询结果中的索引 - public int Index { get; private set; } - /// 在查询结果中的所在页 + } + /// 唯一标识 + public int ID => webData != null ? webData.id : -1; + /// 别名 + public string Alias => webData.romName; + /// 描述 + public string Descript => webData.desc; + /// 游戏类型 + public string GameTypeDes => webData.gType; + /// 小图URL + public string ImageURL => webData.imgUrl; + + /// 文件名 + public string FileName { get; private set; } + /// 在查询结果中的索引 + public int Index { get; private set; } + /// 在查询结果中的所在页 public int Page { get; private set; } public string Hash => webData != null ? webData.hash : string.Empty; @@ -189,16 +189,16 @@ namespace AxibugEmuOnline.Client } } - public event Action OnDownloadOver; - public event Action OnInfoFilled; - - public RomFile(int index, int insidePage, RomPlatformType defaultPlatform) - { - Index = index; - Page = insidePage; - m_defaultPlatform = defaultPlatform; - } - + public event Action OnDownloadOver; + public event Action OnInfoFilled; + + public RomFile(int index, int insidePage, RomPlatformType defaultPlatform) + { + Index = index; + Page = insidePage; + m_defaultPlatform = defaultPlatform; + } + public void CheckLocalFileState() { if (webData == null) m_hasLocalFile = false; @@ -215,22 +215,22 @@ namespace AxibugEmuOnline.Client foreach (var depRom in dependencies) depRom.CheckLocalFileState(); - } - - public void BeginDownload() - { - if (RomReady) return; - if (IsDownloading) return; - - //检查依赖Rom的下载情况 + } + + public void BeginDownload() + { + if (RomReady) return; + if (IsDownloading) return; + + //检查依赖Rom的下载情况 foreach (var depRom in dependencies) { depRom.BeginDownload(); - } + } App.FileDownloader.BeginDownload(webData.url, (bytes) => { - HandleRomFilePostProcess(bytes); - }); + HandleRomFilePostProcess(bytes); + }); } private void HandleRomFilePostProcess(byte[] bytes) @@ -244,23 +244,23 @@ namespace AxibugEmuOnline.Client var zip = new ZipInputStream(new System.IO.MemoryStream(bytes)); List depth0Files = new List(); - while (true) - { + while (true) + { var currentEntry = zip.GetNextEntry(); - if (currentEntry == null) break; - - if (currentEntry.IsDirectory) continue; - - var buffer = new byte[1024]; - System.IO.MemoryStream output = new System.IO.MemoryStream(); - while (true) - { - var size = zip.Read(buffer, 0, buffer.Length); - if (size == 0) break; - else output.Write(buffer, 0, size); - } - output.Flush(); - unzipFiles[$"{LocalFilePath}/{currentEntry.Name}"] = output.ToArray(); + if (currentEntry == null) break; + + if (currentEntry.IsDirectory) continue; + + var buffer = new byte[1024]; + System.IO.MemoryStream output = new System.IO.MemoryStream(); + while (true) + { + var size = zip.Read(buffer, 0, buffer.Length); + if (size == 0) break; + else output.Write(buffer, 0, size); + } + output.Flush(); + unzipFiles[$"{LocalFilePath}/{currentEntry.Name}"] = output.ToArray(); } string rootDirName = null; @@ -289,50 +289,50 @@ namespace AxibugEmuOnline.Client OnDownloadOver?.Invoke(this); } - public byte[] GetRomFileData() - { - Debug.Assert(!MultiFileRom, "仅供单文件Rom使用的接口"); - - if (webData == null) throw new Exception("Not Valid Rom"); - if (!RomReady) throw new Exception("Rom File Not Downloaded"); - - var bytes = AxiIO.File.ReadAllBytes(LocalFilePath); - if (System.IO.Path.GetExtension(LocalFilePath).ToLower() == ".zip") - { + public byte[] GetRomFileData() + { + Debug.Assert(!MultiFileRom, "仅供单文件Rom使用的接口"); + + if (webData == null) throw new Exception("Not Valid Rom"); + if (!RomReady) throw new Exception("Rom File Not Downloaded"); + + var bytes = AxiIO.File.ReadAllBytes(LocalFilePath); + if (System.IO.Path.GetExtension(LocalFilePath).ToLower() == ".zip") + { var zip = new ZipInputStream(new System.IO.MemoryStream(bytes)); - while (true) - { - var currentEntry = zip.GetNextEntry(); - if (currentEntry == null) break; + while (true) + { + var currentEntry = zip.GetNextEntry(); + if (currentEntry == null) break; //当前平台单文件rom扩展名判断 - if (!currentEntry.Name.ToLower().EndsWith(FileExtentionName)) continue; - - var buffer = new byte[1024]; - System.IO.MemoryStream output = new System.IO.MemoryStream(); - while (true) - { - var size = zip.Read(buffer, 0, buffer.Length); - if (size == 0) break; - else output.Write(buffer, 0, size); - } - output.Flush(); - return output.ToArray(); - } - } - else - { - return bytes; - } - - throw new Exception("Not Valid Rom Data"); + if (!currentEntry.Name.ToLower().EndsWith(FileExtentionName)) continue; + + var buffer = new byte[1024]; + System.IO.MemoryStream output = new System.IO.MemoryStream(); + while (true) + { + var size = zip.Read(buffer, 0, buffer.Length); + if (size == 0) break; + else output.Write(buffer, 0, size); + } + output.Flush(); + return output.ToArray(); + } + } + else + { + return bytes; + } + + throw new Exception("Not Valid Rom Data"); } - public void SetWebData(HttpAPI.Resp_RomInfo resp_RomInfo) - { - webData = resp_RomInfo; - FileName = MultiFileRom ? System.IO.Path.GetFileNameWithoutExtension(webData.url) : System.IO.Path.GetFileName(webData.url); - FileName = System.Net.WebUtility.UrlDecode(FileName); + public void SetWebData(HttpAPI.Resp_RomInfo resp_RomInfo) + { + webData = resp_RomInfo; + FileName = MultiFileRom ? System.IO.Path.GetFileNameWithoutExtension(webData.url) : System.IO.Path.GetFileName(webData.url); + FileName = System.Net.WebUtility.UrlDecode(FileName); //收集依赖Rom if (webData.parentRomIdsList != null) @@ -349,9 +349,9 @@ namespace AxibugEmuOnline.Client } } - CheckLocalFileState(); - - App.StartCoroutine(WaitInfoReady()); + CheckLocalFileState(); + + App.StartCoroutine(WaitInfoReady()); } private IEnumerator WaitInfoReady() @@ -359,6 +359,6 @@ namespace AxibugEmuOnline.Client while (!InfoReady) yield return null; OnInfoFilled?.Invoke(); - } - } -} + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/RomLib.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/RomLib.cs index 5da6d78a..acfac4f6 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/RomLib.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/RomLib/RomLib.cs @@ -1,20 +1,20 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugEmuOnline.Client.Common; -using AxibugEmuOnline.Client.Event; -using AxibugProtobuf; -using System; -using System.Collections.Generic; -using System.Linq; -using static AxibugEmuOnline.Client.HttpAPI; - -namespace AxibugEmuOnline.Client +using AxibugEmuOnline.Client.ClientCore; +using AxibugEmuOnline.Client.Common; +using AxibugEmuOnline.Client.Event; +using AxibugProtobuf; +using System; +using System.Collections.Generic; +using System.Linq; +using static AxibugEmuOnline.Client.HttpAPI; + +namespace AxibugEmuOnline.Client { public class RomLib { - /// Rom请求,一页的大小 + /// Rom请求,一页的大小 private const int PAGE_SIZE = 10; - /// 请求指令 + /// 请求指令 private HashSet FetchPageCmd = new HashSet(); private RomFile[] RomFetchList; private Dictionary RomFileIdMapper = new Dictionary(); @@ -57,23 +57,23 @@ namespace AxibugEmuOnline.Client return romFile; } - /// 清除所有下载的Rom文件 + /// 清除所有下载的Rom文件 public void ClearRomFile() { var path = $"{App.PersistentDataPath(m_platform)}/RemoteRoms"; if (AxiIO.Directory.Exists(path)) AxiIO.Directory.Delete(path, true); } - /// 移除一个已下载的Rom + /// 移除一个已下载的Rom public void RemoveOneRomFile(RomFile romFile) { if (romFile.RomReady) AxiIO.File.Delete(romFile.LocalFilePath); } - /// - /// 获得所有Rom文件 - /// + /// + /// 获得所有Rom文件 + /// public void FetchRomCount(Action callback, string searchKey = null) { lastSearchKey = searchKey; @@ -186,5 +186,5 @@ namespace AxibugEmuOnline.Client { RomFileNameMapper[rom.FileName] = rom; } - } -} + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SavCloudApi.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SavCloudApi.cs index 484c7c38..8821f113 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SavCloudApi.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SavCloudApi.cs @@ -1,126 +1,126 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugEmuOnline.Client.Common; -using AxibugEmuOnline.Client.Event; -using AxibugEmuOnline.Client.Network; -using AxibugProtobuf; -using System.Collections.Generic; -using System.Linq; - -namespace AxibugEmuOnline.Client -{ +using AxibugEmuOnline.Client.ClientCore; +using AxibugEmuOnline.Client.Common; +using AxibugEmuOnline.Client.Event; +using AxibugEmuOnline.Client.Network; +using AxibugProtobuf; +using System.Collections.Generic; +using System.Linq; + +namespace AxibugEmuOnline.Client +{ /// /// 负责存档的云端保存和获取功能 - /// - public class SavCloudApi - { - public delegate void OnFetchGameSavListHandle(int romID, Protobuf_Mine_GameSavInfo[] savSlotData); - public event OnFetchGameSavListHandle OnFetchGameSavList; - public delegate void OnUploadedSavDataHandle(int romID, int slotIndex, Protobuf_Mine_GameSavInfo savInfo); - public event OnUploadedSavDataHandle OnUploadedSavData; - - public SavCloudApi() - { - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdGamesavGetGameSavList, RecvGetGameSavList); - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdGamesavDelGameSav, RecvDelGameSavList); - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdGamesavUploadGameSav, RecvUpLoadGameSav); - } - - private HashSet m_fetchingRomIDs = new HashSet(); - /// - /// 发送请求即时存档列表 - /// - /// - public void SendGetGameSavList(int RomID) - { - if (m_fetchingRomIDs.Contains(RomID)) return; - - Protobuf_Mine_GetGameSavList req = new Protobuf_Mine_GetGameSavList() - { - RomID = RomID, - }; - App.log.Info($"SendGetGameSavList"); - App.network.SendToServer((int)CommandID.CmdGamesavGetGameSavList, ProtoBufHelper.Serizlize(req)); - } - - void RecvGetGameSavList(byte[] reqData) - { + /// + public class SavCloudApi + { + public delegate void OnFetchGameSavListHandle(int romID, Protobuf_Mine_GameSavInfo[] savSlotData); + public event OnFetchGameSavListHandle OnFetchGameSavList; + public delegate void OnUploadedSavDataHandle(int romID, int slotIndex, Protobuf_Mine_GameSavInfo savInfo); + public event OnUploadedSavDataHandle OnUploadedSavData; + + public SavCloudApi() + { + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdGamesavGetGameSavList, RecvGetGameSavList); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdGamesavDelGameSav, RecvDelGameSavList); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdGamesavUploadGameSav, RecvUpLoadGameSav); + } + + private HashSet m_fetchingRomIDs = new HashSet(); + /// + /// 发送请求即时存档列表 + /// + /// + public void SendGetGameSavList(int RomID) + { + if (m_fetchingRomIDs.Contains(RomID)) return; + + Protobuf_Mine_GetGameSavList req = new Protobuf_Mine_GetGameSavList() + { + RomID = RomID, + }; + App.log.Info($"SendGetGameSavList"); + App.network.SendToServer((int)CommandID.CmdGamesavGetGameSavList, ProtoBufHelper.Serizlize(req)); + } + + void RecvGetGameSavList(byte[] reqData) + { Protobuf_Mine_GetGameSavList_RESP msg = ProtoBufHelper.DeSerizlize(reqData); - if (m_fetchingRomIDs.Remove(msg.RomID)) return; - - Protobuf_Mine_GameSavInfo[] savArr = new Protobuf_Mine_GameSavInfo[4]; - for (int i = 0; i < savArr.Length; i++) - { - Protobuf_Mine_GameSavInfo info = msg.SavDataList.FirstOrDefault(w => w.SavDataIdx == i); - savArr[i] = info; - } - OnFetchGameSavList?.Invoke(msg.RomID, savArr); - } - - /// - /// 发送删除即时存档 - /// - /// - /// - public void SendDelGameSavList(int RomID, int SavDataIdx) - { - Protobuf_Mine_DelGameSav req = new Protobuf_Mine_DelGameSav() - { - RomID = RomID, - SavDataIdx = SavDataIdx - }; - App.log.Info($"SendDelGameSavList"); - App.network.SendToServer((int)CommandID.CmdGamesavDelGameSav, ProtoBufHelper.Serizlize(req)); - } - - void RecvDelGameSavList(byte[] reqData) - { - Protobuf_Mine_DelGameSav_RESP msg = ProtoBufHelper.DeSerizlize(reqData); - Eventer.Instance.PostEvent(EEvent.OnNetGameSavDeleted, msg.RomID, msg.SavDataIdx); - } - - /// - /// 上传即时存档 - /// - /// - /// - public void SendUpLoadGameSav(int RomID, int SavDataIdx, uint sequence, byte[] RawData, byte[] SavImgData) - { - //压缩 - byte[] compressRawData = Helper.CompressByteArray(RawData); - - //压缩 - byte[] compressImgData = Helper.CompressByteArray(SavImgData); - - Protobuf_Mine_UpLoadGameSav req = new Protobuf_Mine_UpLoadGameSav() - { - RomID = RomID, - SavDataIdx = SavDataIdx, - StateRaw = Google.Protobuf.ByteString.CopyFrom(compressRawData), + if (m_fetchingRomIDs.Remove(msg.RomID)) return; + + Protobuf_Mine_GameSavInfo[] savArr = new Protobuf_Mine_GameSavInfo[4]; + for (int i = 0; i < savArr.Length; i++) + { + Protobuf_Mine_GameSavInfo info = msg.SavDataList.FirstOrDefault(w => w.SavDataIdx == i); + savArr[i] = info; + } + OnFetchGameSavList?.Invoke(msg.RomID, savArr); + } + + /// + /// 发送删除即时存档 + /// + /// + /// + public void SendDelGameSavList(int RomID, int SavDataIdx) + { + Protobuf_Mine_DelGameSav req = new Protobuf_Mine_DelGameSav() + { + RomID = RomID, + SavDataIdx = SavDataIdx + }; + App.log.Info($"SendDelGameSavList"); + App.network.SendToServer((int)CommandID.CmdGamesavDelGameSav, ProtoBufHelper.Serizlize(req)); + } + + void RecvDelGameSavList(byte[] reqData) + { + Protobuf_Mine_DelGameSav_RESP msg = ProtoBufHelper.DeSerizlize(reqData); + Eventer.Instance.PostEvent(EEvent.OnNetGameSavDeleted, msg.RomID, msg.SavDataIdx); + } + + /// + /// 上传即时存档 + /// + /// + /// + public void SendUpLoadGameSav(int RomID, int SavDataIdx, uint sequence, byte[] RawData, byte[] SavImgData) + { + //压缩 + byte[] compressRawData = Helper.CompressByteArray(RawData); + + //压缩 + byte[] compressImgData = Helper.CompressByteArray(SavImgData); + + Protobuf_Mine_UpLoadGameSav req = new Protobuf_Mine_UpLoadGameSav() + { + RomID = RomID, + SavDataIdx = SavDataIdx, + StateRaw = Google.Protobuf.ByteString.CopyFrom(compressRawData), SavImg = Google.Protobuf.ByteString.CopyFrom(compressImgData), Sequence = (int)sequence - }; - - App.log.Info($"SendDelGameSavList"); - App.log.Info($"上传即时存档数据 原数据大小:{RawData.Length},压缩后;{compressRawData.Length}"); - App.log.Info($"上传截图 原数据大小:{SavImgData.Length},压缩后;{compressImgData.Length}"); - - App.network.SendToServer((int)CommandID.CmdGamesavUploadGameSav, ProtoBufHelper.Serizlize(req)); - } - - void RecvUpLoadGameSav(byte[] reqData) - { - Protobuf_Mine_UpLoadGameSav_RESP msg = ProtoBufHelper.DeSerizlize(reqData); - OnUploadedSavData?.Invoke(msg.RomID, msg.SavDataIdx, msg.UploadSevInfo); - } - - /// - /// 即时存档或网络截图下载完成之后,需要先解压再使用 - /// - /// - public byte[] UnGzipData(byte[] data) - { - return Helper.DecompressByteArray(data); - } - } + }; + + App.log.Info($"SendDelGameSavList"); + App.log.Info($"上传即时存档数据 原数据大小:{RawData.Length},压缩后;{compressRawData.Length}"); + App.log.Info($"上传截图 原数据大小:{SavImgData.Length},压缩后;{compressImgData.Length}"); + + App.network.SendToServer((int)CommandID.CmdGamesavUploadGameSav, ProtoBufHelper.Serizlize(req)); + } + + void RecvUpLoadGameSav(byte[] reqData) + { + Protobuf_Mine_UpLoadGameSav_RESP msg = ProtoBufHelper.DeSerizlize(reqData); + OnUploadedSavData?.Invoke(msg.RomID, msg.SavDataIdx, msg.UploadSevInfo); + } + + /// + /// 即时存档或网络截图下载完成之后,需要先解压再使用 + /// + /// + public byte[] UnGzipData(byte[] data) + { + return Helper.DecompressByteArray(data); + } + } } \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFile.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFile.cs index 91cbc4d5..fa08afc3 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFile.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFile.cs @@ -172,6 +172,8 @@ namespace AxibugEmuOnline.Client public unsafe void Save(uint sequence, byte[] savData, byte[] screenShotData) { + if (IsBusy) return; + var filePath = FilePath; var header = new Header diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/DownloadingState.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/DownloadingState.cs index 23949a35..951d4c9d 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/DownloadingState.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/SaveSlotManager/SaveFileSyncStates/DownloadingState.cs @@ -26,8 +26,8 @@ namespace AxibugEmuOnline.Client } m_sequece = (uint)netData.Sequence; - m_downloadTask = AxiHttpProxy.GetDownLoad($"{App.httpAPI.WebHost}/{netData.SavUrl}?v={m_sequece}"); - m_downloadTaskImg = AxiHttpProxy.GetDownLoad($"{App.httpAPI.WebHost}/{netData.SavImgUrl}?v={m_sequece}"); + m_downloadTask = AxiHttpProxy.GetDownLoad($"{App.httpAPI.WebHost}/{netData.SavUrl}"); + m_downloadTaskImg = AxiHttpProxy.GetDownLoad($"{App.httpAPI.WebHost}/{netData.SavImgUrl}"); Host.SetSavingFlag(); } @@ -52,25 +52,14 @@ namespace AxibugEmuOnline.Client if (m_downloadTaskImg.downloadHandler.bHadErr) //下载失败 { - FSM.GetState().Error = m_downloadTaskImg.downloadHandler.ErrInfo; - FSM.ChangeState(); + FSM.ChangeState(); return; } - try - { - var savData = Host.CloudAPI.UnGzipData(m_downloadTask.downloadHandler.data); - var imgData = m_downloadTaskImg.downloadHandler.data; //图片数据已被服务器解压 - - Host.Save(m_sequece, savData, imgData); - FSM.ChangeState(); - } - catch - { - FSM.GetState().Error = "云存档解压失败"; - FSM.ChangeState(); - return; - } + var savData = Host.CloudAPI.UnGzipData(m_downloadTask.downloadHandler.data); + var imgData = Host.CloudAPI.UnGzipData(m_downloadTaskImg.downloadHandler.data); + Host.Save(m_sequece, savData, imgData); + FSM.ChangeState(); } } diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/UserDataManager.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/UserDataManager.cs index 4c0ce88b..f6bd247f 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/UserDataManager.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/UserDataManager.cs @@ -1,225 +1,225 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugEmuOnline.Client.Common; -using AxibugEmuOnline.Client.Event; -using AxibugEmuOnline.Client.Network; -using AxibugProtobuf; -using System.Collections.Generic; -using System.Linq; - -namespace AxibugEmuOnline.Client.Manager -{ - public class UserDataBase - { - public long UID { get; set; } - public string Account { get; set; } - public string NickName { get; set; } - } - - public class MainUserDataBase : UserDataBase - { +using AxibugEmuOnline.Client.ClientCore; +using AxibugEmuOnline.Client.Common; +using AxibugEmuOnline.Client.Event; +using AxibugEmuOnline.Client.Network; +using AxibugProtobuf; +using System.Collections.Generic; +using System.Linq; + +namespace AxibugEmuOnline.Client.Manager +{ + public class UserDataBase + { + public long UID { get; set; } + public string Account { get; set; } + public string NickName { get; set; } + } + + public class MainUserDataBase : UserDataBase + { public bool IsLoggedIn { get; set; } = false; public string Token { get; set; } - } - - public class UserDataManager - { - public UserDataManager() - { - //注册重连成功事件,以便后续自动登录 - App.network.OnReConnected += OnReConnected; - - //网络事件注册 - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdUserOnlinelist, RecvUserOnlinelist); - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdUserJoin, RecvCmdUserJoin); - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdUserLeave, RecvGetUserLeave); - - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdModifyNickName, RecvModifyNickName); - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdUpdateSelfUserInfo, RecvUpdateSelfUserInfo); - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdUpdateOtherUserInfo, RecvUpdateOtherUserInfo); - } - - public MainUserDataBase userdata { get; private set; } = new MainUserDataBase(); - public bool IsLoggedIn => userdata.IsLoggedIn; - public string Token => userdata.IsLoggedIn ? userdata.Token : string.Empty; - Dictionary DictUID2User = new Dictionary(); - public int OnlinePlayerCount => DictUID2User.Count; - public void InitMainUserData(string UName, long UID, string token) - { - userdata.NickName = UName; - userdata.IsLoggedIn = true; - userdata.UID = UID; + } + + public class UserDataManager + { + public UserDataManager() + { + //注册重连成功事件,以便后续自动登录 + App.network.OnReConnected += OnReConnected; + + //网络事件注册 + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdUserOnlinelist, RecvUserOnlinelist); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdUserJoin, RecvCmdUserJoin); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdUserLeave, RecvGetUserLeave); + + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdModifyNickName, RecvModifyNickName); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdUpdateSelfUserInfo, RecvUpdateSelfUserInfo); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdUpdateOtherUserInfo, RecvUpdateOtherUserInfo); + } + + public MainUserDataBase userdata { get; private set; } = new MainUserDataBase(); + public bool IsLoggedIn => userdata.IsLoggedIn; + public string Token => userdata.IsLoggedIn ? userdata.Token : string.Empty; + Dictionary DictUID2User = new Dictionary(); + public int OnlinePlayerCount => DictUID2User.Count; + public void InitMainUserData(string UName, long UID, string token) + { + userdata.NickName = UName; + userdata.IsLoggedIn = true; + userdata.UID = UID; userdata.Token = token; -#if UNITY_EDITOR - App.log.Debug($"收到登录token:{token}"); -#endif +#if UNITY_EDITOR + App.log.Debug($"收到登录token:{token}"); +#endif //以及其他数据初始化 //... - } - /// - /// 登出 - /// - public void LoginOutData() - { - userdata.IsLoggedIn = false; - //以及其他数据清理 - //... - } - /// - /// 当重连成功 - /// - public void OnReConnected() - { - //如果之前已登录,则重新登录 - if (userdata.IsLoggedIn) - { - App.login.Login(); - } - } - - #region 角色管理 - public void UpdateOrAddUser(UserMiniInfo minfo, out bool isNewUser) - { - lock (DictUID2User) - { - if (!DictUID2User.ContainsKey(minfo.UID)) - { - DictUID2User[minfo.UID] = new UserDataBase() - { - UID = minfo.UID, - NickName = minfo.NickName, - Account = "", - }; - isNewUser = true; - } - else - { - isNewUser = false; - DictUID2User[minfo.UID].NickName = minfo.NickName; - } - } - } - - public void RemoveUser(long UID) - { - bool bflag = false; - string UName = ""; - lock (DictUID2User) - { - if (DictUID2User.ContainsKey(UID)) - { - UName = DictUID2User[UID].NickName; - DictUID2User.Remove(UID); - bflag = true; - } - } - if (bflag) - { - //抛出用户离开事件 - Eventer.Instance.PostEvent(EEvent.OnUserLoginOut, UID, UName); - } - } - public UserDataBase GetUserByUid(long UID) - { - lock (DictUID2User) - { - if (DictUID2User.ContainsKey(UID)) - { - return DictUID2User[UID]; - } - return null; - } - } - - public UserDataBase[] GetUserList() - { - UserDataBase[] ulist = new UserDataBase[DictUID2User.Count]; - long[] UIDs = DictUID2User.Keys.ToArray(); - for (int i = 0; i < UIDs.Length; i++) - { - ulist[i] = DictUID2User[UIDs[i]]; - } - return ulist; - } - #endregion - - /// - /// 请求拉取房间列表 - /// - public void Send_GetUserList() - { - Protobuf_UserList msg = new Protobuf_UserList() - { - }; - App.network.SendToServer((int)CommandID.CmdUserOnlinelist, ProtoBufHelper.Serizlize(msg)); - } - - public void RecvUserOnlinelist(byte[] reqData) - { - Protobuf_UserList_RESP msg = ProtoBufHelper.DeSerizlize(reqData); - DictUID2User.Clear(); - for (int i = 0; i < msg.UserList.Count; i++) - { - UserMiniInfo mi = msg.UserList[i]; - bool isNewUser; - UpdateOrAddUser(mi, out isNewUser); - } - Eventer.Instance.PostEvent(EEvent.OnUserListAllUpdate); - } - public void RecvCmdUserJoin(byte[] reqData) - { - Protobuf_UserJoin_RESP msg = ProtoBufHelper.DeSerizlize(reqData); - bool isNewUser; - UpdateOrAddUser(msg.UserInfo, out isNewUser); - if (isNewUser) + } + /// + /// 登出 + /// + public void LoginOutData() + { + userdata.IsLoggedIn = false; + //以及其他数据清理 + //... + } + /// + /// 当重连成功 + /// + public void OnReConnected() + { + //如果之前已登录,则重新登录 + if (userdata.IsLoggedIn) { - Eventer.Instance.PostEvent(EEvent.OnUserLogin, msg.UserInfo.UID, msg.UserInfo.NickName); - OverlayManager.PopTip($"玩家[{msg.UserInfo.NickName}]上线了"); - } - } - - public void RecvGetUserLeave(byte[] reqData) - { - Protobuf_UserLeave_RESP msg = ProtoBufHelper.DeSerizlize(reqData); - RemoveUser(msg.UID); - } - - /// - /// 发送修改昵称请求 - /// - /// - public void Send_ModifyNickName(string NickName) - { - Protobuf_Modify_NickName msg = new Protobuf_Modify_NickName() - { - NickName = NickName - }; - App.network.SendToServer((int)CommandID.CmdModifyNickName, ProtoBufHelper.Serizlize(msg)); - } - - void RecvModifyNickName(byte[] reqData) - { - Protobuf_Modify_NickName_RESP msg = ProtoBufHelper.DeSerizlize(reqData); - } - - private void RecvUpdateSelfUserInfo(byte[] reqData) - { - Protobuf_Update_UserInfo_RESP msg = ProtoBufHelper.DeSerizlize(reqData); - userdata.NickName = msg.UserInfo.NickName; - Eventer.Instance.PostEvent(EEvent.OnSelfInfoUpdate); - } - - private void RecvUpdateOtherUserInfo(byte[] reqData) - { - Protobuf_Update_OtherUserInfo_RESP msg = ProtoBufHelper.DeSerizlize(reqData); - UserDataBase userdata = GetUserByUid(msg.UID); - if (userdata == null) - return; - userdata.NickName = msg.UserInfo.NickName; - - App.roomMgr.ChangeCurrRoomPlayerName(msg.UID); - - Eventer.Instance.PostEvent(EEvent.OnOtherUserInfoUpdate, msg.UID); - } - - } -} + App.login.Login(); + } + } + + #region 角色管理 + public void UpdateOrAddUser(UserMiniInfo minfo, out bool isNewUser) + { + lock (DictUID2User) + { + if (!DictUID2User.ContainsKey(minfo.UID)) + { + DictUID2User[minfo.UID] = new UserDataBase() + { + UID = minfo.UID, + NickName = minfo.NickName, + Account = "", + }; + isNewUser = true; + } + else + { + isNewUser = false; + DictUID2User[minfo.UID].NickName = minfo.NickName; + } + } + } + + public void RemoveUser(long UID) + { + bool bflag = false; + string UName = ""; + lock (DictUID2User) + { + if (DictUID2User.ContainsKey(UID)) + { + UName = DictUID2User[UID].NickName; + DictUID2User.Remove(UID); + bflag = true; + } + } + if (bflag) + { + //抛出用户离开事件 + Eventer.Instance.PostEvent(EEvent.OnUserLoginOut, UID, UName); + } + } + public UserDataBase GetUserByUid(long UID) + { + lock (DictUID2User) + { + if (DictUID2User.ContainsKey(UID)) + { + return DictUID2User[UID]; + } + return null; + } + } + + public UserDataBase[] GetUserList() + { + UserDataBase[] ulist = new UserDataBase[DictUID2User.Count]; + long[] UIDs = DictUID2User.Keys.ToArray(); + for (int i = 0; i < UIDs.Length; i++) + { + ulist[i] = DictUID2User[UIDs[i]]; + } + return ulist; + } + #endregion + + /// + /// 请求拉取房间列表 + /// + public void Send_GetUserList() + { + Protobuf_UserList msg = new Protobuf_UserList() + { + }; + App.network.SendToServer((int)CommandID.CmdUserOnlinelist, ProtoBufHelper.Serizlize(msg)); + } + + public void RecvUserOnlinelist(byte[] reqData) + { + Protobuf_UserList_RESP msg = ProtoBufHelper.DeSerizlize(reqData); + DictUID2User.Clear(); + for (int i = 0; i < msg.UserList.Count; i++) + { + UserMiniInfo mi = msg.UserList[i]; + bool isNewUser; + UpdateOrAddUser(mi, out isNewUser); + } + Eventer.Instance.PostEvent(EEvent.OnUserListAllUpdate); + } + public void RecvCmdUserJoin(byte[] reqData) + { + Protobuf_UserJoin_RESP msg = ProtoBufHelper.DeSerizlize(reqData); + bool isNewUser; + UpdateOrAddUser(msg.UserInfo, out isNewUser); + if (isNewUser) + { + Eventer.Instance.PostEvent(EEvent.OnUserLogin, msg.UserInfo.UID, msg.UserInfo.NickName); + OverlayManager.PopTip($"玩家[{msg.UserInfo.NickName}]上线了"); + } + } + + public void RecvGetUserLeave(byte[] reqData) + { + Protobuf_UserLeave_RESP msg = ProtoBufHelper.DeSerizlize(reqData); + RemoveUser(msg.UID); + } + + /// + /// 发送修改昵称请求 + /// + /// + public void Send_ModifyNickName(string NickName) + { + Protobuf_Modify_NickName msg = new Protobuf_Modify_NickName() + { + NickName = NickName + }; + App.network.SendToServer((int)CommandID.CmdModifyNickName, ProtoBufHelper.Serizlize(msg)); + } + + void RecvModifyNickName(byte[] reqData) + { + Protobuf_Modify_NickName_RESP msg = ProtoBufHelper.DeSerizlize(reqData); + } + + private void RecvUpdateSelfUserInfo(byte[] reqData) + { + Protobuf_Update_UserInfo_RESP msg = ProtoBufHelper.DeSerizlize(reqData); + userdata.NickName = msg.UserInfo.NickName; + Eventer.Instance.PostEvent(EEvent.OnSelfInfoUpdate); + } + + private void RecvUpdateOtherUserInfo(byte[] reqData) + { + Protobuf_Update_OtherUserInfo_RESP msg = ProtoBufHelper.DeSerizlize(reqData); + UserDataBase userdata = GetUserByUid(msg.UID); + if (userdata == null) + return; + userdata.NickName = msg.UserInfo.NickName; + + App.roomMgr.ChangeCurrRoomPlayerName(msg.UID); + + Eventer.Instance.PostEvent(EEvent.OnOtherUserInfoUpdate, msg.UID); + } + + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/MsgBool.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/MsgBool.cs index e81f0987..96c541a9 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/MsgBool.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/MsgBool.cs @@ -1,39 +1,39 @@ -/// -/// String和Bool的缝合怪 -/// -public struct MsgBool -{ - public string ErrorMsg; +/// +/// String和Bool的缝合怪 +/// +public struct MsgBool +{ + public string ErrorMsg; public bool Value; //low C# readonly //public override readonly string ToString() - public override string ToString() - { - if (Value) - { - return true.ToString(); - } - else - { - return ErrorMsg; - } - } - - public static implicit operator MsgBool(string errorMsg) - { - return new MsgBool { Value = false, ErrorMsg = errorMsg }; - } - - public static implicit operator MsgBool(bool value) - { - return new MsgBool { Value = value }; - } - - public static implicit operator bool(MsgBool msgBool) - { - return msgBool.Value; + public override string ToString() + { + if (Value) + { + return true.ToString(); + } + else + { + return ErrorMsg; + } + } + + public static implicit operator MsgBool(string errorMsg) + { + return new MsgBool { Value = false, ErrorMsg = errorMsg }; + } + + public static implicit operator MsgBool(bool value) + { + return new MsgBool { Value = value }; + } + + public static implicit operator bool(MsgBool msgBool) + { + return msgBool.Value; } //low C# @@ -42,8 +42,8 @@ public struct MsgBool // return (msgBool.Value, msgBool.ErrorMsg); //} - public static implicit operator string(MsgBool msgBool) - { - return msgBool.ToString(); - } -} + public static implicit operator string(MsgBool msgBool) + { + return msgBool.ToString(); + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Network/NetMsg.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Network/NetMsg.cs index a8f5c314..234f5863 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Network/NetMsg.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Network/NetMsg.cs @@ -1,102 +1,102 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugEmuOnline.Client.Event; -using AxibugProtobuf; -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace AxibugEmuOnline.Client.Network -{ - - public class NetMsg - { - private static NetMsg instance = new NetMsg(); - public static NetMsg Instance { get { return instance; } } - - private Dictionary> netEventDic = new Dictionary>(128); - - private Queue> queueNetMsg = new Queue>(); - public static object lockQueueNetMsg = new object(); +using AxibugEmuOnline.Client.ClientCore; +using AxibugEmuOnline.Client.Event; +using AxibugProtobuf; +using System; +using System.Collections.Generic; +using UnityEngine; - private Queue queueEventFromNet = new Queue(); +namespace AxibugEmuOnline.Client.Network +{ + + public class NetMsg + { + private static NetMsg instance = new NetMsg(); + public static NetMsg Instance { get { return instance; } } + + private Dictionary> netEventDic = new Dictionary>(128); + + private Queue> queueNetMsg = new Queue>(); + public static object lockQueueNetMsg = new object(); + + private Queue queueEventFromNet = new Queue(); public static object lockQueueEventFromNet = new object(); - - - private NetMsg() { } - - - - #region RegisterMsgEvent - - public void RegNetMsgEvent(int cmd, Action callback) - { - InterRegNetMsgEvent(cmd, callback); - } - - private void InterRegNetMsgEvent(int cmd, Delegate callback) - { - if (netEventDic.ContainsKey(cmd)) - { - if (netEventDic[cmd].IndexOf(callback) < 0) - { - netEventDic[cmd].Add(callback); - } - } - else - { - netEventDic.Add(cmd, new List() { callback }); - } - } - #endregion - - #region UnregisterCMD - - public void UnregisterCMD(int evt, Action callback) - { - Delegate tempDelegate = callback; - InterUnregisterCMD(evt, tempDelegate); - } - - private void InterUnregisterCMD(int cmd, Delegate callback) - { - if (netEventDic.ContainsKey(cmd)) - { - netEventDic[cmd].Remove(callback); - if (netEventDic[cmd].Count == 0) netEventDic.Remove(cmd); - } + + + private NetMsg() { } + + + + #region RegisterMsgEvent + + public void RegNetMsgEvent(int cmd, Action callback) + { + InterRegNetMsgEvent(cmd, callback); } - #endregion + + private void InterRegNetMsgEvent(int cmd, Delegate callback) + { + if (netEventDic.ContainsKey(cmd)) + { + if (netEventDic[cmd].IndexOf(callback) < 0) + { + netEventDic[cmd].Add(callback); + } + } + else + { + netEventDic.Add(cmd, new List() { callback }); + } + } + #endregion + + #region UnregisterCMD + + public void UnregisterCMD(int evt, Action callback) + { + Delegate tempDelegate = callback; + InterUnregisterCMD(evt, tempDelegate); + } + + private void InterUnregisterCMD(int cmd, Delegate callback) + { + if (netEventDic.ContainsKey(cmd)) + { + netEventDic[cmd].Remove(callback); + if (netEventDic[cmd].Count == 0) netEventDic.Remove(cmd); + } + } + #endregion public void NextNetEvent() - { - DequeueNesMsg(); - DequeueEventFromNet(); + { + DequeueNesMsg(); + DequeueEventFromNet(); } - #region PostEventFromNet - - public void EnqueueEventFromNet(Action act) - { - lock (lockQueueEventFromNet) - { - queueEventFromNet.Enqueue(act); - } - } - - public void DequeueEventFromNet() - { - lock (lockQueueEventFromNet) - { - while (queueEventFromNet.Count > 0) + #region PostEventFromNet + + public void EnqueueEventFromNet(Action act) + { + lock (lockQueueEventFromNet) + { + queueEventFromNet.Enqueue(act); + } + } + + public void DequeueEventFromNet() + { + lock (lockQueueEventFromNet) + { + while (queueEventFromNet.Count > 0) { - var msgData = queueEventFromNet.Dequeue(); - PostNetEventFromNet(msgData); - } - } - } - - void PostNetEventFromNet(Action act) + var msgData = queueEventFromNet.Dequeue(); + PostNetEventFromNet(msgData); + } + } + } + + void PostNetEventFromNet(Action act) { try { @@ -106,73 +106,73 @@ namespace AxibugEmuOnline.Client.Network { App.log.Error(ex.ToString()); } - } + } #endregion - #region PostNetMsg - - public void EnqueueNetMsg(int cmd, int ERRCODE, byte[] arg) - { - lock (lockQueueNetMsg) - { - queueNetMsg.Enqueue(new ValueTuple(cmd, ERRCODE, arg)); - } - } - - public void DequeueNesMsg() - { - lock (lockQueueNetMsg) - { - while (queueNetMsg.Count > 0) + #region PostNetMsg + + public void EnqueueNetMsg(int cmd, int ERRCODE, byte[] arg) + { + lock (lockQueueNetMsg) + { + queueNetMsg.Enqueue(new ValueTuple(cmd, ERRCODE, arg)); + } + } + + public void DequeueNesMsg() + { + lock (lockQueueNetMsg) + { + while (queueNetMsg.Count > 0) { - var msgData = queueNetMsg.Dequeue(); - PostNetMsgEvent(msgData.Item1, msgData.Item2, msgData.Item3); - } - } - } - - public void PostNetMsgEvent(int cmd, int ERRCODE, byte[] arg) - { - ErrorCode err = ((ErrorCode)ERRCODE); - if (err != ErrorCode.ErrorOk) - { - OverlayManager.PopTip("错误:" + err.ToString()); - } - - List eventList = GetNetEventDicList(cmd); - if (eventList != null) - { - foreach (Delegate callback in eventList) - { - try - { - ((Action)callback)(arg); - } - catch (Exception e) - { - App.log.Error(e.ToString()); - } - } - } - } - #endregion - - /// - /// 获取所有事件 - /// - /// - /// - private List GetNetEventDicList(int cmd) - { - if (netEventDic.ContainsKey(cmd)) - { - List tempList = netEventDic[cmd]; - if (null != tempList) - { - return tempList; - } - } - return null; - } - } -} + var msgData = queueNetMsg.Dequeue(); + PostNetMsgEvent(msgData.Item1, msgData.Item2, msgData.Item3); + } + } + } + + public void PostNetMsgEvent(int cmd, int ERRCODE, byte[] arg) + { + ErrorCode err = ((ErrorCode)ERRCODE); + if (err != ErrorCode.ErrorOk) + { + OverlayManager.PopTip("错误:" + err.ToString()); + } + + List eventList = GetNetEventDicList(cmd); + if (eventList != null) + { + foreach (Delegate callback in eventList) + { + try + { + ((Action)callback)(arg); + } + catch (Exception e) + { + App.log.Error(e.ToString()); + } + } + } + } + #endregion + + /// + /// 获取所有事件 + /// + /// + /// + private List GetNetEventDicList(int cmd) + { + if (netEventDic.ContainsKey(cmd)) + { + List tempList = netEventDic[cmd]; + if (null != tempList) + { + return tempList; + } + } + return null; + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Switch/SwitchCommon.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Switch/SwitchCommon.cs index e28f5ee2..d0d6e381 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Switch/SwitchCommon.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Switch/SwitchCommon.cs @@ -1,9 +1,11 @@ using AxibugEmuOnline.Client; +using AxibugEmuOnline.Client.ClientCore; using UnityEngine; public class SwitchCommon : MonoBehaviour { void Start() { + Debug.Log("SwitchCommon Start"); TickLoop.LoopAction_15s += ApplyCommit; } diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/BgSettingsUI/ScreenScalerListMenuItem.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/BgSettingsUI/ScreenScalerListMenuItem.cs index 4ad2b1fe..bd7347e8 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/BgSettingsUI/ScreenScalerListMenuItem.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/BgSettingsUI/ScreenScalerListMenuItem.cs @@ -1,35 +1,35 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugEmuOnline.Client.Settings; -using System; -using System.Collections.Generic; - -namespace AxibugEmuOnline.Client -{ - public class ScreenScalerListMenuItem : VirtualSubMenuItem - { - public override bool OnEnterItem() - { - App.settings.Filter.EnableFilterPreview(); - - return base.OnEnterItem(); - } - - public override bool OnExitItem() - { - App.settings.Filter.ShutDownFilterPreview(); - +using AxibugEmuOnline.Client.ClientCore; +using AxibugEmuOnline.Client.Settings; +using System; +using System.Collections.Generic; + +namespace AxibugEmuOnline.Client +{ + public class ScreenScalerListMenuItem : VirtualSubMenuItem + { + public override bool OnEnterItem() + { + App.settings.Filter.EnableFilterPreview(); + + return base.OnEnterItem(); + } + + public override bool OnExitItem() + { + App.settings.Filter.ShutDownFilterPreview(); + return base.OnExitItem(); - } - - protected override void GetVirtualListDatas(VirtualListDataHandle callback) - { - List list = new List(); + } + + protected override void GetVirtualListDatas(VirtualListDataHandle callback) + { + List list = new List(); foreach (var enumValue in Enum.GetValues(typeof(ScreenScaler.EnumScalerMode))) list.Add(enumValue); var select = list.IndexOf(App.settings.ScreenScaler.GlobalMode); if (select == -1) select = 0; - callback.Invoke(list, select); - } - } -} + callback.Invoke(list, select); + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/BgSettingsUI/UI_BgSettingItem_Color.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/BgSettingsUI/UI_BgSettingItem_Color.cs index 4632336a..c41971a8 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/BgSettingsUI/UI_BgSettingItem_Color.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/BgSettingsUI/UI_BgSettingItem_Color.cs @@ -1,104 +1,104 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugEmuOnline.Client.Settings; -using AxibugEmuOnline.Client.UI; -using DG.Tweening; -using DG.Tweening.Core; -using DG.Tweening.Plugins.Options; -using System.Linq; -using UnityEngine; - -namespace AxibugEmuOnline.Client -{ - /// - /// 背景颜色设置UI - /// - public class UI_BgSettingItem_Color : MenuItem, IVirtualItem - { - public int Index { get; set; } - public BgColorSettings Datacontext { get; private set; } - - public void SetData(object data) - { - Datacontext = (BgColorSettings)data; - Datacontext.OnColorChanged += Setting_OnColorChanged; - - UpdateView(); - } - - private void Setting_OnColorChanged(XMBColor color) - { - UpdateView(); - } - - private void UpdateView() - { - var color = Datacontext.CurrentColor; - Icon.GetMaterial().SetColor("_Color1", color.color1); - Icon.GetMaterial().SetColor("_Color2", color.color2); - SetBaseInfo("主题色", "设置主题色", color.Name); - } - - public void SetDependencyProperty(object data) - { - SetSelectState(data is ThirdMenuRoot && ((ThirdMenuRoot)data).SelectIndex == Index); - } - - public void Release() - { - Datacontext.OnColorChanged -= Setting_OnColorChanged; - } - public override bool OnEnterItem() - { - var options = Datacontext.Presets.Select(preset => new ColorOption(preset)).ToList(); - var currentColor = Datacontext.CurrentColor; - var index = options.FindIndex(op => op.Color.GetHashCode() == currentColor.GetHashCode()); - OverlayManager.PopSideBar(options, Mathf.Clamp(index, 0, options.Count - 1)); - return false; - } - - public class ColorOption : ExecuteMenu - { - public XMBColor Color; - public override string Name => Color.Name; - +using AxibugEmuOnline.Client.ClientCore; +using AxibugEmuOnline.Client.Settings; +using AxibugEmuOnline.Client.UI; +using DG.Tweening; +using DG.Tweening.Core; +using DG.Tweening.Plugins.Options; +using System.Linq; +using UnityEngine; + +namespace AxibugEmuOnline.Client +{ + /// + /// 背景颜色设置UI + /// + public class UI_BgSettingItem_Color : MenuItem, IVirtualItem + { + public int Index { get; set; } + public BgColorSettings Datacontext { get; private set; } + + public void SetData(object data) + { + Datacontext = (BgColorSettings)data; + Datacontext.OnColorChanged += Setting_OnColorChanged; + + UpdateView(); + } + + private void Setting_OnColorChanged(XMBColor color) + { + UpdateView(); + } + + private void UpdateView() + { + var color = Datacontext.CurrentColor; + Icon.GetMaterial().SetColor("_Color1", color.color1); + Icon.GetMaterial().SetColor("_Color2", color.color2); + SetBaseInfo("主题色", "设置主题色", color.Name); + } + + public void SetDependencyProperty(object data) + { + SetSelectState(data is ThirdMenuRoot && ((ThirdMenuRoot)data).SelectIndex == Index); + } + + public void Release() + { + Datacontext.OnColorChanged -= Setting_OnColorChanged; + } + public override bool OnEnterItem() + { + var options = Datacontext.Presets.Select(preset => new ColorOption(preset)).ToList(); + var currentColor = Datacontext.CurrentColor; + var index = options.FindIndex(op => op.Color.GetHashCode() == currentColor.GetHashCode()); + OverlayManager.PopSideBar(options, Mathf.Clamp(index, 0, options.Count - 1)); + return false; + } + + public class ColorOption : ExecuteMenu + { + public XMBColor Color; + public override string Name => Color.Name; + public ColorOption(XMBColor color) - { - Color = color; - } - - public override void OnShow(OptionUI_MenuItem ui) - { - ui.IconUI.gameObject.SetActiveEx(true); - ui.IconUI.SetMaterial(Resources.Load("Materials/XMBBackGroundPreview")); - ui.IconUI.GetMaterial().SetColor("_Color1", Color.color1); - ui.IconUI.GetMaterial().SetColor("_Color2", Color.color2); - } - - private static TweenerCore s_colorChangeTween; - public override void OnFocus() - { - float progress = 0; - XMBColor start = App.settings.BgColor.CurrentColor; - XMBColor endColor = Color; - - if (s_colorChangeTween != null) - { - s_colorChangeTween.Kill(); - s_colorChangeTween = null; - } - s_colorChangeTween = DOTween.To(() => progress, (x) => - { - progress = x; - var lerpColor = XMBColor.Lerp(start, endColor, x); - App.settings.BgColor.CurrentColor = lerpColor; - }, 1, 1f).SetEase(Ease.OutCubic); - s_colorChangeTween.onComplete = () => - { - s_colorChangeTween = null; - }; - } - - public override void OnExcute(OptionUI optionUI, ref bool cancelHide) { } - } - } -} + { + Color = color; + } + + public override void OnShow(OptionUI_MenuItem ui) + { + ui.IconUI.gameObject.SetActiveEx(true); + ui.IconUI.SetMaterial(Resources.Load("Materials/XMBBackGroundPreview")); + ui.IconUI.GetMaterial().SetColor("_Color1", Color.color1); + ui.IconUI.GetMaterial().SetColor("_Color2", Color.color2); + } + + private static TweenerCore s_colorChangeTween; + public override void OnFocus() + { + float progress = 0; + XMBColor start = App.settings.BgColor.CurrentColor; + XMBColor endColor = Color; + + if (s_colorChangeTween != null) + { + s_colorChangeTween.Kill(); + s_colorChangeTween = null; + } + s_colorChangeTween = DOTween.To(() => progress, (x) => + { + progress = x; + var lerpColor = XMBColor.Lerp(start, endColor, x); + App.settings.BgColor.CurrentColor = lerpColor; + }, 1, 1f).SetEase(Ease.OutCubic); + s_colorChangeTween.onComplete = () => + { + s_colorChangeTween = null; + }; + } + + public override void OnExcute(OptionUI optionUI, ref bool cancelHide) { } + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/BgSettingsUI/UI_FilterItem.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/BgSettingsUI/UI_FilterItem.cs index 54f40ec4..4fe3bc1b 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/BgSettingsUI/UI_FilterItem.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/BgSettingsUI/UI_FilterItem.cs @@ -1,16 +1,16 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugEmuOnline.Client.UI; -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using static AxibugEmuOnline.Client.Settings.FilterManager; - -namespace AxibugEmuOnline.Client +using AxibugEmuOnline.Client.ClientCore; +using AxibugEmuOnline.Client.UI; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using static AxibugEmuOnline.Client.Settings.FilterManager; + +namespace AxibugEmuOnline.Client { - /// - /// 滤镜预览UI - /// + /// + /// 滤镜预览UI + /// public class UI_FilterItem : MenuItem, IVirtualItem { public int Index { get; set; } @@ -199,5 +199,5 @@ namespace AxibugEmuOnline.Client } - } -} + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/BgSettingsUI/UI_ScalerModeItem.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/BgSettingsUI/UI_ScalerModeItem.cs index 3a1e3a57..8b17d8cd 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/BgSettingsUI/UI_ScalerModeItem.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/BgSettingsUI/UI_ScalerModeItem.cs @@ -1,12 +1,12 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugEmuOnline.Client.Settings; -using AxibugEmuOnline.Client.UI; - -namespace AxibugEmuOnline.Client +using AxibugEmuOnline.Client.ClientCore; +using AxibugEmuOnline.Client.Settings; +using AxibugEmuOnline.Client.UI; + +namespace AxibugEmuOnline.Client { - /// - /// 画面比例模式选项UI - /// + /// + /// 画面比例模式选项UI + /// public class UI_ScalerModeItem : MenuItem, IVirtualItem { public int Index { get; set; } @@ -52,5 +52,5 @@ namespace AxibugEmuOnline.Client { return false; } - } -} + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/CommandDispatcher/CommandDispatcher.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/CommandDispatcher/CommandDispatcher.cs index 4926fbdb..57c6d379 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/CommandDispatcher/CommandDispatcher.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/CommandDispatcher/CommandDispatcher.cs @@ -1,118 +1,118 @@ -using System.Collections.Generic; -using UnityEngine; - -namespace AxibugEmuOnline.Client -{ - public class CommandDispatcher : MonoBehaviour - { - public static CommandDispatcher Instance { get; private set; } - - /// 平级注册对象,都会响应指令 - List m_register = new List(); - /// 独占注册对象,指令会被列表中最后一个对象独占 - List m_registerHigh = new List(); - - CommandListener m_listener; - +using System.Collections.Generic; +using UnityEngine; + +namespace AxibugEmuOnline.Client +{ + public class CommandDispatcher : MonoBehaviour + { + public static CommandDispatcher Instance { get; private set; } + + /// 平级注册对象,都会响应指令 + List m_register = new List(); + /// 独占注册对象,指令会被列表中最后一个对象独占 + List m_registerHigh = new List(); + + CommandListener m_listener; + CommandListener.ScheduleType? m_waitMapperSetting = null; public CommandListener.ScheduleType Mode { get => m_listener.Schedule; set => m_waitMapperSetting = value; - } - - private void Awake() - { - Instance = this; - - //初始化command监视器 - m_listener = new CommandListener(); - } - - private void OnDestroy() - { - Instance = null; - } - - public bool IsRegisted(CommandExecuter commandExecuter) - { - return m_register.Contains(commandExecuter) || m_registerHigh.Contains(commandExecuter); - } - - public void RegistController(CommandExecuter controller) - { - if (!controller.AloneMode) - { - if (m_register.Contains(controller)) { return; } - - m_register.Add(controller); - } - else - { - if (m_registerHigh.Contains(controller)) { return; } - - m_registerHigh.Add(controller); - } - } - - public void UnRegistController(CommandExecuter menuItemController) - { - if (!menuItemController.AloneMode) - m_register.Remove(menuItemController); - else - m_registerHigh.Remove(menuItemController); - } - - readonly List oneFrameRegister = new List(); - private void Update() - { - if (!InputUI.IsInputing) - { - peekRegister(oneFrameRegister); - m_listener.Update(oneFrameRegister); - } - - //键位映射在按键响应的堆栈结束后处理,防止迭代器修改问题 - if (m_waitMapperSetting != null) - { - m_listener.Schedule = m_waitMapperSetting.Value; - m_waitMapperSetting = null; - } - } - - private List peekRegister(List results) - { - results.Clear(); - - if (m_registerHigh.Count > 0) - { - for (int i = m_registerHigh.Count - 1; i >= 0; i--) - { - var controller = m_registerHigh[i]; - if (controller.Enable) - { - results.Add(controller); - return results; - } - } - } - - foreach (var controller in m_register) - { - if (!controller.Enable) continue; - - results.Add(controller); - } - - return results; - } - -#if UNITY_EDITOR - public void GetRegisters(out IReadOnlyList normal, out IReadOnlyList alone) - { - normal = m_register; - alone = m_registerHigh; - } -#endif - } -} + } + + private void Awake() + { + Instance = this; + + //初始化command监视器 + m_listener = new CommandListener(); + } + + private void OnDestroy() + { + Instance = null; + } + + public bool IsRegisted(CommandExecuter commandExecuter) + { + return m_register.Contains(commandExecuter) || m_registerHigh.Contains(commandExecuter); + } + + public void RegistController(CommandExecuter controller) + { + if (!controller.AloneMode) + { + if (m_register.Contains(controller)) { return; } + + m_register.Add(controller); + } + else + { + if (m_registerHigh.Contains(controller)) { return; } + + m_registerHigh.Add(controller); + } + } + + public void UnRegistController(CommandExecuter menuItemController) + { + if (!menuItemController.AloneMode) + m_register.Remove(menuItemController); + else + m_registerHigh.Remove(menuItemController); + } + + readonly List oneFrameRegister = new List(); + private void Update() + { + if (!InputUI.IsInputing) + { + peekRegister(oneFrameRegister); + m_listener.Update(oneFrameRegister); + } + + //键位映射在按键响应的堆栈结束后处理,防止迭代器修改问题 + if (m_waitMapperSetting != null) + { + m_listener.Schedule = m_waitMapperSetting.Value; + m_waitMapperSetting = null; + } + } + + private List peekRegister(List results) + { + results.Clear(); + + if (m_registerHigh.Count > 0) + { + for (int i = m_registerHigh.Count - 1; i >= 0; i--) + { + var controller = m_registerHigh[i]; + if (controller.Enable) + { + results.Add(controller); + return results; + } + } + } + + foreach (var controller in m_register) + { + if (!controller.Enable) continue; + + results.Add(controller); + } + + return results; + } + +#if UNITY_EDITOR + public void GetRegisters(out IReadOnlyList normal, out IReadOnlyList alone) + { + normal = m_register; + alone = m_registerHigh; + } +#endif + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/CommandDispatcher/CommandListener.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/CommandDispatcher/CommandListener.cs index af565a5a..aecb1c3f 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/CommandDispatcher/CommandListener.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/CommandDispatcher/CommandListener.cs @@ -1,14 +1,14 @@ -using AxibugEmuOnline.Client.ClientCore; -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace AxibugEmuOnline.Client -{ - public class CommandListener - { - EnumCommand[] m_checkCmds; - List m_commands = new List(); +using AxibugEmuOnline.Client.ClientCore; +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace AxibugEmuOnline.Client +{ + public class CommandListener + { + EnumCommand[] m_checkCmds; + List m_commands = new List(); long CheckFrame = -1; XMBKeyBinding m_keyBinder; public ScheduleType Schedule { get; set; } @@ -17,16 +17,16 @@ namespace AxibugEmuOnline.Client { m_keyBinder = App.settings.KeyMapper.GetBinder(); m_checkCmds = Enum.GetValues(typeof(EnumCommand)) as EnumCommand[]; - } - - IEnumerable GetCommand() - { - if (CheckFrame == Time.frameCount) - return m_commands; - CheckFrame = Time.frameCount; - - m_commands.Clear(); - + } + + IEnumerable GetCommand() + { + if (CheckFrame == Time.frameCount) + return m_commands; + CheckFrame = Time.frameCount; + + m_commands.Clear(); + int controllerIndex = (int)Schedule; foreach (var cmd in m_checkCmds) @@ -36,25 +36,25 @@ namespace AxibugEmuOnline.Client } - return m_commands; - } - - public void Update(IEnumerable executers) - { - foreach (var cmd in GetCommand()) - { - foreach (var executer in executers) - { - //App.log.Debug($"CommandListener GetCommand | {Time.frameCount}|{executer.name}| {cmd.Cmd}|{cmd.Cancel}"); - executer.ExecuteCommand(cmd.Cmd, cmd.Cancel); - } - } - } - + return m_commands; + } + + public void Update(IEnumerable executers) + { + foreach (var cmd in GetCommand()) + { + foreach (var executer in executers) + { + //App.log.Debug($"CommandListener GetCommand | {Time.frameCount}|{executer.name}| {cmd.Cmd}|{cmd.Cancel}"); + executer.ExecuteCommand(cmd.Cmd, cmd.Cancel); + } + } + } + public enum ScheduleType { Normal, Gaming - } - } -} + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/GamesUI/RomItem.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/GamesUI/RomItem.cs index 99198f43..b6b9352c 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/GamesUI/RomItem.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/GamesUI/RomItem.cs @@ -1,45 +1,45 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugEmuOnline.Client.Event; -using AxibugEmuOnline.Client.UI; -using Coffee.UIExtensions; -using UnityEngine; -using UnityEngine.UI; - -namespace AxibugEmuOnline.Client -{ - public class RomItem : MenuItem, IVirtualItem - { - [SerializeField] - Image m_romImage; - - [SerializeField] - GameObject DownloadingFlag; - [SerializeField] - Slider DownProgress; - [SerializeField] - GameObject FileReadyFlag; - [SerializeField] - UIShiny DownloadComplete; - [SerializeField] - GameObject Star; - - public int Index { get; set; } - +using AxibugEmuOnline.Client.ClientCore; +using AxibugEmuOnline.Client.Event; +using AxibugEmuOnline.Client.UI; +using Coffee.UIExtensions; +using UnityEngine; +using UnityEngine.UI; + +namespace AxibugEmuOnline.Client +{ + public class RomItem : MenuItem, IVirtualItem + { + [SerializeField] + Image m_romImage; + + [SerializeField] + GameObject DownloadingFlag; + [SerializeField] + Slider DownProgress; + [SerializeField] + GameObject FileReadyFlag; + [SerializeField] + UIShiny DownloadComplete; + [SerializeField] + GameObject Star; + + public int Index { get; set; } + public bool IsStar { get { return m_romfile != null && m_romfile.InfoReady ? m_romfile.Star : false; } - } - public int RomID { get { return m_romfile != null && m_romfile.InfoReady ? m_romfile.ID : -1; } } - + } + public int RomID { get { return m_romfile != null && m_romfile.InfoReady ? m_romfile.ID : -1; } } + private RomLib m_romlib => App.GetRomLib(m_romfile.Platform); public bool RomInfoReady => m_romfile != null && m_romfile.InfoReady; - private RomFile m_romfile; - + private RomFile m_romfile; + protected override void OnEnable() { Eventer.Instance.RegisterEvent(EEvent.OnRomFileDownloaded, OnRomDownloaded); @@ -59,103 +59,103 @@ namespace AxibugEmuOnline.Client DownloadComplete.Play(); } - public void SetData(object data) - { - Reset(); - - m_romfile = (RomFile)data; - m_romfile.OnInfoFilled += OnRomInfoFilled; - m_romImage.sprite = null; - - UpdateView(); - - if (!m_romfile.InfoReady) - { - m_romlib.BeginFetchRomInfo(m_romfile); - } - - SetSelectState(data is ThirdMenuRoot && ((ThirdMenuRoot)data).SelectIndex == Index); - } - - public void SetDependencyProperty(object data) - { - SetSelectState(data is ThirdMenuRoot && ((ThirdMenuRoot)data).SelectIndex == Index); - } - + public void SetData(object data) + { + Reset(); + + m_romfile = (RomFile)data; + m_romfile.OnInfoFilled += OnRomInfoFilled; + m_romImage.sprite = null; + + UpdateView(); + + if (!m_romfile.InfoReady) + { + m_romlib.BeginFetchRomInfo(m_romfile); + } + + SetSelectState(data is ThirdMenuRoot && ((ThirdMenuRoot)data).SelectIndex == Index); + } + + public void SetDependencyProperty(object data) + { + SetSelectState(data is ThirdMenuRoot && ((ThirdMenuRoot)data).SelectIndex == Index); + } + protected override void OnSelected(float progress) { base.OnSelected(progress); if (m_romImage.sprite == null) LaunchUI.Instance.HideRomPreview(); else LaunchUI.Instance.SetRomPreview(m_romImage.sprite); - } - - public void Release() - { - m_romfile.OnInfoFilled -= OnRomInfoFilled; - } - - private void OnRomInfoFilled() - { - UpdateView(); - } - - private void UpdateView() - { - if (!m_romfile.InfoReady) - { - SetBaseInfo("正在拉取", "---", "---"); - } - else - { - SetBaseInfo(m_romfile.Alias, m_romfile.Descript, m_romfile.GameTypeDes); - App.CacheMgr.GetSpriteCache(m_romfile.ImageURL, (img, url) => - { - if (!m_romfile.InfoReady || url != m_romfile.ImageURL) return; - - m_romImage.sprite = img; - if (m_select) LaunchUI.Instance.SetRomPreview(img); - }); - Star.SetActiveEx(m_romfile.Star); - } - } - - public override bool OnEnterItem() - { - if (!m_romfile.RomReady) - { - m_romfile.BeginDownload(); - return false; - } - else - { - App.emu.BeginGame(m_romfile); - - return false; - } - } - - - protected override void Update() - { - DownloadingFlag.SetActiveEx(false); - FileReadyFlag.SetActiveEx(false); - Star.SetActiveEx(IsStar); - - if (m_romfile == null) return; - if (!m_romfile.InfoReady) return; - - if (m_romfile.IsDownloading) - { - DownloadingFlag.SetActiveEx(true); - DownProgress.value = m_romfile.Progress; - } - else if (m_romfile.RomReady) - { - FileReadyFlag.SetActiveEx(true); - } - - base.Update(); - } - } -} + } + + public void Release() + { + m_romfile.OnInfoFilled -= OnRomInfoFilled; + } + + private void OnRomInfoFilled() + { + UpdateView(); + } + + private void UpdateView() + { + if (!m_romfile.InfoReady) + { + SetBaseInfo("正在拉取", "---", "---"); + } + else + { + SetBaseInfo(m_romfile.Alias, m_romfile.Descript, m_romfile.GameTypeDes); + App.CacheMgr.GetSpriteCache(m_romfile.ImageURL, (img, url) => + { + if (!m_romfile.InfoReady || url != m_romfile.ImageURL) return; + + m_romImage.sprite = img; + if (m_select) LaunchUI.Instance.SetRomPreview(img); + }); + Star.SetActiveEx(m_romfile.Star); + } + } + + public override bool OnEnterItem() + { + if (!m_romfile.RomReady) + { + m_romfile.BeginDownload(); + return false; + } + else + { + App.emu.BeginGame(m_romfile); + + return false; + } + } + + + protected override void Update() + { + DownloadingFlag.SetActiveEx(false); + FileReadyFlag.SetActiveEx(false); + Star.SetActiveEx(IsStar); + + if (m_romfile == null) return; + if (!m_romfile.InfoReady) return; + + if (m_romfile.IsDownloading) + { + DownloadingFlag.SetActiveEx(true); + DownProgress.value = m_romfile.Progress; + } + else if (m_romfile.RomReady) + { + FileReadyFlag.SetActiveEx(true); + } + + base.Update(); + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/GamesUI/RomListMenuItem.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/GamesUI/RomListMenuItem.cs index eba1f4a7..e99df596 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/GamesUI/RomListMenuItem.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/GamesUI/RomListMenuItem.cs @@ -1,109 +1,109 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugProtobuf; -using System.Collections.Generic; -using UnityEngine; - -namespace AxibugEmuOnline.Client -{ - public class RomListMenuItem : VirtualSubMenuItem - { - [SerializeField] - protected bool StarRom; - [SerializeField] - protected RomPlatformType Platform; - - private RomLib RomLib - { - get - { - if (StarRom) return App.starRomLib; - else return App.GetRomLib(Platform); - } - } - - private List m_options; - - protected override void Awake() - { - base.Awake(); - - m_options = new List() - { - new OptMenu_Search(this), - new OptMenu_ShowAll(this), - new OptMenu_Fav(this), - }; - } - - public string SearchKey; - protected override void GetVirtualListDatas(VirtualListDataHandle callback) - { - RomLib.FetchRomCount((roms) => callback.Invoke(roms, 0), SearchKey); - } - - public override bool OnEnterItem() - { - var res = base.OnEnterItem(); - if (res) CommandDispatcher.Instance.RegistController(this); - - return true; - } - - public override bool OnExitItem() - { - var res = base.OnExitItem(); - if (res) CommandDispatcher.Instance.UnRegistController(this); - - return false; - } - - - protected override void OnCmdOptionMenu() +using AxibugEmuOnline.Client.ClientCore; +using AxibugProtobuf; +using System.Collections.Generic; +using UnityEngine; + +namespace AxibugEmuOnline.Client +{ + public class RomListMenuItem : VirtualSubMenuItem + { + [SerializeField] + protected bool StarRom; + [SerializeField] + protected RomPlatformType Platform; + + private RomLib RomLib { - OverlayManager.PopSideBar(m_options); - } - - public class OptMenu_Search : ExecuteMenu - { - private RomListMenuItem m_romListUI; - public override string Name => "搜索"; - + get + { + if (StarRom) return App.starRomLib; + else return App.GetRomLib(Platform); + } + } + + private List m_options; + + protected override void Awake() + { + base.Awake(); + + m_options = new List() + { + new OptMenu_Search(this), + new OptMenu_ShowAll(this), + new OptMenu_Fav(this), + }; + } + + public string SearchKey; + protected override void GetVirtualListDatas(VirtualListDataHandle callback) + { + RomLib.FetchRomCount((roms) => callback.Invoke(roms, 0), SearchKey); + } + + public override bool OnEnterItem() + { + var res = base.OnEnterItem(); + if (res) CommandDispatcher.Instance.RegistController(this); + + return true; + } + + public override bool OnExitItem() + { + var res = base.OnExitItem(); + if (res) CommandDispatcher.Instance.UnRegistController(this); + + return false; + } + + + protected override void OnCmdOptionMenu() + { + OverlayManager.PopSideBar(m_options); + } + + public class OptMenu_Search : ExecuteMenu + { + private RomListMenuItem m_romListUI; + public override string Name => "搜索"; + public OptMenu_Search(RomListMenuItem romListUI) - { - m_romListUI = romListUI; - } - - public override void OnExcute(OptionUI optionUI, ref bool cancelHide) - { - OverlayManager.Input(OnSearchCommit, "输入Rom名称", m_romListUI.SearchKey); - } - - private void OnSearchCommit(string text) - { - m_romListUI.SearchKey = text; - m_romListUI.RefreshUI(); - } - } - - public class OptMenu_ShowAll : ExecuteMenu - { - private RomListMenuItem m_ui; - - public override string Name => "显示全部"; - public override bool Visible => !string.IsNullOrWhiteSpace(m_ui.SearchKey); - - public OptMenu_ShowAll(RomListMenuItem romListUI) - { - m_ui = romListUI; - } - - public override void OnExcute(OptionUI optionUI, ref bool cancelHide) - { - m_ui.SearchKey = null; - m_ui.RefreshUI(); - } - } - + { + m_romListUI = romListUI; + } + + public override void OnExcute(OptionUI optionUI, ref bool cancelHide) + { + OverlayManager.Input(OnSearchCommit, "输入Rom名称", m_romListUI.SearchKey); + } + + private void OnSearchCommit(string text) + { + m_romListUI.SearchKey = text; + m_romListUI.RefreshUI(); + } + } + + public class OptMenu_ShowAll : ExecuteMenu + { + private RomListMenuItem m_ui; + + public override string Name => "显示全部"; + public override bool Visible => !string.IsNullOrWhiteSpace(m_ui.SearchKey); + + public OptMenu_ShowAll(RomListMenuItem romListUI) + { + m_ui = romListUI; + } + + public override void OnExcute(OptionUI optionUI, ref bool cancelHide) + { + m_ui.SearchKey = null; + m_ui.RefreshUI(); + } + } + public class OptMenu_Fav : ExecuteMenu { private RomListMenuItem m_romListUI; @@ -129,6 +129,6 @@ namespace AxibugEmuOnline.Client else App.share.SendGameStar(romItem.RomID, 0); } - } - } -} + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI.cs index 3ed9dd31..97c00934 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI.cs @@ -1,45 +1,45 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugEmuOnline.Client.Event; -using AxibugEmuOnline.Client.Network; -using AxibugProtobuf; -using System; -using System.Collections.Generic; - -namespace AxibugEmuOnline.Client -{ - public class InGameUI : CommandExecuter - { - private bool m_delayCreateRoom; - private object m_state; - private StepPerformer m_stepPerformer; - - private readonly List menus = new List(); - public static InGameUI Instance { get; private set; } - - public RomFile RomFile { get; private set; } - - public override bool Enable => gameObject.activeInHierarchy; - - public EmuCore Core { get; private set; } - - protected override void Awake() - { - Instance = this; - gameObject.SetActiveEx(false); - - m_stepPerformer = new StepPerformer(this); - - menus.Add(new InGameUI_FilterSetting(this)); - menus.Add(new InGameUI_Scaler(this)); - menus.Add(new InGameUI_Reset(this)); - menus.Add(new InGameUI_SaveStateQuick(this)); - menus.Add(new InGameUI_LoadStateQuick(this)); - menus.Add(new InGameUI_SaveStateMenu(this)); - menus.Add(new InGameUI_QuitGame(this)); - - base.Awake(); - } - +using AxibugEmuOnline.Client.ClientCore; +using AxibugEmuOnline.Client.Event; +using AxibugEmuOnline.Client.Network; +using AxibugProtobuf; +using System; +using System.Collections.Generic; + +namespace AxibugEmuOnline.Client +{ + public class InGameUI : CommandExecuter + { + private bool m_delayCreateRoom; + private object m_state; + private StepPerformer m_stepPerformer; + + private readonly List menus = new List(); + public static InGameUI Instance { get; private set; } + + public RomFile RomFile { get; private set; } + + public override bool Enable => gameObject.activeInHierarchy; + + public EmuCore Core { get; private set; } + + protected override void Awake() + { + Instance = this; + gameObject.SetActiveEx(false); + + m_stepPerformer = new StepPerformer(this); + + menus.Add(new InGameUI_FilterSetting(this)); + menus.Add(new InGameUI_Scaler(this)); + menus.Add(new InGameUI_Reset(this)); + menus.Add(new InGameUI_SaveStateQuick(this)); + menus.Add(new InGameUI_LoadStateQuick(this)); + menus.Add(new InGameUI_SaveStateMenu(this)); + menus.Add(new InGameUI_QuitGame(this)); + + base.Awake(); + } + protected override void Update() { base.Update(); @@ -48,8 +48,8 @@ namespace AxibugEmuOnline.Client App.settings.Filter.ExecuteFilterRender(Core.OutputPixel, Core.DrawCanvas); App.settings.ScreenScaler.CalcScale(Core.DrawCanvas, Core.Platform); - } - + } + void PushCoreFrame() { if (Core == null) return; @@ -57,70 +57,70 @@ namespace AxibugEmuOnline.Client NetMsg.Instance.DequeueNesMsg(); Core.PushEmulatorFrame(); - } - - protected override void OnDestroy() - { - Instance = null; - base.OnDestroy(); - } - - /// 保存快速快照 - public void SaveQuickState(object state) - { - m_state = state; - } - - /// - /// 读取快速快照 - /// - public object GetQuickState() - { - return m_state; - } - - public void Show(RomFile currentRom, EmuCore core) - { - m_delayCreateRoom = false; - m_state = null; //清空游戏快照 - CommandDispatcher.Instance.RegistController(this); - - RomFile = currentRom; - Core = core; - m_stepPerformer.Reset(); - - if (!App.roomMgr.InRoom) - { - if (App.user.IsLoggedIn) - { - App.roomMgr.SendCreateRoom(RomFile.ID, RomFile.Hash); - } - else - { - m_delayCreateRoom = true; - OverlayManager.PopTip("稍后将会建立房间"); - } - } - - Eventer.Instance.RegisterEvent(EEvent.OnLoginSucceed, OnLoggedIn); - Eventer.Instance.RegisterEvent(EEvent.OnRoomWaitStepChange, OnServerStepUpdate); - Eventer.Instance.RegisterEvent(EEvent.OnMineRoomCreated, OnRoomCreated); - - gameObject.SetActiveEx(true); - - var filterSetting = App.settings.Filter.GetFilterSetting(currentRom); - if (filterSetting.filter != null) - { - var filter = filterSetting.filter; - var preset = filterSetting.preset ?? filter.DefaultPreset; - - filter.ApplyPreset(preset); - App.settings.Filter.EnableFilter(filter); - } - } - - private void OnRoomCreated() - { + } + + protected override void OnDestroy() + { + Instance = null; + base.OnDestroy(); + } + + /// 保存快速快照 + public void SaveQuickState(object state) + { + m_state = state; + } + + /// + /// 读取快速快照 + /// + public object GetQuickState() + { + return m_state; + } + + public void Show(RomFile currentRom, EmuCore core) + { + m_delayCreateRoom = false; + m_state = null; //清空游戏快照 + CommandDispatcher.Instance.RegistController(this); + + RomFile = currentRom; + Core = core; + m_stepPerformer.Reset(); + + if (!App.roomMgr.InRoom) + { + if (App.user.IsLoggedIn) + { + App.roomMgr.SendCreateRoom(RomFile.ID, RomFile.Hash); + } + else + { + m_delayCreateRoom = true; + OverlayManager.PopTip("稍后将会建立房间"); + } + } + + Eventer.Instance.RegisterEvent(EEvent.OnLoginSucceed, OnLoggedIn); + Eventer.Instance.RegisterEvent(EEvent.OnRoomWaitStepChange, OnServerStepUpdate); + Eventer.Instance.RegisterEvent(EEvent.OnMineRoomCreated, OnRoomCreated); + + gameObject.SetActiveEx(true); + + var filterSetting = App.settings.Filter.GetFilterSetting(currentRom); + if (filterSetting.filter != null) + { + var filter = filterSetting.filter; + var preset = filterSetting.preset ?? filter.DefaultPreset; + + filter.ApplyPreset(preset); + App.settings.Filter.EnableFilter(filter); + } + } + + private void OnRoomCreated() + { if (m_delayCreateRoom) { m_delayCreateRoom = false; @@ -138,48 +138,48 @@ namespace AxibugEmuOnline.Client } App.roomMgr.SendChangePlaySlotIdxWithJoyIdx(temp); } - } - - private void OnLoggedIn() - { - if (m_delayCreateRoom) App.roomMgr.SendCreateRoom(RomFile.ID, RomFile.Hash); - } - - private void OnServerStepUpdate(int step) - { - m_stepPerformer.Perform(step); - } - - public void Hide() - { - CommandDispatcher.Instance.UnRegistController(this); - gameObject.SetActiveEx(false); - - App.settings.Filter.ShutDownFilter(); - } - - protected override void OnCmdOptionMenu() - { - OverlayManager.PopSideBar(menus, 0, PopMenu_OnHide); - - if (!Core.IsNetPlay) //单人模式暂停模拟器 - Core.Pause(); - } - - //菜单关闭时候 - private void PopMenu_OnHide() - { - if (!Core.IsNetPlay) //单人模式恢复模拟器的暂停 - Core.Resume(); - } - - public void QuitGame() - { - Eventer.Instance.UnregisterEvent(EEvent.OnRoomWaitStepChange, OnServerStepUpdate); - Eventer.Instance.UnregisterEvent(EEvent.OnLoginSucceed, OnLoggedIn); - Eventer.Instance.UnregisterEvent(EEvent.OnMineRoomCreated, OnRoomCreated); - App.roomMgr.SendLeavnRoom(); - App.emu.StopGame(); - } - } + } + + private void OnLoggedIn() + { + if (m_delayCreateRoom) App.roomMgr.SendCreateRoom(RomFile.ID, RomFile.Hash); + } + + private void OnServerStepUpdate(int step) + { + m_stepPerformer.Perform(step); + } + + public void Hide() + { + CommandDispatcher.Instance.UnRegistController(this); + gameObject.SetActiveEx(false); + + App.settings.Filter.ShutDownFilter(); + } + + protected override void OnCmdOptionMenu() + { + OverlayManager.PopSideBar(menus, 0, PopMenu_OnHide); + + if (!Core.IsNetPlay) //单人模式暂停模拟器 + Core.Pause(); + } + + //菜单关闭时候 + private void PopMenu_OnHide() + { + if (!Core.IsNetPlay) //单人模式恢复模拟器的暂停 + Core.Resume(); + } + + public void QuitGame() + { + Eventer.Instance.UnregisterEvent(EEvent.OnRoomWaitStepChange, OnServerStepUpdate); + Eventer.Instance.UnregisterEvent(EEvent.OnLoginSucceed, OnLoggedIn); + Eventer.Instance.UnregisterEvent(EEvent.OnMineRoomCreated, OnRoomCreated); + App.roomMgr.SendLeavnRoom(); + App.emu.StopGame(); + } + } } \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_FilterSetting.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_FilterSetting.cs index 402032e9..aee40aeb 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_FilterSetting.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_FilterSetting.cs @@ -1,28 +1,28 @@ -using AxibugEmuOnline.Client.ClientCore; -using System.Collections.Generic; -using System.Linq; -using static AxibugEmuOnline.Client.Settings.FilterManager; - -namespace AxibugEmuOnline.Client +using AxibugEmuOnline.Client.ClientCore; +using System.Collections.Generic; +using System.Linq; +using static AxibugEmuOnline.Client.Settings.FilterManager; + +namespace AxibugEmuOnline.Client { - public class InGameUI_FilterSetting : ExpandMenu - { - private InGameUI m_gameUI; - public override string Name => "滤镜"; - + public class InGameUI_FilterSetting : ExpandMenu + { + private InGameUI m_gameUI; + public override string Name => "滤镜"; + public InGameUI_FilterSetting(InGameUI gameUI) - { - m_gameUI = gameUI; - } - - protected override List GetOptionMenus() - { - List menus = new List(); - menus.Add(new FilterNone(m_gameUI.RomFile)); - menus.AddRange(App.settings.Filter.Filters.Select(f => new FilterMenu(m_gameUI.RomFile, f) as InternalOptionMenu)); - return menus; - } - + { + m_gameUI = gameUI; + } + + protected override List GetOptionMenus() + { + List menus = new List(); + menus.Add(new FilterNone(m_gameUI.RomFile)); + menus.AddRange(App.settings.Filter.Filters.Select(f => new FilterMenu(m_gameUI.RomFile, f) as InternalOptionMenu)); + return menus; + } + public class FilterNone : ExecuteMenu { private RomFile m_rom; @@ -36,16 +36,16 @@ namespace AxibugEmuOnline.Client public override void OnExcute(OptionUI optionUI, ref bool cancelHide) { - App.settings.Filter.ShutDownFilter(); + App.settings.Filter.ShutDownFilter(); App.settings.Filter.SetupFilter(m_rom, null, null); } - } - - public class FilterMenu : ExpandMenu - { - private Filter m_filter; - private List m_presetsMenuItems; - + } + + public class FilterMenu : ExpandMenu + { + private Filter m_filter; + private List m_presetsMenuItems; + public override bool IsApplied { get @@ -57,27 +57,27 @@ namespace AxibugEmuOnline.Client return false; } - } - public override string Name => m_filter.Name; - public FilterMenu(RomFile rom, Filter filter) - { - m_filter = filter; - m_presetsMenuItems = new List { new FilterPresetMenu(rom, m_filter, m_filter.DefaultPreset) }; - m_presetsMenuItems.AddRange(m_filter.Presets.Select(preset => new FilterPresetMenu(rom, m_filter, preset))); - } - - protected override List GetOptionMenus() - { - return m_presetsMenuItems; - } - } - - public class FilterPresetMenu : ExecuteMenu - { - private FilterPreset m_preset; - private RomFile m_rom; - private Filter m_filter; - + } + public override string Name => m_filter.Name; + public FilterMenu(RomFile rom, Filter filter) + { + m_filter = filter; + m_presetsMenuItems = new List { new FilterPresetMenu(rom, m_filter, m_filter.DefaultPreset) }; + m_presetsMenuItems.AddRange(m_filter.Presets.Select(preset => new FilterPresetMenu(rom, m_filter, preset))); + } + + protected override List GetOptionMenus() + { + return m_presetsMenuItems; + } + } + + public class FilterPresetMenu : ExecuteMenu + { + private FilterPreset m_preset; + private RomFile m_rom; + private Filter m_filter; + public override bool IsApplied { get @@ -89,19 +89,19 @@ namespace AxibugEmuOnline.Client public override string Name => m_preset.Name; public FilterPresetMenu(RomFile rom, Filter filter, FilterPreset preset) - { - m_preset = preset; - m_rom = rom; - m_filter = filter; - } - - public override void OnExcute(OptionUI optionUI, ref bool cancelHide) - { - m_filter.ApplyPreset(m_preset); - App.settings.Filter.EnableFilter(m_filter); - - App.settings.Filter.SetupFilter(m_rom, m_filter, m_preset); - } - } - } -} + { + m_preset = preset; + m_rom = rom; + m_filter = filter; + } + + public override void OnExcute(OptionUI optionUI, ref bool cancelHide) + { + m_filter.ApplyPreset(m_preset); + App.settings.Filter.EnableFilter(m_filter); + + App.settings.Filter.SetupFilter(m_rom, m_filter, m_preset); + } + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_LoadStateQuick.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_LoadStateQuick.cs index 0fa39a39..21d4d221 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_LoadStateQuick.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_LoadStateQuick.cs @@ -1,25 +1,25 @@ -namespace AxibugEmuOnline.Client -{ - public class InGameUI_LoadStateQuick : ExecuteMenu - { - private InGameUI m_gameUI; - public override bool Visible => !m_gameUI.Core.IsNetPlay && m_gameUI.GetQuickState() != null; - public override string Name => "快速读取"; - +namespace AxibugEmuOnline.Client +{ + public class InGameUI_LoadStateQuick : ExecuteMenu + { + private InGameUI m_gameUI; + public override bool Visible => !m_gameUI.Core.IsNetPlay && m_gameUI.GetQuickState() != null; + public override string Name => "快速读取"; + public InGameUI_LoadStateQuick(InGameUI gameUI) - { - m_gameUI = gameUI; - } - - public override void OnExcute(OptionUI optionUI, ref bool cancelHide) - { - if (m_gameUI.Core.IsNetPlay) return; - - object state = m_gameUI.GetQuickState(); - if (state != null) - { - m_gameUI.Core.LoadState(state); - } - } - } -} + { + m_gameUI = gameUI; + } + + public override void OnExcute(OptionUI optionUI, ref bool cancelHide) + { + if (m_gameUI.Core.IsNetPlay) return; + + object state = m_gameUI.GetQuickState(); + if (state != null) + { + m_gameUI.Core.LoadState(state); + } + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_Reset.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_Reset.cs index 32db8a89..ea866e73 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_Reset.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_Reset.cs @@ -1,25 +1,25 @@ -using AxibugEmuOnline.Client.ClientCore; - -namespace AxibugEmuOnline.Client -{ - public class InGameUI_Reset : ExecuteMenu - { - private InGameUI m_gameUI; - public override string Name => "复位"; - public override bool Visible => !m_gameUI.Core.IsNetPlay || App.roomMgr.IsHost; - +using AxibugEmuOnline.Client.ClientCore; + +namespace AxibugEmuOnline.Client +{ + public class InGameUI_Reset : ExecuteMenu + { + private InGameUI m_gameUI; + public override string Name => "复位"; + public override bool Visible => !m_gameUI.Core.IsNetPlay || App.roomMgr.IsHost; + public InGameUI_Reset(InGameUI gameUI) - { - m_gameUI = gameUI; - } - - public override void OnExcute(OptionUI optionUI, ref bool cancelHide) - { - if (!m_gameUI.Core.IsNetPlay) - { - App.emu.ResetGame(); - } - - } - } -} + { + m_gameUI = gameUI; + } + + public override void OnExcute(OptionUI optionUI, ref bool cancelHide) + { + if (!m_gameUI.Core.IsNetPlay) + { + App.emu.ResetGame(); + } + + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_SaveStateMenu.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_SaveStateMenu.cs index b98ed527..eff8c86a 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_SaveStateMenu.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_SaveStateMenu.cs @@ -92,16 +92,18 @@ namespace AxibugEmuOnline.Client public override void OnExcute(OptionUI optionUI, ref bool cancelHide) { - if (m_savFile.IsBusy) //取消同步进程 + if (m_savFile.IsBusy) { - m_savFile.FSM.ChangeState(); + OverlayManager.PopTip("存档正在同步中"); + cancelHide = true; + return; } var stateData = m_ingameUI.Core.GetStateBytes(); var tex = m_ingameUI.Core.OutputPixel; var screenData = tex.ToJPG(m_ingameUI.Core.DrawCanvas.transform.localScale); - m_savFile.Save(m_savFile.Sequecen + 1, stateData, screenData); + m_savFile.Save(m_savFile.Sequecen, stateData, screenData); } } @@ -165,6 +167,7 @@ namespace AxibugEmuOnline.Client public override void OnExcute(OptionUI optionUI, ref bool cancelHide) { if (m_savFile.GetCurrentState() is not SaveFile.ConflictState) return; + cancelHide = true; m_savFile.FSM.ChangeState(); } } @@ -184,6 +187,7 @@ namespace AxibugEmuOnline.Client public override void OnExcute(OptionUI optionUI, ref bool cancelHide) { if (m_savFile.GetCurrentState() is not SaveFile.ConflictState) return; + cancelHide = true; m_savFile.FSM.ChangeState(); } } diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/ItemPresent/GameObjectPool.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/ItemPresent/GameObjectPool.cs index 0d7e4cb2..1df27227 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/ItemPresent/GameObjectPool.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/ItemPresent/GameObjectPool.cs @@ -1,59 +1,59 @@ -using System.Collections.Generic; -using UnityEngine; - -public static class GameObjectPool -{ - private static GameObject PoolAttach; - private static Dictionary> s_poolMap = new Dictionary>(); - private static Dictionary s_instanceToSrc = new Dictionary(); - public static GameObject GetInstance(GameObject prefabSrc, Transform parent) - { - if (PoolAttach == null) - { - PoolAttach = new GameObject("[GameObjectPool]"); - PoolAttach.transform.localScale = Vector3.zero; - GameObject.DontDestroyOnLoad(PoolAttach); - } - - if (!s_poolMap.ContainsKey(prefabSrc)) s_poolMap[prefabSrc] = new Queue(); - - GameObject instance = null; - var pool = s_poolMap[prefabSrc]; - if (pool.Count > 0) - { - instance = pool.Dequeue(); - instance.transform.SetParent(parent, true); - instance.transform.localScale = prefabSrc.transform.localScale; - instance.transform.localRotation = prefabSrc.transform.localRotation; - instance.transform.localPosition = prefabSrc.transform.localPosition; - } - else - { - instance = GameObject.Instantiate(prefabSrc, parent); - s_instanceToSrc[instance] = prefabSrc; - } - - //instance.SetActive(true); - return instance; - } - - public static void Release(GameObject instance) - { - GameObject src; +using System.Collections.Generic; +using UnityEngine; + +public static class GameObjectPool +{ + private static GameObject PoolAttach; + private static Dictionary> s_poolMap = new Dictionary>(); + private static Dictionary s_instanceToSrc = new Dictionary(); + public static GameObject GetInstance(GameObject prefabSrc, Transform parent) + { + if (PoolAttach == null) + { + PoolAttach = new GameObject("[GameObjectPool]"); + PoolAttach.transform.localScale = Vector3.zero; + GameObject.DontDestroyOnLoad(PoolAttach); + } + + if (!s_poolMap.ContainsKey(prefabSrc)) s_poolMap[prefabSrc] = new Queue(); + + GameObject instance = null; + var pool = s_poolMap[prefabSrc]; + if (pool.Count > 0) + { + instance = pool.Dequeue(); + instance.transform.SetParent(parent, true); + instance.transform.localScale = prefabSrc.transform.localScale; + instance.transform.localRotation = prefabSrc.transform.localRotation; + instance.transform.localPosition = prefabSrc.transform.localPosition; + } + else + { + instance = GameObject.Instantiate(prefabSrc, parent); + s_instanceToSrc[instance] = prefabSrc; + } + + //instance.SetActive(true); + return instance; + } + + public static void Release(GameObject instance) + { + GameObject src; Queue pool; - s_instanceToSrc.TryGetValue(instance, out src); - if (src != null && s_poolMap.TryGetValue(src, out pool)) - { - pool.Enqueue(instance); - //instance.SetActive(false); - if (instance == null) return; - if (PoolAttach == null) return; - - instance.transform.SetParent(PoolAttach.transform, true); - } - else - { - GameObject.Destroy(instance); - } - } -} + s_instanceToSrc.TryGetValue(instance, out src); + if (src != null && s_poolMap.TryGetValue(src, out pool)) + { + pool.Enqueue(instance); + //instance.SetActive(false); + if (instance == null) return; + if (PoolAttach == null) return; + + instance.transform.SetParent(PoolAttach.transform, true); + } + else + { + GameObject.Destroy(instance); + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/ItemPresent/ItemPresent.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/ItemPresent/ItemPresent.cs index 87febc95..a43542fe 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/ItemPresent/ItemPresent.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/ItemPresent/ItemPresent.cs @@ -1,555 +1,555 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.UI; - -public class ItemPresent : GridLayoutGroup, IVirtualLayout -{ - public RectTransform ItemTemplate; - public RectTransform ViewRect; - - private Dictionary _cacheItemScripts = new Dictionary(); - private List _dataList; - private object _dependencyProperty; - private Vector2 _layoutCellsize; - - public Action OnItemDelayShowPorcessComplete; - - -#if UNITY_EDITOR - public int EditorOnlyItemCount - { - get => ItemCount; - set => ItemCount = value; - } -#endif - - private int ItemCount - { - get => children.Count; - set - { - if (value == ItemCount) return; - - if (value <= 0) - { - foreach (var child in children) - { - child.Dispose(); - } - - children.Clear(); - } - else - { - var gap = value - children.Count; - - if (gap > 0) - { - for (int i = 0; i < gap; i++) - { - ItemProxy item = new ItemProxy(this); - children.Add(item); - item.Width = cellSize.x; - item.Height = cellSize.y; - item.Index = children.Count - 1; - } - } - else if (gap < 0) - { - for (int i = 0; i < -gap; i++) - { - int removeIndex = children.Count - 1; - children[removeIndex].Dispose(); - children.RemoveAt(removeIndex); - } - } - } - - SetDirty(); - } - } - private List children = new List(); - - private List handleChildren = new List(); - private bool m_dataDirty; - private ItemSelector m_itemSelector; - protected override void Awake() - { - m_itemSelector = gameObject.GetComponent(); - } - - public override void CalculateLayoutInputHorizontal() - { - handleChildren.Clear(); - for (int i = 0; i < children.Count; i++) - { - var child = children[i]; - if (child.IsDestroyed || !child.Visible) - continue; - - handleChildren.Add(child); - } - m_Tracker.Clear(); - updateFixHeightAndWidth(); - - int minColumns = 0; - int preferredColumns = 0; - if (m_Constraint == Constraint.FixedColumnCount) - { - minColumns = preferredColumns = m_ConstraintCount; - } - else if (m_Constraint == Constraint.FixedRowCount) - { - minColumns = preferredColumns = Mathf.CeilToInt(handleChildren.Count / (float)m_ConstraintCount - 0.001f); - } - else - { - minColumns = 1; - preferredColumns = Mathf.CeilToInt(Mathf.Sqrt(handleChildren.Count)); - } - - SetLayoutInputForAxis( - padding.horizontal + (_layoutCellsize.x + spacing.x) * minColumns - spacing.x, - padding.horizontal + (_layoutCellsize.x + spacing.x) * preferredColumns - spacing.x, - -1, 0); - } - - public void MoveToScrollViewCenter(ScrollRect scrollRect, int dataIndex) - { - if (m_dataDirty) - { - for (int i = 0; i < children.Count; i++) - { - var child = children[i]; - child.UpdateLayout(); - } - Canvas.ForceUpdateCanvases(); - } - - var targetProxy = children[dataIndex]; - var width = rectTransform.rect.width; - var height = rectTransform.rect.height; - - // Item is here - var itemCenterPositionInScroll = GetWorldPointInWidget(scrollRect.transform as RectTransform, GetWidgetWorldPoint(targetProxy)); - //Debug.Log("Item Anchor Pos In Scroll: " + itemCenterPositionInScroll); - // But must be here - var targetPositionInScroll = GetWorldPointInWidget(scrollRect.transform as RectTransform, GetWidgetWorldPoint(scrollRect.viewport)); - //Debug.Log("Target Anchor Pos In Scroll: " + targetPositionInScroll); - // So it has to move this distance - var difference = targetPositionInScroll - itemCenterPositionInScroll; - difference.z = 0f; - - var newNormalizedPosition = new Vector2(difference.x / (rectTransform.rect.width - scrollRect.viewport.rect.width), - difference.y / (rectTransform.rect.height - scrollRect.viewport.rect.height)); - - newNormalizedPosition = scrollRect.normalizedPosition - newNormalizedPosition; - - newNormalizedPosition.x = Mathf.Clamp01(newNormalizedPosition.x); - newNormalizedPosition.y = Mathf.Clamp01(newNormalizedPosition.y); - - scrollRect.normalizedPosition = newNormalizedPosition; - //DOTween.To(() => scrollRect.normalizedPosition, x => scrollRect.normalizedPosition = x, newNormalizedPosition, 0.2f); - } - - Vector3 GetWidgetWorldPoint(RectTransform target) - { - //pivot position + item size has to be included - var pivotOffset = new Vector3( - (0.5f - target.pivot.x) * target.rect.size.x, - (0.5f - target.pivot.y) * target.rect.size.y, - 0f); - var localPosition = target.localPosition + pivotOffset; - return target.parent.TransformPoint(localPosition); - } - - Vector3 GetWidgetWorldPoint(ItemProxy proxy) - { - Vector3[] temp = new Vector3[4]; - rectTransform.GetLocalCorners(temp); - var pos = (Vector2)temp[1] + proxy.AnchoredPosition; - pos = rectTransform.TransformPoint(pos); - - return pos; - } - - Vector3 GetWorldPointInWidget(RectTransform target, Vector3 worldPoint) - { - return target.InverseTransformPoint(worldPoint); - } - - public override void CalculateLayoutInputVertical() - { - int minRows = 0; - if (m_Constraint == Constraint.FixedColumnCount) - { - minRows = Mathf.CeilToInt(handleChildren.Count / (float)m_ConstraintCount - 0.001f); - } - else if (m_Constraint == Constraint.FixedRowCount) - { - minRows = m_ConstraintCount; - } - else - { - float width = rectTransform.rect.width; - int cellCountX = Mathf.Max(1, Mathf.FloorToInt((width - padding.horizontal + spacing.x + 0.001f) / (_layoutCellsize.x + spacing.x))); - minRows = Mathf.CeilToInt(handleChildren.Count / (float)cellCountX); - } - - float minSpace = padding.vertical + (_layoutCellsize.y + spacing.y) * minRows - spacing.y; - SetLayoutInputForAxis(minSpace, minSpace, -1, 1); - } - - public override void SetLayoutHorizontal() - { - SetProxyCellsAlongAxis(0); - } - - public override void SetLayoutVertical() - { - SetProxyCellsAlongAxis(1); - - foreach (var item in handleChildren) - { - item.UpdateLayout(); - } - } - - - - private void SetProxyCellsAlongAxis(int axis) - { - // Normally a Layout Controller should only set horizontal values when invoked for the horizontal axis - // and only vertical values when invoked for the vertical axis. - // However, in this case we set both the horizontal and vertical position when invoked for the vertical axis. - // Since we only set the horizontal position and not the size, it shouldn't affect children's layout, - // and thus shouldn't break the rule that all horizontal layout must be calculated before all vertical layout. - var proxyChildCount = handleChildren.Count; - if (axis == 0) - { - // Only set the sizes when invoked for horizontal axis, not the positions. - - for (int i = 0; i < proxyChildCount; i++) - { - ItemProxy proxy = handleChildren[i]; - - proxy.Width = _layoutCellsize.x; - proxy.Height = _layoutCellsize.y; - } - return; - } - - float width = rectTransform.rect.size.x; - float height = rectTransform.rect.size.y; - - int cellCountX = 1; - int cellCountY = 1; - if (m_Constraint == Constraint.FixedColumnCount) - { - cellCountX = m_ConstraintCount; - - if (proxyChildCount > cellCountX) - cellCountY = proxyChildCount / cellCountX + (proxyChildCount % cellCountX > 0 ? 1 : 0); - } - else if (m_Constraint == Constraint.FixedRowCount) - { - cellCountY = m_ConstraintCount; - - if (proxyChildCount > cellCountY) - cellCountX = proxyChildCount / cellCountY + (proxyChildCount % cellCountY > 0 ? 1 : 0); - } - else - { - if (_layoutCellsize.x + spacing.x <= 0) - cellCountX = int.MaxValue; - else - cellCountX = Mathf.Max(1, Mathf.FloorToInt((width - padding.horizontal + spacing.x + 0.001f) / (cellSize.x + spacing.x))); - - if (_layoutCellsize.y + spacing.y <= 0) - cellCountY = int.MaxValue; - else - cellCountY = Mathf.Max(1, Mathf.FloorToInt((height - padding.vertical + spacing.y + 0.001f) / (cellSize.y + spacing.y))); - } - - int cornerX = (int)startCorner % 2; - int cornerY = (int)startCorner / 2; - - int cellsPerMainAxis, actualCellCountX, actualCellCountY; - if (startAxis == Axis.Horizontal) - { - cellsPerMainAxis = cellCountX; - actualCellCountX = Mathf.Clamp(cellCountX, 1, proxyChildCount); - actualCellCountY = Mathf.Clamp(cellCountY, 1, Mathf.CeilToInt(proxyChildCount / (float)cellsPerMainAxis)); - } - else - { - cellsPerMainAxis = cellCountY; - actualCellCountY = Mathf.Clamp(cellCountY, 1, proxyChildCount); - actualCellCountX = Mathf.Clamp(cellCountX, 1, Mathf.CeilToInt(proxyChildCount / (float)cellsPerMainAxis)); - } - - Vector2 requiredSpace = new Vector2( - actualCellCountX * _layoutCellsize.x + (actualCellCountX - 1) * spacing.x, - actualCellCountY * _layoutCellsize.y + (actualCellCountY - 1) * spacing.y - ); - Vector2 startOffset = new Vector2( - GetStartOffset(0, requiredSpace.x), - GetStartOffset(1, requiredSpace.y) - ); - - for (int i = 0; i < proxyChildCount; i++) - { - int positionX; - int positionY; - if (startAxis == Axis.Horizontal) - { - positionX = i % cellsPerMainAxis; - positionY = i / cellsPerMainAxis; - } - else - { - positionX = i / cellsPerMainAxis; - positionY = i % cellsPerMainAxis; - } - - if (cornerX == 1) - positionX = actualCellCountX - 1 - positionX; - if (cornerY == 1) - positionY = actualCellCountY - 1 - positionY; - - SetProxyChildAlongAxis(handleChildren[i], 0, startOffset.x + (_layoutCellsize[0] + spacing[0]) * positionX, _layoutCellsize[0]); - SetProxyChildAlongAxis(handleChildren[i], 1, startOffset.y + (_layoutCellsize[1] + spacing[1]) * positionY, _layoutCellsize[1]); - } - } - - private void SetProxyChildAlongAxis(ItemProxy proxy, int axis, float pos, float size) - { - var scaleFactor = 1.0f; - - if (proxy == null) - return; - - Vector2 sizeDelta = new Vector2(proxy.Width, proxy.Height); - sizeDelta[axis] = size; - proxy.Width = sizeDelta.x; - proxy.Height = sizeDelta.y; - - Vector2 anchoredPosition = proxy.AnchoredPosition; - anchoredPosition[axis] = (axis == 0) ? (pos + size * proxy.Pivot[axis] * scaleFactor) : (-pos - size * (1f - proxy.Pivot[axis]) * scaleFactor); - proxy.AnchoredPosition = anchoredPosition; - } - - public void UpdateProxyVisualState() - { - if (m_dataDirty) - { - foreach (var proxy in children) - { - proxy.UpdateView(true); - } - Canvas.ForceUpdateCanvases(); - - m_dataDirty = false; - } - - if (ViewRect == null) - { - foreach (var proxy in children) - { - proxy.IsInViewRect = true; - } - return; - } - - Vector3[] corners = new Vector3[4]; - ViewRect.GetLocalCorners(corners); - Rect parentRect = ViewRect.rect; - parentRect.position = corners[0]; - - rectTransform.GetLocalCorners(corners); - Vector2 leftUpCorner = corners[1]; - - foreach (var proxy in children) - { - var localPos = leftUpCorner + proxy.AnchoredPosition; - localPos.x -= proxy.Width * 0.5f; - localPos.y -= proxy.Height * 0.5f; - localPos = transform.localToWorldMatrix.MultiplyPoint(localPos); - localPos = ViewRect.worldToLocalMatrix.MultiplyPoint(localPos); - - Rect proxyRect = new Rect(localPos, new Vector2(proxy.Width, proxy.Height)); - - if (parentRect.Overlaps(proxyRect)) proxy.IsInViewRect = true; - else proxy.IsInViewRect = false; - } - } - - public bool PauseUpdateView; - private void LateUpdate() - { - if (!PauseUpdateView) - { - updateFixHeightAndWidth(); - - UpdateProxyVisualState(); - HandleProxyShow(); - } - } - - private void updateFixHeightAndWidth() - { - _layoutCellsize = cellSize; - } - - private List NeedDelayShowItems = new List(); - private bool hasNeedShowInLastFrame = false; - private float stepDuration = 0f; - private void HandleProxyShow(bool allLoad = true, float delayStep = 0.02f) - { - if (allLoad) - { - foreach (var proxy in children) - { - if (proxy.NeedHide) - proxy.UpdateView(); - else if (proxy.NeedShow) - proxy.UpdateView(); - } - } - else - { - NeedDelayShowItems.Clear(); - foreach (var proxy in children) - { - if (proxy.NeedHide) - proxy.UpdateView(); - else if (proxy.NeedShow && !proxy.firstShow) - proxy.UpdateView(); - else if (proxy.NeedShow && proxy.firstShow) - { - NeedDelayShowItems.Add(proxy); - } - } - - if (NeedDelayShowItems.Count == 0 && hasNeedShowInLastFrame) - { - // Debug.Log("Show Complete!", gameObject); - OnItemDelayShowPorcessComplete?.Invoke(); - } - hasNeedShowInLastFrame = NeedDelayShowItems.Count > 0; - - stepDuration += Time.deltaTime; - while (stepDuration >= delayStep) - { - foreach (var proxy in NeedDelayShowItems) - { - if (proxy.NeedShow) - { - proxy.UpdateView(); - break; - } - } - stepDuration -= delayStep; - } - } - } - - protected override void OnDestroy() - { - Clear(); - } - - public void Clear() - { - foreach (var proxy in children) - proxy.Dispose(); - - children.Clear(); - } - - - public void SetData(IEnumerable dataList) - { - Clear(); - - if (dataList == null) - { - ItemCount = 0; - if (_dataList != null) - _dataList.Clear(); - } - else if (dataList is IEnumerable) - { +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +public class ItemPresent : GridLayoutGroup, IVirtualLayout +{ + public RectTransform ItemTemplate; + public RectTransform ViewRect; + + private Dictionary _cacheItemScripts = new Dictionary(); + private List _dataList; + private object _dependencyProperty; + private Vector2 _layoutCellsize; + + public Action OnItemDelayShowPorcessComplete; + + +#if UNITY_EDITOR + public int EditorOnlyItemCount + { + get => ItemCount; + set => ItemCount = value; + } +#endif + + private int ItemCount + { + get => children.Count; + set + { + if (value == ItemCount) return; + + if (value <= 0) + { + foreach (var child in children) + { + child.Dispose(); + } + + children.Clear(); + } + else + { + var gap = value - children.Count; + + if (gap > 0) + { + for (int i = 0; i < gap; i++) + { + ItemProxy item = new ItemProxy(this); + children.Add(item); + item.Width = cellSize.x; + item.Height = cellSize.y; + item.Index = children.Count - 1; + } + } + else if (gap < 0) + { + for (int i = 0; i < -gap; i++) + { + int removeIndex = children.Count - 1; + children[removeIndex].Dispose(); + children.RemoveAt(removeIndex); + } + } + } + + SetDirty(); + } + } + private List children = new List(); + + private List handleChildren = new List(); + private bool m_dataDirty; + private ItemSelector m_itemSelector; + protected override void Awake() + { + m_itemSelector = gameObject.GetComponent(); + } + + public override void CalculateLayoutInputHorizontal() + { + handleChildren.Clear(); + for (int i = 0; i < children.Count; i++) + { + var child = children[i]; + if (child.IsDestroyed || !child.Visible) + continue; + + handleChildren.Add(child); + } + m_Tracker.Clear(); + updateFixHeightAndWidth(); + + int minColumns = 0; + int preferredColumns = 0; + if (m_Constraint == Constraint.FixedColumnCount) + { + minColumns = preferredColumns = m_ConstraintCount; + } + else if (m_Constraint == Constraint.FixedRowCount) + { + minColumns = preferredColumns = Mathf.CeilToInt(handleChildren.Count / (float)m_ConstraintCount - 0.001f); + } + else + { + minColumns = 1; + preferredColumns = Mathf.CeilToInt(Mathf.Sqrt(handleChildren.Count)); + } + + SetLayoutInputForAxis( + padding.horizontal + (_layoutCellsize.x + spacing.x) * minColumns - spacing.x, + padding.horizontal + (_layoutCellsize.x + spacing.x) * preferredColumns - spacing.x, + -1, 0); + } + + public void MoveToScrollViewCenter(ScrollRect scrollRect, int dataIndex) + { + if (m_dataDirty) + { + for (int i = 0; i < children.Count; i++) + { + var child = children[i]; + child.UpdateLayout(); + } + Canvas.ForceUpdateCanvases(); + } + + var targetProxy = children[dataIndex]; + var width = rectTransform.rect.width; + var height = rectTransform.rect.height; + + // Item is here + var itemCenterPositionInScroll = GetWorldPointInWidget(scrollRect.transform as RectTransform, GetWidgetWorldPoint(targetProxy)); + //Debug.Log("Item Anchor Pos In Scroll: " + itemCenterPositionInScroll); + // But must be here + var targetPositionInScroll = GetWorldPointInWidget(scrollRect.transform as RectTransform, GetWidgetWorldPoint(scrollRect.viewport)); + //Debug.Log("Target Anchor Pos In Scroll: " + targetPositionInScroll); + // So it has to move this distance + var difference = targetPositionInScroll - itemCenterPositionInScroll; + difference.z = 0f; + + var newNormalizedPosition = new Vector2(difference.x / (rectTransform.rect.width - scrollRect.viewport.rect.width), + difference.y / (rectTransform.rect.height - scrollRect.viewport.rect.height)); + + newNormalizedPosition = scrollRect.normalizedPosition - newNormalizedPosition; + + newNormalizedPosition.x = Mathf.Clamp01(newNormalizedPosition.x); + newNormalizedPosition.y = Mathf.Clamp01(newNormalizedPosition.y); + + scrollRect.normalizedPosition = newNormalizedPosition; + //DOTween.To(() => scrollRect.normalizedPosition, x => scrollRect.normalizedPosition = x, newNormalizedPosition, 0.2f); + } + + Vector3 GetWidgetWorldPoint(RectTransform target) + { + //pivot position + item size has to be included + var pivotOffset = new Vector3( + (0.5f - target.pivot.x) * target.rect.size.x, + (0.5f - target.pivot.y) * target.rect.size.y, + 0f); + var localPosition = target.localPosition + pivotOffset; + return target.parent.TransformPoint(localPosition); + } + + Vector3 GetWidgetWorldPoint(ItemProxy proxy) + { + Vector3[] temp = new Vector3[4]; + rectTransform.GetLocalCorners(temp); + var pos = (Vector2)temp[1] + proxy.AnchoredPosition; + pos = rectTransform.TransformPoint(pos); + + return pos; + } + + Vector3 GetWorldPointInWidget(RectTransform target, Vector3 worldPoint) + { + return target.InverseTransformPoint(worldPoint); + } + + public override void CalculateLayoutInputVertical() + { + int minRows = 0; + if (m_Constraint == Constraint.FixedColumnCount) + { + minRows = Mathf.CeilToInt(handleChildren.Count / (float)m_ConstraintCount - 0.001f); + } + else if (m_Constraint == Constraint.FixedRowCount) + { + minRows = m_ConstraintCount; + } + else + { + float width = rectTransform.rect.width; + int cellCountX = Mathf.Max(1, Mathf.FloorToInt((width - padding.horizontal + spacing.x + 0.001f) / (_layoutCellsize.x + spacing.x))); + minRows = Mathf.CeilToInt(handleChildren.Count / (float)cellCountX); + } + + float minSpace = padding.vertical + (_layoutCellsize.y + spacing.y) * minRows - spacing.y; + SetLayoutInputForAxis(minSpace, minSpace, -1, 1); + } + + public override void SetLayoutHorizontal() + { + SetProxyCellsAlongAxis(0); + } + + public override void SetLayoutVertical() + { + SetProxyCellsAlongAxis(1); + + foreach (var item in handleChildren) + { + item.UpdateLayout(); + } + } + + + + private void SetProxyCellsAlongAxis(int axis) + { + // Normally a Layout Controller should only set horizontal values when invoked for the horizontal axis + // and only vertical values when invoked for the vertical axis. + // However, in this case we set both the horizontal and vertical position when invoked for the vertical axis. + // Since we only set the horizontal position and not the size, it shouldn't affect children's layout, + // and thus shouldn't break the rule that all horizontal layout must be calculated before all vertical layout. + var proxyChildCount = handleChildren.Count; + if (axis == 0) + { + // Only set the sizes when invoked for horizontal axis, not the positions. + + for (int i = 0; i < proxyChildCount; i++) + { + ItemProxy proxy = handleChildren[i]; + + proxy.Width = _layoutCellsize.x; + proxy.Height = _layoutCellsize.y; + } + return; + } + + float width = rectTransform.rect.size.x; + float height = rectTransform.rect.size.y; + + int cellCountX = 1; + int cellCountY = 1; + if (m_Constraint == Constraint.FixedColumnCount) + { + cellCountX = m_ConstraintCount; + + if (proxyChildCount > cellCountX) + cellCountY = proxyChildCount / cellCountX + (proxyChildCount % cellCountX > 0 ? 1 : 0); + } + else if (m_Constraint == Constraint.FixedRowCount) + { + cellCountY = m_ConstraintCount; + + if (proxyChildCount > cellCountY) + cellCountX = proxyChildCount / cellCountY + (proxyChildCount % cellCountY > 0 ? 1 : 0); + } + else + { + if (_layoutCellsize.x + spacing.x <= 0) + cellCountX = int.MaxValue; + else + cellCountX = Mathf.Max(1, Mathf.FloorToInt((width - padding.horizontal + spacing.x + 0.001f) / (cellSize.x + spacing.x))); + + if (_layoutCellsize.y + spacing.y <= 0) + cellCountY = int.MaxValue; + else + cellCountY = Mathf.Max(1, Mathf.FloorToInt((height - padding.vertical + spacing.y + 0.001f) / (cellSize.y + spacing.y))); + } + + int cornerX = (int)startCorner % 2; + int cornerY = (int)startCorner / 2; + + int cellsPerMainAxis, actualCellCountX, actualCellCountY; + if (startAxis == Axis.Horizontal) + { + cellsPerMainAxis = cellCountX; + actualCellCountX = Mathf.Clamp(cellCountX, 1, proxyChildCount); + actualCellCountY = Mathf.Clamp(cellCountY, 1, Mathf.CeilToInt(proxyChildCount / (float)cellsPerMainAxis)); + } + else + { + cellsPerMainAxis = cellCountY; + actualCellCountY = Mathf.Clamp(cellCountY, 1, proxyChildCount); + actualCellCountX = Mathf.Clamp(cellCountX, 1, Mathf.CeilToInt(proxyChildCount / (float)cellsPerMainAxis)); + } + + Vector2 requiredSpace = new Vector2( + actualCellCountX * _layoutCellsize.x + (actualCellCountX - 1) * spacing.x, + actualCellCountY * _layoutCellsize.y + (actualCellCountY - 1) * spacing.y + ); + Vector2 startOffset = new Vector2( + GetStartOffset(0, requiredSpace.x), + GetStartOffset(1, requiredSpace.y) + ); + + for (int i = 0; i < proxyChildCount; i++) + { + int positionX; + int positionY; + if (startAxis == Axis.Horizontal) + { + positionX = i % cellsPerMainAxis; + positionY = i / cellsPerMainAxis; + } + else + { + positionX = i / cellsPerMainAxis; + positionY = i % cellsPerMainAxis; + } + + if (cornerX == 1) + positionX = actualCellCountX - 1 - positionX; + if (cornerY == 1) + positionY = actualCellCountY - 1 - positionY; + + SetProxyChildAlongAxis(handleChildren[i], 0, startOffset.x + (_layoutCellsize[0] + spacing[0]) * positionX, _layoutCellsize[0]); + SetProxyChildAlongAxis(handleChildren[i], 1, startOffset.y + (_layoutCellsize[1] + spacing[1]) * positionY, _layoutCellsize[1]); + } + } + + private void SetProxyChildAlongAxis(ItemProxy proxy, int axis, float pos, float size) + { + var scaleFactor = 1.0f; + + if (proxy == null) + return; + + Vector2 sizeDelta = new Vector2(proxy.Width, proxy.Height); + sizeDelta[axis] = size; + proxy.Width = sizeDelta.x; + proxy.Height = sizeDelta.y; + + Vector2 anchoredPosition = proxy.AnchoredPosition; + anchoredPosition[axis] = (axis == 0) ? (pos + size * proxy.Pivot[axis] * scaleFactor) : (-pos - size * (1f - proxy.Pivot[axis]) * scaleFactor); + proxy.AnchoredPosition = anchoredPosition; + } + + public void UpdateProxyVisualState() + { + if (m_dataDirty) + { + foreach (var proxy in children) + { + proxy.UpdateView(true); + } + Canvas.ForceUpdateCanvases(); + + m_dataDirty = false; + } + + if (ViewRect == null) + { + foreach (var proxy in children) + { + proxy.IsInViewRect = true; + } + return; + } + + Vector3[] corners = new Vector3[4]; + ViewRect.GetLocalCorners(corners); + Rect parentRect = ViewRect.rect; + parentRect.position = corners[0]; + + rectTransform.GetLocalCorners(corners); + Vector2 leftUpCorner = corners[1]; + + foreach (var proxy in children) + { + var localPos = leftUpCorner + proxy.AnchoredPosition; + localPos.x -= proxy.Width * 0.5f; + localPos.y -= proxy.Height * 0.5f; + localPos = transform.localToWorldMatrix.MultiplyPoint(localPos); + localPos = ViewRect.worldToLocalMatrix.MultiplyPoint(localPos); + + Rect proxyRect = new Rect(localPos, new Vector2(proxy.Width, proxy.Height)); + + if (parentRect.Overlaps(proxyRect)) proxy.IsInViewRect = true; + else proxy.IsInViewRect = false; + } + } + + public bool PauseUpdateView; + private void LateUpdate() + { + if (!PauseUpdateView) + { + updateFixHeightAndWidth(); + + UpdateProxyVisualState(); + HandleProxyShow(); + } + } + + private void updateFixHeightAndWidth() + { + _layoutCellsize = cellSize; + } + + private List NeedDelayShowItems = new List(); + private bool hasNeedShowInLastFrame = false; + private float stepDuration = 0f; + private void HandleProxyShow(bool allLoad = true, float delayStep = 0.02f) + { + if (allLoad) + { + foreach (var proxy in children) + { + if (proxy.NeedHide) + proxy.UpdateView(); + else if (proxy.NeedShow) + proxy.UpdateView(); + } + } + else + { + NeedDelayShowItems.Clear(); + foreach (var proxy in children) + { + if (proxy.NeedHide) + proxy.UpdateView(); + else if (proxy.NeedShow && !proxy.firstShow) + proxy.UpdateView(); + else if (proxy.NeedShow && proxy.firstShow) + { + NeedDelayShowItems.Add(proxy); + } + } + + if (NeedDelayShowItems.Count == 0 && hasNeedShowInLastFrame) + { + // Debug.Log("Show Complete!", gameObject); + OnItemDelayShowPorcessComplete?.Invoke(); + } + hasNeedShowInLastFrame = NeedDelayShowItems.Count > 0; + + stepDuration += Time.deltaTime; + while (stepDuration >= delayStep) + { + foreach (var proxy in NeedDelayShowItems) + { + if (proxy.NeedShow) + { + proxy.UpdateView(); + break; + } + } + stepDuration -= delayStep; + } + } + } + + protected override void OnDestroy() + { + Clear(); + } + + public void Clear() + { + foreach (var proxy in children) + proxy.Dispose(); + + children.Clear(); + } + + + public void SetData(IEnumerable dataList) + { + Clear(); + + if (dataList == null) + { + ItemCount = 0; + if (_dataList != null) + _dataList.Clear(); + } + else if (dataList is IEnumerable) + { var ienumrable = (IEnumerable)dataList; - List temp = new List(); - foreach (var item in ienumrable) - { - temp.Add(item); - } - ItemCount = temp.Count; - _dataList = temp; - } - else - { - Debug.LogException(new Exception("ItemPresent SetData 传递的参数类型不受支持"), gameObject); - return; - } - - m_dataDirty = true; - } - - public void UpdateDependencyProperty(object dp) - { - _dependencyProperty = dp; - foreach (var proxy in children) - { - proxy.UpdateDP(); - } - - //m_dataDirty = true; - } - - public Dictionary CacheItemScripts => _cacheItemScripts; - - public object DependencyProperty => _dependencyProperty; - - public RectTransform RectTransform => rectTransform; - public Vector2 GetItemAnchorePos(int index) - { - var proxy = children[index]; - return proxy.AnchoredPosition; - } - public RectTransform GetItemUIIfExist(int index) - { - if (index < 0) return null; - if (children.Count <= index) return null; - - var proxy = children[index]; - return proxy.RuntimeItemUI; - } - public List DataList - { - get => _dataList; - set => SetData(value); - } - - private ScrollRect _scrollRect; - public RectTransform GetItemUIByDataIndex(int dataIndex) - { - if (_scrollRect == null) - { - _scrollRect = GetComponentInParent(); - } - //if (_scrollRect != null) MoveToScrollViewCenter(_scrollRect, dataIndex); - - return this.GetItemUIIfExist(dataIndex); - } - - public RectTransform GetTemplate(object data) - { - if (m_itemSelector == null) return ItemTemplate; - else return m_itemSelector.GetItemTemplate(data); - } -} + List temp = new List(); + foreach (var item in ienumrable) + { + temp.Add(item); + } + ItemCount = temp.Count; + _dataList = temp; + } + else + { + Debug.LogException(new Exception("ItemPresent SetData 传递的参数类型不受支持"), gameObject); + return; + } + + m_dataDirty = true; + } + + public void UpdateDependencyProperty(object dp) + { + _dependencyProperty = dp; + foreach (var proxy in children) + { + proxy.UpdateDP(); + } + + //m_dataDirty = true; + } + + public Dictionary CacheItemScripts => _cacheItemScripts; + + public object DependencyProperty => _dependencyProperty; + + public RectTransform RectTransform => rectTransform; + public Vector2 GetItemAnchorePos(int index) + { + var proxy = children[index]; + return proxy.AnchoredPosition; + } + public RectTransform GetItemUIIfExist(int index) + { + if (index < 0) return null; + if (children.Count <= index) return null; + + var proxy = children[index]; + return proxy.RuntimeItemUI; + } + public List DataList + { + get => _dataList; + set => SetData(value); + } + + private ScrollRect _scrollRect; + public RectTransform GetItemUIByDataIndex(int dataIndex) + { + if (_scrollRect == null) + { + _scrollRect = GetComponentInParent(); + } + //if (_scrollRect != null) MoveToScrollViewCenter(_scrollRect, dataIndex); + + return this.GetItemUIIfExist(dataIndex); + } + + public RectTransform GetTemplate(object data) + { + if (m_itemSelector == null) return ItemTemplate; + else return m_itemSelector.GetItemTemplate(data); + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/ItemPresent/ItemProxy.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/ItemPresent/ItemProxy.cs index 489d2af5..6d230311 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/ItemPresent/ItemProxy.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/ItemPresent/ItemProxy.cs @@ -1,11 +1,11 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.UI; - - - -public interface IVirtualLayout +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + + + +public interface IVirtualLayout { Dictionary CacheItemScripts { get; } List DataList { get; } @@ -18,10 +18,10 @@ public interface IVirtualLayout void UpdateProxyVisualState(); void UpdateDependencyProperty(object dp); void SetData(IEnumerable dataList); - void MoveToScrollViewCenter(ScrollRect scrollRect, int dataIndex); -} - -public class ItemProxy + void MoveToScrollViewCenter(ScrollRect scrollRect, int dataIndex); +} + +public class ItemProxy { public bool IsDestroyed; public bool Visible = true; @@ -207,10 +207,10 @@ public class ItemProxy GameObject.DestroyImmediate(_runtimeInstance.gameObject); _runtimeInstance = null; } - } -} - -public class ScripteInterface + } +} + +public class ScripteInterface { private IVirtualItem _itemInstance; public IVirtualItem ItemInstance => _itemInstance; @@ -237,15 +237,15 @@ public class ScripteInterface if (_itemInstance == null) return; _itemInstance.SetDependencyProperty(dependencyProperty); - } - -} - -public interface IVirtualItem + } + +} + +public interface IVirtualItem { GameObject gameObject { get; } int Index { get; set; } void SetData(object data); void SetDependencyProperty(object data); - void Release(); -} + void Release(); +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/LaunchUI.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/LaunchUI.cs index a375a2ed..1f4e1abf 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/LaunchUI.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/LaunchUI.cs @@ -1,131 +1,131 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugEmuOnline.Client.UI; -using Coffee.UIExtensions; -using DG.Tweening; -using DG.Tweening.Core; -using DG.Tweening.Plugins.Options; -using UnityEngine; -using UnityEngine.UI; - -namespace AxibugEmuOnline.Client -{ - public class LaunchUI : MonoBehaviour - { - [SerializeField] - RectTransform MainMenuRoot; - [SerializeField] - MainMenuController MainMenu; - [SerializeField] - Image XMBBackground; - [SerializeField] - Image RomPreviewBigPic; - [SerializeField] - CanvasGroup XMBCG_For_RomPreviewBigPic; - - Vector2 m_mainLayoutPosition; - [SerializeField] - float m_detailLayoutPosition_x = 55; - [SerializeField] - float m_LayoutChangeSpeed = 10; - - public static LaunchUI Instance { get; private set; } - - TweenerCore m_layoutTween; - AlphaWraper romPreviewWraper; - - private void Awake() - { - Instance = this; - m_mainLayoutPosition = MainMenuRoot.anchoredPosition; - MainMenu.ListenControlAction = true; - - romPreviewWraper = new AlphaWraper(XMBCG_For_RomPreviewBigPic, RomPreviewBigPic.GetComponent(), false); - } - - private void Start() - { - CommandDispatcher.Instance.Mode = CommandListener.ScheduleType.Normal; - } - - private void Update() - { - if (CommandDispatcher.Instance.Mode == CommandListener.ScheduleType.Gaming && App.emu.Core == null) - CommandDispatcher.Instance.Mode = CommandListener.ScheduleType.Normal; - } - - public void HideMainMenu() - { - XMBBackground.gameObject.SetActiveEx(false); - MainMenuRoot.gameObject.SetActiveEx(false); - RomPreviewBigPic.gameObject.SetActiveEx(false); - } - - public void ShowMainMenu() - { - XMBBackground.gameObject.SetActiveEx(true); - MainMenuRoot.gameObject.SetActiveEx(true); - +using AxibugEmuOnline.Client.ClientCore; +using AxibugEmuOnline.Client.UI; +using Coffee.UIExtensions; +using DG.Tweening; +using DG.Tweening.Core; +using DG.Tweening.Plugins.Options; +using UnityEngine; +using UnityEngine.UI; + +namespace AxibugEmuOnline.Client +{ + public class LaunchUI : MonoBehaviour + { + [SerializeField] + RectTransform MainMenuRoot; + [SerializeField] + MainMenuController MainMenu; + [SerializeField] + Image XMBBackground; + [SerializeField] + Image RomPreviewBigPic; + [SerializeField] + CanvasGroup XMBCG_For_RomPreviewBigPic; + + Vector2 m_mainLayoutPosition; + [SerializeField] + float m_detailLayoutPosition_x = 55; + [SerializeField] + float m_LayoutChangeSpeed = 10; + + public static LaunchUI Instance { get; private set; } + + TweenerCore m_layoutTween; + AlphaWraper romPreviewWraper; + + private void Awake() + { + Instance = this; + m_mainLayoutPosition = MainMenuRoot.anchoredPosition; + MainMenu.ListenControlAction = true; + + romPreviewWraper = new AlphaWraper(XMBCG_For_RomPreviewBigPic, RomPreviewBigPic.GetComponent(), false); + } + + private void Start() + { + CommandDispatcher.Instance.Mode = CommandListener.ScheduleType.Normal; + } + + private void Update() + { + if (CommandDispatcher.Instance.Mode == CommandListener.ScheduleType.Gaming && App.emu.Core == null) + CommandDispatcher.Instance.Mode = CommandListener.ScheduleType.Normal; + } + + public void HideMainMenu() + { + XMBBackground.gameObject.SetActiveEx(false); + MainMenuRoot.gameObject.SetActiveEx(false); + RomPreviewBigPic.gameObject.SetActiveEx(false); + } + + public void ShowMainMenu() + { + XMBBackground.gameObject.SetActiveEx(true); + MainMenuRoot.gameObject.SetActiveEx(true); + if (romPreviewWraper.On) { XMBCG_For_RomPreviewBigPic.gameObject.SetActive(false); RomPreviewBigPic.gameObject.SetActive(true); - } + } else if (!romPreviewWraper.On) { XMBCG_For_RomPreviewBigPic.gameObject.SetActive(true); XMBCG_For_RomPreviewBigPic.alpha = 1; RomPreviewBigPic.gameObject.SetActive(false); - } - } - + } + } + public void HideRomPreview() { romPreviewWraper.On = false; - } - + } + public void SetRomPreview(Sprite sp) { if (MainMenu.ListenControlAction) return; RomPreviewBigPic.sprite = sp; romPreviewWraper.On = true; - } - - public void ToDetailMenuLayout() - { - if (m_layoutTween != null) - { - m_layoutTween.Kill(); - m_layoutTween = null; - } - m_layoutTween = DOTween - .To( - () => MainMenuRoot.anchoredPosition, - (x) => MainMenuRoot.anchoredPosition = x, - new Vector2(m_detailLayoutPosition_x, MainMenuRoot.anchoredPosition.y), - m_LayoutChangeSpeed) - .SetSpeedBased(); - MainMenu.ListenControlAction = false; - MainMenu.EnterDetailState(); - } - - public void ToMainMenuLayout() - { - if (m_layoutTween != null) - { - m_layoutTween.Kill(); - m_layoutTween = null; - } - m_layoutTween = DOTween.To( - () => MainMenuRoot.anchoredPosition, - (x) => MainMenuRoot.anchoredPosition = x, - m_mainLayoutPosition, - m_LayoutChangeSpeed) - .SetSpeedBased(); - MainMenu.ListenControlAction = true; - MainMenu.ExitDetailState(); - - HideRomPreview(); - } - } -} + } + + public void ToDetailMenuLayout() + { + if (m_layoutTween != null) + { + m_layoutTween.Kill(); + m_layoutTween = null; + } + m_layoutTween = DOTween + .To( + () => MainMenuRoot.anchoredPosition, + (x) => MainMenuRoot.anchoredPosition = x, + new Vector2(m_detailLayoutPosition_x, MainMenuRoot.anchoredPosition.y), + m_LayoutChangeSpeed) + .SetSpeedBased(); + MainMenu.ListenControlAction = false; + MainMenu.EnterDetailState(); + } + + public void ToMainMenuLayout() + { + if (m_layoutTween != null) + { + m_layoutTween.Kill(); + m_layoutTween = null; + } + m_layoutTween = DOTween.To( + () => MainMenuRoot.anchoredPosition, + (x) => MainMenuRoot.anchoredPosition = x, + m_mainLayoutPosition, + m_LayoutChangeSpeed) + .SetSpeedBased(); + MainMenu.ListenControlAction = true; + MainMenu.ExitDetailState(); + + HideRomPreview(); + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI.cs index 16d7bdac..74bb21e4 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI.cs @@ -1,334 +1,332 @@ -using AxibugEmuOnline.Client.ClientCore; -using DG.Tweening; -using DG.Tweening.Core; -using DG.Tweening.Plugins.Options; -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace AxibugEmuOnline.Client -{ - public class OptionUI : CommandExecuter - { - [SerializeField] - RectTransform MenuRoot; - [SerializeField] - Selector SelectBorder; - - Dictionary m_menuUI_templates = new Dictionary(); - - private OptionUI m_child; - private OptionUI m_parent; - - public override bool AloneMode => true; - public override bool Enable => m_bPoped && (!m_child || !m_child.m_bPoped); - - private bool m_bPoped; - private readonly List m_runtimeMenuItems = new List(); - - private int m_selectIndex = -1; - public int SelectIndex - { - get => m_selectIndex; - set - { - value = Mathf.Clamp(value, 0, m_runtimeMenuItems.Count - 1); - if (m_selectIndex == value) return; - +using AxibugEmuOnline.Client.ClientCore; +using DG.Tweening; +using DG.Tweening.Core; +using DG.Tweening.Plugins.Options; +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace AxibugEmuOnline.Client +{ + public class OptionUI : CommandExecuter + { + [SerializeField] + RectTransform MenuRoot; + [SerializeField] + Selector SelectBorder; + + Dictionary m_menuUI_templates = new Dictionary(); + + private OptionUI m_child; + private OptionUI m_parent; + + public override bool AloneMode => true; + public override bool Enable => m_bPoped && (!m_child || !m_child.m_bPoped); + + private bool m_bPoped; + private readonly List m_runtimeMenuItems = new List(); + + private int m_selectIndex = -1; + public int SelectIndex + { + get => m_selectIndex; + set + { + value = Mathf.Clamp(value, 0, m_runtimeMenuItems.Count - 1); + if (m_selectIndex == value) return; + var gap = value - m_selectIndex; - var temp = value; - while (!m_runtimeMenuItems[value].Visible) - { - if (gap > 0) - { + var temp = value; + while (!m_runtimeMenuItems[value].Visible) + { + if (gap > 0) + { temp++; if (temp >= m_runtimeMenuItems.Count) return; - } - else - { - temp--; - if (temp < 0) return; - } - - if (temp >= 0 && temp < m_runtimeMenuItems.Count) - value = temp; - } - - m_selectIndex = value; - - OptionUI_MenuItem optionUI_MenuItem = m_runtimeMenuItems[m_selectIndex]; - optionUI_MenuItem.OnFocus(); - var itemUIRect = optionUI_MenuItem.transform as RectTransform; - SelectBorder.Target = itemUIRect; - } - } - - protected override void Awake() - { + } + else + { + temp--; + if (temp < 0) return; + } + + if (temp >= 0 && temp < m_runtimeMenuItems.Count) + value = temp; + } + + m_selectIndex = value; + + OptionUI_MenuItem optionUI_MenuItem = m_runtimeMenuItems[m_selectIndex]; + optionUI_MenuItem.OnFocus(); + var itemUIRect = optionUI_MenuItem.transform as RectTransform; + SelectBorder.Target = itemUIRect; + } + } + + protected override void Awake() + { foreach (var templateIns in GetComponentsInChildren(true)) { m_menuUI_templates[templateIns.GetType()] = templateIns; templateIns.gameObject.SetActiveEx(false); - } - - SelectBorder.gameObject.SetActiveEx(false); - base.Awake(); - } - - protected override void Update() - { - SelectBorder.Active = Enable; - UpdateMenuState(); - - base.Update(); - } - - private void UpdateMenuState() - { - if (!m_bPoped) return; - - if (checkDirty()) + } + + SelectBorder.gameObject.SetActiveEx(false); + base.Awake(); + } + + protected override void Update() + { + SelectBorder.Active = Enable; + UpdateMenuState(); + + base.Update(); + } + + private void UpdateMenuState() + { + if (!m_bPoped) return; + + if (checkDirty()) { Canvas.ForceUpdateCanvases(); - var topParent = FindTopOptionUI(); - var totalWidth = GetTotalWidth(topParent); - - Vector2 end = new Vector2(-totalWidth, MenuRoot.anchoredPosition.y); - if (m_popTween != null) { + Vector2 end = new Vector2(-MenuRoot.rect.width, MenuRoot.anchoredPosition.y); m_popTween.ChangeEndValue(end, false); - } + } else { - topParent.MenuRoot.anchoredPosition = end; + Vector2 end = new Vector2(-MenuRoot.rect.width, MenuRoot.anchoredPosition.y); + var topParent = m_parent; + while (topParent != null && topParent.m_parent != null) + { + topParent = topParent.m_parent; + } + if (topParent != null) + { + topParent.MenuRoot.anchoredPosition = end; + } + else + { + MenuRoot.anchoredPosition = end; + } } - RebuildSelectIndex(); - } - } - - private void RebuildSelectIndex() - { - Canvas.ForceUpdateCanvases(); - - SelectIndex = Mathf.Clamp(SelectIndex, 0, m_runtimeMenuItems.Count - 1); - var selectItem = m_runtimeMenuItems[SelectIndex]; - - if (selectItem.Visible == false) - { - bool find = false; - int currentSelect = SelectIndex; - while (currentSelect > 0) - { - currentSelect--; - if (m_runtimeMenuItems[currentSelect].Visible) - { - find = true; - } - } - if (!find) - { - currentSelect = SelectIndex; - while (currentSelect < m_runtimeMenuItems.Count) - { - if (m_runtimeMenuItems[currentSelect].Visible) - { - find = true; - break; - } - currentSelect++; - } - } - - if (find) - SelectIndex = currentSelect; - } - else - { - var itemUIRect = selectItem.transform as RectTransform; - SelectBorder.Target = itemUIRect; - } - } - - private bool checkDirty() - { - bool dirty = false; - foreach (var menuItem in m_runtimeMenuItems) - { - if (menuItem.gameObject.activeSelf != menuItem.Visible) - { - dirty = true; - menuItem.gameObject.SetActive(menuItem.Visible); - } - } - - return dirty; + RebuildSelectIndex(); + } } - private TweenerCore m_popTween; - private TweenerCore m_hideTween; - CommandListener.ScheduleType? m_lastCS; - private Action m_onClose; - - /// - /// 当菜单弹出时,动态添加一个菜单选项 - /// - /// - public void AddOptionMenuWhenPoping(InternalOptionMenu menu) - { - if (!m_bPoped) return; - - CreateRuntimeMenuItem(menu); - Canvas.ForceUpdateCanvases(); - - OptionUI_MenuItem optionUI_MenuItem = m_runtimeMenuItems[m_selectIndex]; - SelectBorder.Target = null; - SelectBorder.Target = optionUI_MenuItem.transform as RectTransform; - } - - - public void Pop(List menus, int defaultIndex = 0, Action onClose = null) where T : InternalOptionMenu + private void RebuildSelectIndex() + { + Canvas.ForceUpdateCanvases(); + + SelectIndex = Mathf.Clamp(SelectIndex, 0, m_runtimeMenuItems.Count - 1); + var selectItem = m_runtimeMenuItems[SelectIndex]; + + if (selectItem.Visible == false) + { + bool find = false; + int currentSelect = SelectIndex; + while (currentSelect > 0) + { + currentSelect--; + if (m_runtimeMenuItems[currentSelect].Visible) + { + find = true; + } + } + if (!find) + { + currentSelect = SelectIndex; + while (currentSelect < m_runtimeMenuItems.Count) + { + if (m_runtimeMenuItems[currentSelect].Visible) + { + find = true; + break; + } + currentSelect++; + } + } + + if (find) + SelectIndex = currentSelect; + } + else + { + var itemUIRect = selectItem.transform as RectTransform; + SelectBorder.Target = itemUIRect; + } + } + + private bool checkDirty() + { + bool dirty = false; + foreach (var menuItem in m_runtimeMenuItems) + { + if (menuItem.gameObject.activeSelf != menuItem.Visible) + { + dirty = true; + menuItem.gameObject.SetActive(menuItem.Visible); + } + } + + return dirty; + } + + private TweenerCore m_popTween; + private TweenerCore m_hideTween; + CommandListener.ScheduleType? m_lastCS; + private Action m_onClose; + + /// + /// 当菜单弹出时,动态添加一个菜单选项 + /// + /// + public void AddOptionMenuWhenPoping(InternalOptionMenu menu) + { + if (!m_bPoped) return; + + CreateRuntimeMenuItem(menu); + Canvas.ForceUpdateCanvases(); + + OptionUI_MenuItem optionUI_MenuItem = m_runtimeMenuItems[m_selectIndex]; + SelectBorder.Target = null; + SelectBorder.Target = optionUI_MenuItem.transform as RectTransform; + } + + + public void Pop(List menus, int defaultIndex = 0, Action onClose = null) where T : InternalOptionMenu { if (m_hideTween != null) { m_hideTween.Kill(true); - } - - m_onClose = onClose; - ReleaseRuntimeMenus(); - foreach (var menu in menus) CreateRuntimeMenuItem(menu); - CommandDispatcher.Instance.RegistController(this); - SelectBorder.gameObject.SetActiveEx(true); - - Canvas.ForceUpdateCanvases(); - - m_selectIndex = defaultIndex; - OptionUI_MenuItem optionUI_MenuItem = m_runtimeMenuItems[defaultIndex]; - optionUI_MenuItem.OnFocus(); - - var itemUIRect = optionUI_MenuItem.transform as RectTransform; - SelectBorder.Target = itemUIRect; - SelectBorder.RefreshPosition(); - - if (!m_bPoped) - { - m_bPoped = true; - Vector2 start = new Vector2(0, MenuRoot.anchoredPosition.y); - Vector2 end = new Vector2(-MenuRoot.rect.width, MenuRoot.anchoredPosition.y); - m_popTween = DOTween.To( - () => start, - (value) => - { - var moveDelta = value - start; - start = value; - - var topParent = FindTopOptionUI(); - topParent.MenuRoot.anchoredPosition += moveDelta; - }, - end, - 0.3f - ).SetEase(Ease.OutCubic); - m_popTween.onComplete = () => m_popTween = null; - - m_lastCS = CommandDispatcher.Instance.Mode; - CommandDispatcher.Instance.Mode = CommandListener.ScheduleType.Normal; - } - } - - OptionUI FindTopOptionUI() - { - if (m_parent == null) return this; + } - var topParent = m_parent; - while (topParent != null && topParent.m_parent != null) + m_onClose = onClose; + ReleaseRuntimeMenus(); + foreach (var menu in menus) CreateRuntimeMenuItem(menu); + CommandDispatcher.Instance.RegistController(this); + SelectBorder.gameObject.SetActiveEx(true); + + Canvas.ForceUpdateCanvases(); + + m_selectIndex = defaultIndex; + OptionUI_MenuItem optionUI_MenuItem = m_runtimeMenuItems[defaultIndex]; + optionUI_MenuItem.OnFocus(); + + var itemUIRect = optionUI_MenuItem.transform as RectTransform; + SelectBorder.Target = itemUIRect; + SelectBorder.RefreshPosition(); + + if (!m_bPoped) { - topParent = topParent.m_parent; - } - - return topParent; - } - - static float GetTotalWidth(OptionUI root) - { - float totalWidth = root.MenuRoot.rect.width; - if (root.m_child != null) - { - totalWidth += GetTotalWidth(root.m_child); - } - - return totalWidth; - } - + + m_bPoped = true; + Vector2 start = new Vector2(0, MenuRoot.anchoredPosition.y); + Vector2 end = new Vector2(-MenuRoot.rect.width, MenuRoot.anchoredPosition.y); + m_popTween = DOTween.To( + () => start, + (value) => + { + var moveDelta = value - start; + start = value; + + var topParent = m_parent; + while (topParent != null && topParent.m_parent != null) + { + topParent = topParent.m_parent; + } + if (topParent != null) + { + topParent.MenuRoot.anchoredPosition += moveDelta; + } + else + { + MenuRoot.anchoredPosition += moveDelta; + } + }, + end, + 0.3f + ).SetEase(Ease.OutCubic); + m_popTween.onComplete = () => m_popTween = null; + + m_lastCS = CommandDispatcher.Instance.Mode; + CommandDispatcher.Instance.Mode = CommandListener.ScheduleType.Normal; + } + + } + /// /// 关闭这个侧边栏选项UI /// - public void Hide() - { - if (m_bPoped) - { + public void Hide() + { + if (m_bPoped) + { if (m_child != null) { m_child.Hide(); - } - - Vector2 start = new Vector2(-MenuRoot.rect.width, MenuRoot.anchoredPosition.y); - Vector2 end = new Vector2(0, MenuRoot.anchoredPosition.y); - - SelectBorder.gameObject.SetActiveEx(false); - - CommandDispatcher.Instance.UnRegistController(this); - Canvas.ForceUpdateCanvases(); - + } + + Vector2 start = new Vector2(-MenuRoot.rect.width, MenuRoot.anchoredPosition.y); + Vector2 end = new Vector2(0, MenuRoot.anchoredPosition.y); + + SelectBorder.gameObject.SetActiveEx(false); + + CommandDispatcher.Instance.UnRegistController(this); + Canvas.ForceUpdateCanvases(); + if (m_popTween != null) { - m_popTween.Kill(true); - } - - m_hideTween = DOTween.To( - () => start, - (value) => - { - var moveDelta = value - start; - start = value; - - var topParent = m_parent; - while (topParent != null && topParent.m_parent != null) - { - topParent = topParent.m_parent; - } - if (topParent != null) - { - topParent.MenuRoot.anchoredPosition += moveDelta; - } - else - { - MenuRoot.anchoredPosition += moveDelta; - } - }, - end, - 0.3f - ).SetEase(Ease.OutCubic); + m_popTween.Kill(true); + } + + m_hideTween = DOTween.To( + () => start, + (value) => + { + var moveDelta = value - start; + start = value; + + var topParent = m_parent; + while (topParent != null && topParent.m_parent != null) + { + topParent = topParent.m_parent; + } + if (topParent != null) + { + topParent.MenuRoot.anchoredPosition += moveDelta; + } + else + { + MenuRoot.anchoredPosition += moveDelta; + } + }, + end, + 0.3f + ).SetEase(Ease.OutCubic); m_hideTween.onComplete = () => { ReleaseRuntimeMenus(); m_runtimeMenuItems.Clear(); m_hideTween = null; - }; - - m_bPoped = false; - - CommandDispatcher.Instance.Mode = m_lastCS.Value; - - m_onClose?.Invoke(); - m_onClose = null; - } - } - - private void CreateRuntimeMenuItem(InternalOptionMenu menuData) - { - m_menuUI_templates.TryGetValue(menuData.MenuUITemplateType, out var template); + }; + + m_bPoped = false; + + CommandDispatcher.Instance.Mode = m_lastCS.Value; + + m_onClose?.Invoke(); + m_onClose = null; + } + } + + private void CreateRuntimeMenuItem(InternalOptionMenu menuData) + { + m_menuUI_templates.TryGetValue(menuData.MenuUITemplateType, out var template); if (template == null) { throw new NotImplementedException($"{menuData.GetType().Name}指定的MenuUI类型实例未在OptionUI中找到"); @@ -338,158 +336,158 @@ namespace AxibugEmuOnline.Client menuUI.gameObject.SetActive(true); menuUI.SetData(this, menuData); m_runtimeMenuItems.Add(menuUI); - } - - private void ReleaseRuntimeMenus() - { - foreach (var item in m_runtimeMenuItems) - { - item.OnHide(); - Destroy(item.gameObject); - } - m_runtimeMenuItems.Clear(); - } - - protected override void OnCmdSelectItemDown() + } + + private void ReleaseRuntimeMenus() + { + foreach (var item in m_runtimeMenuItems) + { + item.OnHide(); + Destroy(item.gameObject); + } + m_runtimeMenuItems.Clear(); + } + + protected override void OnCmdSelectItemDown() { int old = SelectIndex; SelectIndex++; if (old != SelectIndex) - App.audioMgr.PlaySFX(AudioMgr.E_SFXTYPE.Option); - } - - protected override void OnCmdSelectItemUp() + App.audioMgr.PlaySFX(AudioMgr.E_SFXTYPE.Option); + } + + protected override void OnCmdSelectItemUp() { int old = SelectIndex; SelectIndex--; if (old != SelectIndex) - App.audioMgr.PlaySFX(AudioMgr.E_SFXTYPE.Option); - } - - protected override void OnCmdBack() - { - Hide(); - App.audioMgr.PlaySFX(AudioMgr.E_SFXTYPE.Cancel); - } - - protected override void OnCmdSelectItemLeft() - { - var executer = m_runtimeMenuItems[SelectIndex]; - if (executer) - { - executer.OnLeft(); - } - } - - protected override void OnCmdSelectItemRight() - { - var executer = m_runtimeMenuItems[SelectIndex]; - if (!executer.IsExpandMenu) - { - executer.OnRight(); - return; - } - - OnCmdEnter(); - } - - protected override bool OnCmdEnter() - { - var executer = m_runtimeMenuItems[SelectIndex]; - bool cancelHide = false; - executer.OnExecute(this, ref cancelHide); + App.audioMgr.PlaySFX(AudioMgr.E_SFXTYPE.Option); + } + + protected override void OnCmdBack() + { + Hide(); + App.audioMgr.PlaySFX(AudioMgr.E_SFXTYPE.Cancel); + } + + protected override void OnCmdSelectItemLeft() + { + var executer = m_runtimeMenuItems[SelectIndex]; + if (executer) + { + executer.OnLeft(); + } + } + + protected override void OnCmdSelectItemRight() + { + var executer = m_runtimeMenuItems[SelectIndex]; + if (!executer.IsExpandMenu) + { + executer.OnRight(); + return; + } + + OnCmdEnter(); + } + + protected override bool OnCmdEnter() + { + var executer = m_runtimeMenuItems[SelectIndex]; + bool cancelHide = false; + executer.OnExecute(this, ref cancelHide); if (!cancelHide) Hide(); - App.audioMgr.PlaySFX(AudioMgr.E_SFXTYPE.Option); - return false; - } - - /// - /// 展开下级菜单 - /// - /// - /// - /// - /// - public void ExpandSubMenu(List menus, int defaultIndex = 0, Action onClose = null) where T : InternalOptionMenu - { - if (m_child == null) - { - var sourcePrefab = Resources.Load("UIPrefabs/OptionUI"); - m_child = Instantiate(sourcePrefab, transform).GetComponent(); - m_child.name = $"{name}_Sub"; - m_child.m_parent = this; - } - - Canvas.ForceUpdateCanvases(); - - m_child.Pop(menus, 0, onClose); - } - - public void RemoveItem(OptionUI_MenuItem ui) - { - var index = m_runtimeMenuItems.IndexOf(ui); - if (index == -1) return; - - m_runtimeMenuItems.Remove(ui); - ui.OnHide(); - Destroy(ui.gameObject); - - RebuildSelectIndex(); - } - } - - /// - /// 带有执行行为的菜单 - /// - public abstract class ExecuteMenu : InternalOptionMenu - { - public override Type MenuUITemplateType => typeof(OptionUI_ExecuteItem); - /// 设置这个值以控制菜单中显示"已应用"标记 - public virtual bool IsApplied { get; } - - public abstract void OnExcute(OptionUI optionUI, ref bool cancelHide); - } - - /// - /// 带有展开行为的可执行菜单 - /// - public abstract class ExpandMenu : ExecuteMenu - { - protected ExpandMenu() : base() { } - - public sealed override void OnExcute(OptionUI optionUI, ref bool cancelHide) - { - cancelHide = true; - optionUI.ExpandSubMenu(GetOptionMenus()); - } - - protected abstract List GetOptionMenus(); + App.audioMgr.PlaySFX(AudioMgr.E_SFXTYPE.Option); + return false; + } + + /// + /// 展开下级菜单 + /// + /// + /// + /// + /// + public void ExpandSubMenu(List menus, int defaultIndex = 0, Action onClose = null) where T : InternalOptionMenu + { + if (m_child == null) + { + var sourcePrefab = Resources.Load("UIPrefabs/OptionUI"); + m_child = Instantiate(sourcePrefab, transform).GetComponent(); + m_child.name = $"{name}_Sub"; + m_child.m_parent = this; + } + + Canvas.ForceUpdateCanvases(); + + m_child.Pop(menus, 0, onClose); + } + + public void RemoveItem(OptionUI_MenuItem ui) + { + var index = m_runtimeMenuItems.IndexOf(ui); + if (index == -1) return; + + m_runtimeMenuItems.Remove(ui); + ui.OnHide(); + Destroy(ui.gameObject); + + RebuildSelectIndex(); + } } - /// - /// 带有值类型显示和编辑的菜单 - /// - public abstract class ValueSetMenu : InternalOptionMenu - { + + /// + /// 带有执行行为的菜单 + /// + public abstract class ExecuteMenu : InternalOptionMenu + { + public override Type MenuUITemplateType => typeof(OptionUI_ExecuteItem); + /// 设置这个值以控制菜单中显示"已应用"标记 + public virtual bool IsApplied { get; } + + public abstract void OnExcute(OptionUI optionUI, ref bool cancelHide); + } + + /// + /// 带有展开行为的可执行菜单 + /// + public abstract class ExpandMenu : ExecuteMenu + { + protected ExpandMenu() : base() { } + + public sealed override void OnExcute(OptionUI optionUI, ref bool cancelHide) + { + cancelHide = true; + optionUI.ExpandSubMenu(GetOptionMenus()); + } + + protected abstract List GetOptionMenus(); + } + /// + /// 带有值类型显示和编辑的菜单 + /// + public abstract class ValueSetMenu : InternalOptionMenu + { public override Type MenuUITemplateType => typeof(OptionUI_ValueEditItem); - protected ValueSetMenu() : base() { } - - public abstract Type ValueType { get; } - public abstract object ValueRaw { get; } - public abstract void OnValueChanged(object newValue); - public abstract object Min { get; } - public abstract object Max { get; } - } - - /// 不要直接继承这个类 - public abstract class InternalOptionMenu - { - public abstract Type MenuUITemplateType { get; } - public abstract string Name { get; } - public virtual Sprite Icon { get; } - public virtual bool Visible => true; - - public virtual void OnFocus() { } - public virtual void OnShow(OptionUI_MenuItem ui) { } + protected ValueSetMenu() : base() { } + + public abstract Type ValueType { get; } + public abstract object ValueRaw { get; } + public abstract void OnValueChanged(object newValue); + public abstract object Min { get; } + public abstract object Max { get; } + } + + /// 不要直接继承这个类 + public abstract class InternalOptionMenu + { + public abstract Type MenuUITemplateType { get; } + public abstract string Name { get; } + public virtual Sprite Icon { get; } + public virtual bool Visible => true; + + public virtual void OnFocus() { } + public virtual void OnShow(OptionUI_MenuItem ui) { } public virtual void OnHide() { } - } -} + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI_ExecuteItem.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI_ExecuteItem.cs index 0fc4e903..57bf319f 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI_ExecuteItem.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI_ExecuteItem.cs @@ -1,28 +1,28 @@ -using UnityEngine; - -namespace AxibugEmuOnline.Client -{ - public class OptionUI_ExecuteItem : OptionUI_MenuItem - { - public GameObject ExpandFlag; - public GameObject ApplyFlag; - - protected override void OnSetData(InternalOptionMenu menuData) - { - base.OnSetData(menuData); - - ExpandFlag.SetActiveEx(IsExpandMenu); - ApplyFlag.SetActiveEx(IsApplied); - } - - public override void OnExecute(OptionUI optionUI, ref bool cancelHide) - { - MenuData.OnExcute(optionUI, ref cancelHide); - } - +using UnityEngine; + +namespace AxibugEmuOnline.Client +{ + public class OptionUI_ExecuteItem : OptionUI_MenuItem + { + public GameObject ExpandFlag; + public GameObject ApplyFlag; + + protected override void OnSetData(InternalOptionMenu menuData) + { + base.OnSetData(menuData); + + ExpandFlag.SetActiveEx(IsExpandMenu); + ApplyFlag.SetActiveEx(IsApplied); + } + + public override void OnExecute(OptionUI optionUI, ref bool cancelHide) + { + MenuData.OnExcute(optionUI, ref cancelHide); + } + protected override void Update() { ApplyFlag.SetActiveEx(IsApplied); - } - } -} + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI_SavSlotItem.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI_SavSlotItem.cs index 6648e0d6..02882d66 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI_SavSlotItem.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI_SavSlotItem.cs @@ -1,13 +1,13 @@ -using AxibugEmuOnline.Client.Tools; -using System; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.UI; -using static AxibugEmuOnline.Client.InGameUI_SaveStateMenu; - -namespace AxibugEmuOnline.Client -{ - public class OptionUI_SavSlotItem : OptionUI_MenuItem +using AxibugEmuOnline.Client.Tools; +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; +using static AxibugEmuOnline.Client.InGameUI_SaveStateMenu; + +namespace AxibugEmuOnline.Client +{ + public class OptionUI_SavSlotItem : OptionUI_MenuItem { public RawImage UI_ScreenShot; public Image UI_Empty; @@ -113,5 +113,5 @@ namespace AxibugEmuOnline.Client { MenuData.OnExcute(optionUI, ref cancelHide); } - } -} + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI_ValueEditItem.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI_ValueEditItem.cs index 9f8ff3b4..b87e4d7a 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI_ValueEditItem.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI_ValueEditItem.cs @@ -1,84 +1,84 @@ -using AxibugEmuOnline.Client.ClientCore; -using UnityEngine; - -namespace AxibugEmuOnline.Client -{ - public class OptionUI_ValueEditItem : OptionUI_MenuItem - { - [SerializeField] - OptionUI_ValueEditItem_FloatEdit com_floatEdit; - [SerializeField] - OptionUI_ValueEditItem_IntEdit com_intEdit; - [SerializeField] - OptionUI_ValueEditItem_BoolEdit com_boolEdit; - [SerializeField] - OptionUI_ValueEditItem_EnumEdit com_enumEdit; - - IValueEditControl m_currentCom; - - protected override void OnSetData(InternalOptionMenu menuData) - { - com_floatEdit.gameObject.SetActive(false); - com_intEdit.gameObject.SetActive(false); - com_boolEdit.gameObject.SetActive(false); - com_enumEdit.gameObject.SetActive(false); - - if (menuData is ValueSetMenu) - { +using AxibugEmuOnline.Client.ClientCore; +using UnityEngine; + +namespace AxibugEmuOnline.Client +{ + public class OptionUI_ValueEditItem : OptionUI_MenuItem + { + [SerializeField] + OptionUI_ValueEditItem_FloatEdit com_floatEdit; + [SerializeField] + OptionUI_ValueEditItem_IntEdit com_intEdit; + [SerializeField] + OptionUI_ValueEditItem_BoolEdit com_boolEdit; + [SerializeField] + OptionUI_ValueEditItem_EnumEdit com_enumEdit; + + IValueEditControl m_currentCom; + + protected override void OnSetData(InternalOptionMenu menuData) + { + com_floatEdit.gameObject.SetActive(false); + com_intEdit.gameObject.SetActive(false); + com_boolEdit.gameObject.SetActive(false); + com_enumEdit.gameObject.SetActive(false); + + if (menuData is ValueSetMenu) + { var valueMenu = (ValueSetMenu)menuData; - if (valueMenu.ValueType == typeof(float)) - { - m_currentCom = com_floatEdit; - } + if (valueMenu.ValueType == typeof(float)) + { + m_currentCom = com_floatEdit; + } else if (valueMenu.ValueType == typeof(int)) { m_currentCom = com_intEdit; - } + } else if (valueMenu.ValueType == typeof(bool)) { m_currentCom = com_boolEdit; - } - else if (valueMenu.ValueType.IsEnum) - { - m_currentCom = com_enumEdit; - } - else - { - App.log.Error($"尚未支持的数据类型:{valueMenu.ValueType}"); - return; - } - - - m_currentCom.gameObject.SetActiveEx(true); - m_currentCom.SetData(valueMenu); - } - - base.OnSetData(menuData); - } - - public override void OnExecute(OptionUI optionUI, ref bool cancelHide) - { - cancelHide = true; - m_currentCom?.OnExecute(); - } - - public override void OnLeft() - { - m_currentCom?.OnLeft(); - } - - public override void OnRight() - { - m_currentCom?.OnRight(); - } - } - - public interface IValueEditControl - { - void SetData(ValueSetMenu valueMenu); - GameObject gameObject { get; } - void OnLeft(); - void OnRight(); - void OnExecute(); - } -} + } + else if (valueMenu.ValueType.IsEnum) + { + m_currentCom = com_enumEdit; + } + else + { + App.log.Error($"尚未支持的数据类型:{valueMenu.ValueType}"); + return; + } + + + m_currentCom.gameObject.SetActiveEx(true); + m_currentCom.SetData(valueMenu); + } + + base.OnSetData(menuData); + } + + public override void OnExecute(OptionUI optionUI, ref bool cancelHide) + { + cancelHide = true; + m_currentCom?.OnExecute(); + } + + public override void OnLeft() + { + m_currentCom?.OnLeft(); + } + + public override void OnRight() + { + m_currentCom?.OnRight(); + } + } + + public interface IValueEditControl + { + void SetData(ValueSetMenu valueMenu); + GameObject gameObject { get; } + void OnLeft(); + void OnRight(); + void OnExecute(); + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI_ValueEditItem_BoolEdit.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI_ValueEditItem_BoolEdit.cs index 744cd9c4..7e2c0e7f 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI_ValueEditItem_BoolEdit.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/OptionUI/OptionUI_ValueEditItem_BoolEdit.cs @@ -1,37 +1,37 @@ -using UnityEngine; -using UnityEngine.UI; - -namespace AxibugEmuOnline.Client -{ - public class OptionUI_ValueEditItem_BoolEdit : MonoBehaviour, IValueEditControl - { - [SerializeField] - Text txt_value; - +using UnityEngine; +using UnityEngine.UI; + +namespace AxibugEmuOnline.Client +{ + public class OptionUI_ValueEditItem_BoolEdit : MonoBehaviour, IValueEditControl + { + [SerializeField] + Text txt_value; + private ValueSetMenu m_valueMenu; - public void SetData(ValueSetMenu valueMenu) - { - m_valueMenu = valueMenu; - txt_value.text = valueMenu.ValueRaw.ToString(); - } - - public void OnLeft() - { - OnExecute(); - } - - public void OnRight() - { - OnExecute(); - } - - public void OnExecute() + public void SetData(ValueSetMenu valueMenu) + { + m_valueMenu = valueMenu; + txt_value.text = valueMenu.ValueRaw.ToString(); + } + + public void OnLeft() + { + OnExecute(); + } + + public void OnRight() + { + OnExecute(); + } + + public void OnExecute() { var value = (bool)m_valueMenu.ValueRaw; - value = !value; - txt_value.text = value.ToString(); - m_valueMenu.OnValueChanged(value); - } - } -} + value = !value; + txt_value.text = value.ToString(); + m_valueMenu.OnValueChanged(value); + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/RoomUI/RoomItem.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/RoomUI/RoomItem.cs index c46e20a2..b54beada 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/RoomUI/RoomItem.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/RoomUI/RoomItem.cs @@ -1,15 +1,15 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugEmuOnline.Client.Event; -using AxibugEmuOnline.Client.Manager; -using AxibugEmuOnline.Client.UI; -using AxibugProtobuf; -using Coffee.UIExtensions; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.UI; -using Debug = System.Diagnostics.Debug; - -namespace AxibugEmuOnline.Client +using AxibugEmuOnline.Client.ClientCore; +using AxibugEmuOnline.Client.Event; +using AxibugEmuOnline.Client.Manager; +using AxibugEmuOnline.Client.UI; +using AxibugProtobuf; +using Coffee.UIExtensions; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; +using Debug = System.Diagnostics.Debug; + +namespace AxibugEmuOnline.Client { public class RoomItem : MenuItem, IVirtualItem { @@ -17,7 +17,7 @@ namespace AxibugEmuOnline.Client [SerializeField] Slider m_downloadProgress; [SerializeField] GameObject m_downloadingFlag; [SerializeField] GameObject m_romReadyFlag; - [SerializeField] + [SerializeField] UIShiny DownloadComplete; private RomFile m_romFile; @@ -172,5 +172,5 @@ namespace AxibugEmuOnline.Client { Reset(); } - } + } } \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/SubMenuItemGroup.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/SubMenuItemGroup.cs index 257078e9..196327b5 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/SubMenuItemGroup.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/SubMenuItemGroup.cs @@ -1,235 +1,235 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugEmuOnline.Client.UI; -using DG.Tweening; -using DG.Tweening.Core; -using DG.Tweening.Plugins.Options; -using System.Collections.Generic; -using UnityEngine; - -namespace AxibugEmuOnline.Client -{ - public class SubMenuItemGroup : MenuItemController - { - [SerializeField] - MenuItem SubMenuItemTemplate; - [SerializeField] - CanvasGroup alphaGroup; - private TweenerCore selectTween; - - private bool m_selected; - - private TweenerCore rollTween; - - - protected override void Awake() - { - m_selected = false; - if (alphaGroup != null) alphaGroup.alpha = 0; - - base.Awake(); - } - - public override void Init(List menuDataList) - { -#if UNITY_EDITOR - while (transform.childCount > 0) - { - DestroyImmediate(transform.GetChild(0).gameObject); - } -#else - for (int i = 0; i < transform.childCount; i++) - { - Destroy(transform.GetChild(i).gameObject); - } -#endif - - m_runtimeMenuUI.Clear(); - foreach (MenuData menuData in menuDataList) - { - var template = menuData.OverrideTemplate != null ? menuData.OverrideTemplate : SubMenuItemTemplate; - - var item = Clone(template, transform); - item.SetData(menuData); - m_runtimeMenuUI.Add(item); - } - - calcItemPosition(); - - for (var i = 0; i < m_runtimeMenuUI.Count; i++) - { - var item = m_runtimeMenuUI[i]; - var needPos = m_itemUIPosition[i]; - item.Rect.anchoredPosition = needPos; - } - } - - protected override bool OnCmdEnter() - { - base.OnCmdEnter(); - - LaunchUI.Instance.ToDetailMenuLayout(); - var item = GetItemUIByIndex(SelectIndex); - item.SetSelectState(false); - App.audioMgr.PlaySFX(AudioMgr.E_SFXTYPE.Option); - return true; - } - - protected override void OnCmdBack() +using AxibugEmuOnline.Client.ClientCore; +using AxibugEmuOnline.Client.UI; +using DG.Tweening; +using DG.Tweening.Core; +using DG.Tweening.Plugins.Options; +using System.Collections.Generic; +using UnityEngine; + +namespace AxibugEmuOnline.Client +{ + public class SubMenuItemGroup : MenuItemController + { + [SerializeField] + MenuItem SubMenuItemTemplate; + [SerializeField] + CanvasGroup alphaGroup; + private TweenerCore selectTween; + + private bool m_selected; + + private TweenerCore rollTween; + + + protected override void Awake() { - if (m_enteredItem != null) - App.audioMgr.PlaySFX(AudioMgr.E_SFXTYPE.Cancel); - - base.OnCmdBack(); - - LaunchUI.Instance.ToMainMenuLayout(); - var item = GetItemUIByIndex(SelectIndex); + m_selected = false; + if (alphaGroup != null) alphaGroup.alpha = 0; + + base.Awake(); + } + + public override void Init(List menuDataList) + { +#if UNITY_EDITOR + while (transform.childCount > 0) + { + DestroyImmediate(transform.GetChild(0).gameObject); + } +#else + for (int i = 0; i < transform.childCount; i++) + { + Destroy(transform.GetChild(i).gameObject); + } +#endif + + m_runtimeMenuUI.Clear(); + foreach (MenuData menuData in menuDataList) + { + var template = menuData.OverrideTemplate != null ? menuData.OverrideTemplate : SubMenuItemTemplate; + + var item = Clone(template, transform); + item.SetData(menuData); + m_runtimeMenuUI.Add(item); + } + + calcItemPosition(); + + for (var i = 0; i < m_runtimeMenuUI.Count; i++) + { + var item = m_runtimeMenuUI[i]; + var needPos = m_itemUIPosition[i]; + item.Rect.anchoredPosition = needPos; + } + } + + protected override bool OnCmdEnter() + { + base.OnCmdEnter(); + + LaunchUI.Instance.ToDetailMenuLayout(); + var item = GetItemUIByIndex(SelectIndex); + item.SetSelectState(false); + App.audioMgr.PlaySFX(AudioMgr.E_SFXTYPE.Option); + return true; + } + + protected override void OnCmdBack() + { + if (m_enteredItem != null) + App.audioMgr.PlaySFX(AudioMgr.E_SFXTYPE.Cancel); + + base.OnCmdBack(); + + LaunchUI.Instance.ToMainMenuLayout(); + var item = GetItemUIByIndex(SelectIndex); item.SetSelectState(true); - } - - protected override void OnCmdSelectItemUp() - { + } + + protected override void OnCmdSelectItemUp() + { if (m_enteredItem == null) { int old = SelectIndex; SelectIndex--; if (old != SelectIndex) App.audioMgr.PlaySFX(AudioMgr.E_SFXTYPE.Cursor); - } - } - - protected override void OnCmdSelectItemDown() - { + } + } + + protected override void OnCmdSelectItemDown() + { if (m_enteredItem == null) { int old = SelectIndex; SelectIndex++; if (old != SelectIndex) App.audioMgr.PlaySFX(AudioMgr.E_SFXTYPE.Cursor); - } - } - - public virtual void SetSelect(bool select) - { - if (m_selected == select) return; - m_selected = select; - - if (selectTween != null) - { - selectTween.Kill(); - selectTween = null; - } - - if (select) - { - selectTween = DOTween.To(() => alphaGroup.alpha, (x) => alphaGroup.alpha = x, 1, 10).SetSpeedBased(); - } - else - { - selectTween = DOTween.To(() => alphaGroup.alpha, (x) => alphaGroup.alpha = x, 0, 10).SetSpeedBased(); - } - - ListenControlAction = m_selected; - } - - protected override void OnCmdSelectItemLeft() - { - if(m_enteredItem != null) + } + } + + public virtual void SetSelect(bool select) + { + if (m_selected == select) return; + m_selected = select; + + if (selectTween != null) + { + selectTween.Kill(); + selectTween = null; + } + + if (select) + { + selectTween = DOTween.To(() => alphaGroup.alpha, (x) => alphaGroup.alpha = x, 1, 10).SetSpeedBased(); + } + else + { + selectTween = DOTween.To(() => alphaGroup.alpha, (x) => alphaGroup.alpha = x, 0, 10).SetSpeedBased(); + } + + ListenControlAction = m_selected; + } + + protected override void OnCmdSelectItemLeft() + { + if(m_enteredItem != null) App.audioMgr.PlaySFX(AudioMgr.E_SFXTYPE.Cancel); else App.audioMgr.PlaySFX(AudioMgr.E_SFXTYPE.Option); base.OnCmdSelectItemLeft(); - OnCmdBack(); - } - - protected override void OnSelectMenuChanged() - { - if (rollTween != null) { rollTween.Kill(); rollTween = null; } - - float duration = 0.5f; - - calcItemPosition(); - - for (var i = 0; i < m_runtimeMenuUI.Count; i++) - { - var item = m_runtimeMenuUI[i]; - bool isSelectItem = i == SelectIndex; - item.SetSelectState(isSelectItem); - } - - rollTween = DOTween.To(() => 1, (x) => { }, 1, duration).OnUpdate(() => - { - var tweenProgress = rollTween.position / rollTween.Duration(); - for (var i = 0; i < m_runtimeMenuUI.Count; i++) - { - var item = m_runtimeMenuUI[i]; - var needPos = m_itemUIPosition[i]; - item.Rect.anchoredPosition = Vector2.Lerp(item.Rect.anchoredPosition, needPos, tweenProgress); - } - }).OnComplete(() => - { - for (var i = 0; i < m_runtimeMenuUI.Count; i++) - { - var item = m_runtimeMenuUI[i]; - var needPos = m_itemUIPosition[i]; - item.Rect.anchoredPosition = needPos; - } - }); - } - - [SerializeField] - Vector2 m_selectItemPosition = new Vector2(50, -51); - [SerializeField] - float step = 50f; - [SerializeField] - float splitStep = 200f; - - List m_itemUIPosition = new List(); - private void calcItemPosition() - { - m_itemUIPosition.Clear(); - for (int i = 0; i < m_runtimeMenuUI.Count; i++) - { - var gap = SelectIndex - i; - var start = m_selectItemPosition; - start.y += step * gap; - if (i < SelectIndex) start.y += splitStep; - - m_itemUIPosition.Add(start); - } - } - - private MenuItem Clone(MenuItem template, Transform parent) + OnCmdBack(); + } + + protected override void OnSelectMenuChanged() { -#if UNITY_EDITOR + if (rollTween != null) { rollTween.Kill(); rollTween = null; } + + float duration = 0.5f; + + calcItemPosition(); + + for (var i = 0; i < m_runtimeMenuUI.Count; i++) + { + var item = m_runtimeMenuUI[i]; + bool isSelectItem = i == SelectIndex; + item.SetSelectState(isSelectItem); + } + + rollTween = DOTween.To(() => 1, (x) => { }, 1, duration).OnUpdate(() => + { + var tweenProgress = rollTween.position / rollTween.Duration(); + for (var i = 0; i < m_runtimeMenuUI.Count; i++) + { + var item = m_runtimeMenuUI[i]; + var needPos = m_itemUIPosition[i]; + item.Rect.anchoredPosition = Vector2.Lerp(item.Rect.anchoredPosition, needPos, tweenProgress); + } + }).OnComplete(() => + { + for (var i = 0; i < m_runtimeMenuUI.Count; i++) + { + var item = m_runtimeMenuUI[i]; + var needPos = m_itemUIPosition[i]; + item.Rect.anchoredPosition = needPos; + } + }); + } + + [SerializeField] + Vector2 m_selectItemPosition = new Vector2(50, -51); + [SerializeField] + float step = 50f; + [SerializeField] + float splitStep = 200f; + + List m_itemUIPosition = new List(); + private void calcItemPosition() + { + m_itemUIPosition.Clear(); + for (int i = 0; i < m_runtimeMenuUI.Count; i++) + { + var gap = SelectIndex - i; + var start = m_selectItemPosition; + start.y += step * gap; + if (i < SelectIndex) start.y += splitStep; + + m_itemUIPosition.Add(start); + } + } + + private MenuItem Clone(MenuItem template, Transform parent) + { +#if UNITY_EDITOR //========================套娃宏======================== -#if UNITY_2019_1_OR_NEWER //新版Unity,因UNITY2018.2用不了这玩意儿,编辑器也罢 +#if UNITY_2019_1_OR_NEWER //新版Unity,因UNITY2018.2用不了这玩意儿,编辑器也罢 - if (Application.isPlaying) - { - var item = GameObject.Instantiate(template.gameObject, parent).GetComponent(); - item.transform.localPosition = Vector3.zero; - return item; - } - else - { - var clone = UnityEditor.PrefabUtility.InstantiatePrefab(template.gameObject, parent) as GameObject; - clone.transform.localPosition = Vector3.zero; - return clone.GetComponent(); + if (Application.isPlaying) + { + var item = GameObject.Instantiate(template.gameObject, parent).GetComponent(); + item.transform.localPosition = Vector3.zero; + return item; } -#else - var item = GameObject.Instantiate(template.gameObject, parent).GetComponent(); - item.transform.localPosition = Vector3.zero; - return item; -#endif + else + { + var clone = UnityEditor.PrefabUtility.InstantiatePrefab(template.gameObject, parent) as GameObject; + clone.transform.localPosition = Vector3.zero; + return clone.GetComponent(); + } +#else + var item = GameObject.Instantiate(template.gameObject, parent).GetComponent(); + item.transform.localPosition = Vector3.zero; + return item; +#endif //========================套娃宏 End======================== -#else - return GameObject.Instantiate(SubMenuItemTemplate.gameObject, parent).GetComponent(); -#endif +#else + return GameObject.Instantiate(SubMenuItemTemplate.gameObject, parent).GetComponent(); +#endif } - } -} + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/Tools/AlphaWraper.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/Tools/AlphaWraper.cs index 078cb6bd..d5cc9663 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/Tools/AlphaWraper.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/Tools/AlphaWraper.cs @@ -1,94 +1,94 @@ -using DG.Tweening; -using DG.Tweening.Core; -using DG.Tweening.Plugins.Options; -using UnityEngine; - -namespace AxibugEmuOnline.Client -{ +using DG.Tweening; +using DG.Tweening.Core; +using DG.Tweening.Plugins.Options; +using UnityEngine; + +namespace AxibugEmuOnline.Client +{ /// /// 用于指定一对CanvasGroup,做透明度切换 - /// - public class AlphaWraper - { - private bool m_on; - private CanvasGroup m_offUI; - private CanvasGroup m_onUI; - private TweenerCore m_onTween; - private TweenerCore m_offTween; - - public bool On - { - get => m_on; - set - { - if (m_on == value) return; - - m_on = value; - - if (m_onTween != null) - { - m_onTween.Kill(); - m_onTween = null; - } - if (m_offTween != null) - { - m_offTween.Kill(); - m_offTween = null; - } - m_onUI.gameObject.SetActiveEx(true); - m_offUI.gameObject.SetActiveEx(true); - - if (On) - { - float progress = 0f; - m_onTween = DOTween.To(() => progress, (x) => - { - progress = x; - m_onUI.alpha = progress; - m_offUI.alpha = 1 - progress; - }, 1f, 0.3f); - m_onTween.onComplete = () => - { - m_offUI.gameObject.SetActiveEx(false); - }; - } - else - { - float progress = 0f; - m_offTween = DOTween.To(() => progress, (x) => - { - progress = x; - m_onUI.alpha = 1 - progress; - m_offUI.alpha = progress; - }, 1f, 0.3f); - m_offTween.onComplete = () => - { - m_onUI.gameObject.SetActiveEx(false); - }; - } - } - } - - public AlphaWraper(CanvasGroup offUI, CanvasGroup onUI, bool defaultOn) - { - m_offUI = offUI; - m_onUI = onUI; - - m_on = defaultOn; - if (On) - { - onUI.alpha = 1; - onUI.gameObject.SetActiveEx(true); - offUI.alpha = 0; - offUI.gameObject.SetActiveEx(false); - } - else - { - onUI.alpha = 0; - onUI.gameObject.SetActiveEx(false); - offUI.alpha = 1; - offUI.gameObject.SetActiveEx(true); - } - } - } -} + /// + public class AlphaWraper + { + private bool m_on; + private CanvasGroup m_offUI; + private CanvasGroup m_onUI; + private TweenerCore m_onTween; + private TweenerCore m_offTween; + + public bool On + { + get => m_on; + set + { + if (m_on == value) return; + + m_on = value; + + if (m_onTween != null) + { + m_onTween.Kill(); + m_onTween = null; + } + if (m_offTween != null) + { + m_offTween.Kill(); + m_offTween = null; + } + m_onUI.gameObject.SetActiveEx(true); + m_offUI.gameObject.SetActiveEx(true); + + if (On) + { + float progress = 0f; + m_onTween = DOTween.To(() => progress, (x) => + { + progress = x; + m_onUI.alpha = progress; + m_offUI.alpha = 1 - progress; + }, 1f, 0.3f); + m_onTween.onComplete = () => + { + m_offUI.gameObject.SetActiveEx(false); + }; + } + else + { + float progress = 0f; + m_offTween = DOTween.To(() => progress, (x) => + { + progress = x; + m_onUI.alpha = 1 - progress; + m_offUI.alpha = progress; + }, 1f, 0.3f); + m_offTween.onComplete = () => + { + m_onUI.gameObject.SetActiveEx(false); + }; + } + } + } + + public AlphaWraper(CanvasGroup offUI, CanvasGroup onUI, bool defaultOn) + { + m_offUI = offUI; + m_onUI = onUI; + + m_on = defaultOn; + if (On) + { + onUI.alpha = 1; + onUI.gameObject.SetActiveEx(true); + offUI.alpha = 0; + offUI.gameObject.SetActiveEx(false); + } + else + { + onUI.alpha = 0; + onUI.gameObject.SetActiveEx(false); + offUI.alpha = 1; + offUI.gameObject.SetActiveEx(true); + } + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/Tools/AutoRaycastCanvasGroup.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/Tools/AutoRaycastCanvasGroup.cs index df5c5afb..7f583399 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/Tools/AutoRaycastCanvasGroup.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/Tools/AutoRaycastCanvasGroup.cs @@ -1,19 +1,19 @@ -using UnityEngine; - -namespace AxibugEmuOnline.Client -{ +using UnityEngine; + +namespace AxibugEmuOnline.Client +{ /// /// 自动根据canvasgroup的alpha控制blocksRaycasts的开启状态 - /// - [RequireComponent(typeof(CanvasGroup))] - public class AutoRaycastCanvasGroup : MonoBehaviour - { - private CanvasGroup canvasGroup; - private void Update() - { - if (canvasGroup == null) canvasGroup = gameObject.GetComponent(); - - canvasGroup.blocksRaycasts = canvasGroup.alpha == 0 ? false : true; - } - } -} + /// + [RequireComponent(typeof(CanvasGroup))] + public class AutoRaycastCanvasGroup : MonoBehaviour + { + private CanvasGroup canvasGroup; + private void Update() + { + if (canvasGroup == null) canvasGroup = gameObject.GetComponent(); + + canvasGroup.blocksRaycasts = canvasGroup.alpha == 0 ? false : true; + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/Tools/PulseInvoker.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/Tools/PulseInvoker.cs index bbe10d62..24cb2d84 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/Tools/PulseInvoker.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/Tools/PulseInvoker.cs @@ -1,62 +1,62 @@ -using System; - -namespace AxibugEmuOnline.Client.UI -{ +using System; + +namespace AxibugEmuOnline.Client.UI +{ /// /// 用于周期性触发回调的工具,带有触发周期和延迟触发的参数可调 - /// - public class PulseInvoker - { - private Action _action; - private float _interval; - private float _delay; - private float _elapsedTime; - private bool _isActive; + /// + public class PulseInvoker + { + private Action _action; + private float _interval; + private float _delay; + private float _elapsedTime; + private bool _isActive; private bool _isDelayed; - public PulseInvoker(Action action, float delay, float interval) - { - _action = action; - - _delay = delay; - _interval = interval; - } - - public void SetActive() - { - _elapsedTime = 0f; - _isActive = true; - _isDelayed = true; - } - - public void DisActive() - { - _isActive = false; - } - - public void Update(float deltaTime) - { - if (!_isActive) return; - - _elapsedTime += deltaTime; - - if (_isDelayed) - { - if (_elapsedTime >= _delay) - { - _elapsedTime -= _delay; - _isDelayed = false; - _action?.Invoke(); - } - } - else - { - if (_elapsedTime >= _interval) - { - _elapsedTime -= _interval; - _action?.Invoke(); - } - } - } - } -} + public PulseInvoker(Action action, float delay, float interval) + { + _action = action; + + _delay = delay; + _interval = interval; + } + + public void SetActive() + { + _elapsedTime = 0f; + _isActive = true; + _isDelayed = true; + } + + public void DisActive() + { + _isActive = false; + } + + public void Update(float deltaTime) + { + if (!_isActive) return; + + _elapsedTime += deltaTime; + + if (_isDelayed) + { + if (_elapsedTime >= _delay) + { + _elapsedTime -= _delay; + _isDelayed = false; + _action?.Invoke(); + } + } + else + { + if (_elapsedTime >= _interval) + { + _elapsedTime -= _interval; + _action?.Invoke(); + } + } + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/Tools/Selector.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/Tools/Selector.cs index b4f5c840..2cf827fd 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/Tools/Selector.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/Tools/Selector.cs @@ -21,6 +21,8 @@ namespace AxibugEmuOnline.Client get => m_target; set { + if (m_target == value) return; + m_target = value; if (m_target == null) { diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/Tools/UITool.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/Tools/UITool.cs index 61c8f337..3da3ef1f 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/Tools/UITool.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/Tools/UITool.cs @@ -1,38 +1,38 @@ -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.UI; - -namespace AxibugEmuOnline.Client -{ - public static class UITool - { - private static Dictionary _caches = new Dictionary(); - public static Material GetMaterial(this Graphic graphic) - { +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +namespace AxibugEmuOnline.Client +{ + public static class UITool + { + private static Dictionary _caches = new Dictionary(); + public static Material GetMaterial(this Graphic graphic) + { Material material; - if (_caches.TryGetValue(graphic, out material)) - { - return material; - } - else - { - var cloneMat = Material.Instantiate(graphic.material); - _caches[graphic] = cloneMat; - graphic.material = cloneMat; - return cloneMat; - } - } - public static void SetMaterial(this Graphic graphic, Material material) - { - graphic.material = material; - _caches.Remove(graphic); - } - - public static void SetAlpha(this Graphic graphic, float alpha) - { - var temp = graphic.color; - temp.a = alpha; - graphic.color = temp; - } - } -} + if (_caches.TryGetValue(graphic, out material)) + { + return material; + } + else + { + var cloneMat = Material.Instantiate(graphic.material); + _caches[graphic] = cloneMat; + graphic.material = cloneMat; + return cloneMat; + } + } + public static void SetMaterial(this Graphic graphic, Material material) + { + graphic.material = material; + _caches.Remove(graphic); + } + + public static void SetAlpha(this Graphic graphic, float alpha) + { + var temp = graphic.color; + temp.a = alpha; + graphic.color = temp; + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/VirtualSubMenuItem.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/VirtualSubMenuItem.cs index 41d73b50..a72ce488 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/VirtualSubMenuItem.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/VirtualSubMenuItem.cs @@ -1,102 +1,102 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugEmuOnline.Client.UI; -using DG.Tweening; -using DG.Tweening.Core; -using DG.Tweening.Plugins.Options; -using System.Collections; -using UnityEngine; - -namespace AxibugEmuOnline.Client -{ - public abstract class VirtualSubMenuItem : MenuItem - { - [SerializeField] - protected CanvasGroup RomGroupRoot; - - private TweenerCore m_showTween; - - protected override void Awake() - { - base.Awake(); - - RomGroupRoot.gameObject.SetActive(false); - RomGroupRoot.alpha = 0; - } - - public override void SetSelectState(bool selected) - { - if (m_select == selected) return; - - m_select = selected; - - if (ShadowIcon != null) ShadowIcon.gameObject.SetActiveEx(selected); - - if (progressTween != null) { progressTween.Kill(); progressTween = null; } - - progressTween = DOTween.To(() => m_progress, (x) => m_progress = x, m_select ? 1 : 0, 5) - .SetSpeedBased().OnUpdate(() => - { - if (InfoNode != null) InfoNode.alpha = m_progress; - - Root.localScale = Vector3.one * Mathf.Lerp(UnSelectScale, SelectScale, m_progress); - }); - } - - public override bool OnEnterItem() - { - RomGroupRoot.gameObject.SetActive(true); - RomGroupRoot.alpha = 0; - - if (m_showTween != null) - { - m_showTween.Kill(); - m_showTween = null; - } - m_showTween = DOTween.To(() => RomGroupRoot.alpha, (x) => RomGroupRoot.alpha = x, 1, 0.2f); - - var thirdMenuGroup = SubMenuItemGroup as ThirdMenuRoot; - thirdMenuGroup.itemGroup.Clear(); - - RefreshUI(); - - if (SubMenuItemGroup != null) SubMenuItemGroup.SetSelect(true); - - return true; - } - - public delegate void VirtualListDataHandle(IEnumerable data, int initialIndex); - - - protected void RefreshUI() - { - GetVirtualListDatas((datas, initialIndex) => - { - var thirdMenuGroup = SubMenuItemGroup as ThirdMenuRoot; - thirdMenuGroup.itemGroup.UpdateDependencyProperty(thirdMenuGroup); - thirdMenuGroup.itemGroup.SetData(datas); - thirdMenuGroup.itemGroup.UpdateProxyVisualState(); +using AxibugEmuOnline.Client.ClientCore; +using AxibugEmuOnline.Client.UI; +using DG.Tweening; +using DG.Tweening.Core; +using DG.Tweening.Plugins.Options; +using System.Collections; +using UnityEngine; + +namespace AxibugEmuOnline.Client +{ + public abstract class VirtualSubMenuItem : MenuItem + { + [SerializeField] + protected CanvasGroup RomGroupRoot; + + private TweenerCore m_showTween; + + protected override void Awake() + { + base.Awake(); + + RomGroupRoot.gameObject.SetActive(false); + RomGroupRoot.alpha = 0; + } + + public override void SetSelectState(bool selected) + { + if (m_select == selected) return; + + m_select = selected; + + if (ShadowIcon != null) ShadowIcon.gameObject.SetActiveEx(selected); + + if (progressTween != null) { progressTween.Kill(); progressTween = null; } + + progressTween = DOTween.To(() => m_progress, (x) => m_progress = x, m_select ? 1 : 0, 5) + .SetSpeedBased().OnUpdate(() => + { + if (InfoNode != null) InfoNode.alpha = m_progress; + + Root.localScale = Vector3.one * Mathf.Lerp(UnSelectScale, SelectScale, m_progress); + }); + } + + public override bool OnEnterItem() + { + RomGroupRoot.gameObject.SetActive(true); + RomGroupRoot.alpha = 0; + + if (m_showTween != null) + { + m_showTween.Kill(); + m_showTween = null; + } + m_showTween = DOTween.To(() => RomGroupRoot.alpha, (x) => RomGroupRoot.alpha = x, 1, 0.2f); + + var thirdMenuGroup = SubMenuItemGroup as ThirdMenuRoot; + thirdMenuGroup.itemGroup.Clear(); + + RefreshUI(); + + if (SubMenuItemGroup != null) SubMenuItemGroup.SetSelect(true); + + return true; + } + + public delegate void VirtualListDataHandle(IEnumerable data, int initialIndex); + + + protected void RefreshUI() + { + GetVirtualListDatas((datas, initialIndex) => + { + var thirdMenuGroup = SubMenuItemGroup as ThirdMenuRoot; + thirdMenuGroup.itemGroup.UpdateDependencyProperty(thirdMenuGroup); + thirdMenuGroup.itemGroup.SetData(datas); + thirdMenuGroup.itemGroup.UpdateProxyVisualState(); thirdMenuGroup.ResetToIndex(initialIndex); - }); - } - - protected abstract void GetVirtualListDatas(VirtualListDataHandle callback); - - public override bool OnExitItem() - { - if (m_showTween != null) - { - m_showTween.Kill(); - m_showTween = null; - } - m_showTween = DOTween.To(() => RomGroupRoot.alpha, (x) => RomGroupRoot.alpha = x, 0, 0.2f) - .OnComplete(() => - { - RomGroupRoot.gameObject.SetActive(false); - }); - - if (SubMenuItemGroup != null) SubMenuItemGroup.SetSelect(false); - - return true; - } - } -} + }); + } + + protected abstract void GetVirtualListDatas(VirtualListDataHandle callback); + + public override bool OnExitItem() + { + if (m_showTween != null) + { + m_showTween.Kill(); + m_showTween = null; + } + m_showTween = DOTween.To(() => RomGroupRoot.alpha, (x) => RomGroupRoot.alpha = x, 0, 0.2f) + .OnComplete(() => + { + RomGroupRoot.gameObject.SetActive(false); + }); + + if (SubMenuItemGroup != null) SubMenuItemGroup.SetSelect(false); + + return true; + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/XMBTopGroupUI/XMBInfoBar.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/XMBTopGroupUI/XMBInfoBar.cs index 5cbf80f4..d03517bc 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/XMBTopGroupUI/XMBInfoBar.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/XMBTopGroupUI/XMBInfoBar.cs @@ -1,137 +1,137 @@ -using AxibugEmuOnline.Client; -using AxibugEmuOnline.Client.ClientCore; -using System; -using UnityEngine; -using UnityEngine.UI; - -public class XMBInfoBar : MonoBehaviour -{ - public Text txtDateTime; - public Image imgPowerRoot; - public Image imgPower1; - public Image imgPower2; - public Image imgPower3; - public Text DelayValue; - public Text OnlinePlayerCount; - public Text FPS; - public GameObject ControlSlotInfoNode; - - void OnEnable() - { - TickLoop.LoopAction_1s += RefreshAll; - RefreshAll(); - } - +using AxibugEmuOnline.Client; +using AxibugEmuOnline.Client.ClientCore; +using System; +using UnityEngine; +using UnityEngine.UI; + +public class XMBInfoBar : MonoBehaviour +{ + public Text txtDateTime; + public Image imgPowerRoot; + public Image imgPower1; + public Image imgPower2; + public Image imgPower3; + public Text DelayValue; + public Text OnlinePlayerCount; + public Text FPS; + public GameObject ControlSlotInfoNode; + + void OnEnable() + { + TickLoop.LoopAction_1s += RefreshAll; + RefreshAll(); + } + private void Update() { ControlSlotInfoNode.SetActiveEx(App.emu.Core != null); - } - - void OnDisable() - { - TickLoop.LoopAction_1s -= RefreshAll; - } - - void RefreshAll() - { - RefreshTime(); - RefreshPower(); - RefreshDelay(); - RefreshFps(); } - /// - /// (uint lastFrame, float lastTime) - /// - ValueTuple m_lastFrameInfo; - private void RefreshFps() - { - if (App.emu.Core == null) - FPS.gameObject.SetActiveEx(false); - else - { + void OnDisable() + { + TickLoop.LoopAction_1s -= RefreshAll; + } + + void RefreshAll() + { + RefreshTime(); + RefreshPower(); + RefreshDelay(); + RefreshFps(); + } + + /// + /// (uint lastFrame, float lastTime) + /// + ValueTuple m_lastFrameInfo; + private void RefreshFps() + { + if (App.emu.Core == null) + FPS.gameObject.SetActiveEx(false); + else + { FPS.gameObject.SetActiveEx(true); //var gap = App.emu.Core.Frame - m_lastFrameInfo.lastFrame; //var time = Time.realtimeSinceStartup - m_lastFrameInfo.lastTime; var gap = App.emu.Core.Frame - m_lastFrameInfo.Item1; var time = Time.realtimeSinceStartup - m_lastFrameInfo.Item2; - var fps = gap / time; + var fps = gap / time; FPS.text = $"FPS:{fps:.#}"; //m_lastFrameInfo.lastFrame = App.emu.Core.Frame; //m_lastFrameInfo.lastTime = Time.realtimeSinceStartup; m_lastFrameInfo.Item1 = App.emu.Core.Frame; m_lastFrameInfo.Item2 = Time.realtimeSinceStartup; - } - } - - private void RefreshDelay() - { - if (App.user == null) - { - DelayValue.text = $"-"; - OnlinePlayerCount.text = $"-"; - return; - } - else - { - if (App.user.IsLoggedIn) - { - DelayValue.text = $"{App.tick.AveNetDelay * 1000:0}ms"; - OnlinePlayerCount.text = App.user.OnlinePlayerCount.ToString(); - } - else - { - DelayValue.text = "-"; - OnlinePlayerCount.text = $"-"; - } - } - } - - void RefreshTime() - { - txtDateTime.text = DateTime.Now.ToString("MM/dd HH:mm"); - } - - void RefreshPower() - { - float battery = SystemInfo.batteryLevel; - - if (Application.platform == RuntimePlatform.WindowsPlayer - || - Application.platform == RuntimePlatform.WindowsEditor - || - Application.platform == RuntimePlatform.OSXPlayer - || - Application.platform == RuntimePlatform.OSXEditor - ) - { - battery = 1f; - } - - if (battery > 0.80f) - { - imgPower1.gameObject.SetActive(true); - imgPower2.gameObject.SetActive(true); - imgPower2.gameObject.SetActive(true); - } - else if (battery > 0.50f) - { - imgPower1.gameObject.SetActive(false); - imgPower2.gameObject.SetActive(true); - imgPower2.gameObject.SetActive(true); - } - else if (battery > 0.20f) - { - imgPower1.gameObject.SetActive(false); - imgPower2.gameObject.SetActive(false); - imgPower2.gameObject.SetActive(true); - } - else - { - imgPower1.gameObject.SetActive(false); - imgPower2.gameObject.SetActive(false); - imgPower2.gameObject.SetActive(false); - } - } -} + } + } + + private void RefreshDelay() + { + if (App.user == null) + { + DelayValue.text = $"-"; + OnlinePlayerCount.text = $"-"; + return; + } + else + { + if (App.user.IsLoggedIn) + { + DelayValue.text = $"{App.tick.AveNetDelay * 1000:0}ms"; + OnlinePlayerCount.text = App.user.OnlinePlayerCount.ToString(); + } + else + { + DelayValue.text = "-"; + OnlinePlayerCount.text = $"-"; + } + } + } + + void RefreshTime() + { + txtDateTime.text = DateTime.Now.ToString("MM/dd HH:mm"); + } + + void RefreshPower() + { + float battery = SystemInfo.batteryLevel; + + if (Application.platform == RuntimePlatform.WindowsPlayer + || + Application.platform == RuntimePlatform.WindowsEditor + || + Application.platform == RuntimePlatform.OSXPlayer + || + Application.platform == RuntimePlatform.OSXEditor + ) + { + battery = 1f; + } + + if (battery > 0.80f) + { + imgPower1.gameObject.SetActive(true); + imgPower2.gameObject.SetActive(true); + imgPower2.gameObject.SetActive(true); + } + else if (battery > 0.50f) + { + imgPower1.gameObject.SetActive(false); + imgPower2.gameObject.SetActive(true); + imgPower2.gameObject.SetActive(true); + } + else if (battery > 0.20f) + { + imgPower1.gameObject.SetActive(false); + imgPower2.gameObject.SetActive(false); + imgPower2.gameObject.SetActive(true); + } + else + { + imgPower1.gameObject.SetActive(false); + imgPower2.gameObject.SetActive(false); + imgPower2.gameObject.SetActive(false); + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Utility.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Utility.cs index c7c630cd..5ca49638 100644 --- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Utility.cs +++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Utility.cs @@ -1,47 +1,47 @@ -using AxibugEmuOnline.Client.ClientCore; -using AxibugProtobuf; -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; - -namespace AxibugEmuOnline.Client -{ - public static class Utility - { - public static void SetActiveEx(this GameObject go, bool active) - { - if (active && go.activeSelf) return; - if (!active && !go.activeSelf) return; - - go.SetActive(active); - } - - public static string GetHostNickName(this Protobuf_Room_MiniInfo roomInfo) - { - var hostUID = roomInfo.HostPlayerUID; - Protobuf_Room_GamePlaySlot slotdata = roomInfo.GamePlaySlotList.FirstOrDefault(w => w.PlayerUID == hostUID); - if (slotdata != null) - return slotdata.PlayerNickName; - else - return string.Empty; - } - - public static void GetRoomPlayers(this Protobuf_Room_MiniInfo roomInfo, out int current, out int max) - { - current = 0; max = 4; - current = roomInfo.GamePlaySlotList.Count(w => w.PlayerUID > 0); - } - - private static Dictionary s_RomFileCahcesInRoomInfo = new Dictionary(); - public static void FetchRomFileInRoomInfo(this Protobuf_Room_MiniInfo roomInfo, Action callback) - { - RomFile romFile; - - if (s_RomFileCahcesInRoomInfo.TryGetValue(roomInfo.GameRomID, out romFile)) - { - callback.Invoke(roomInfo, romFile); - return; +using AxibugEmuOnline.Client.ClientCore; +using AxibugProtobuf; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace AxibugEmuOnline.Client +{ + public static class Utility + { + public static void SetActiveEx(this GameObject go, bool active) + { + if (active && go.activeSelf) return; + if (!active && !go.activeSelf) return; + + go.SetActive(active); + } + + public static string GetHostNickName(this Protobuf_Room_MiniInfo roomInfo) + { + var hostUID = roomInfo.HostPlayerUID; + Protobuf_Room_GamePlaySlot slotdata = roomInfo.GamePlaySlotList.FirstOrDefault(w => w.PlayerUID == hostUID); + if (slotdata != null) + return slotdata.PlayerNickName; + else + return string.Empty; + } + + public static void GetRoomPlayers(this Protobuf_Room_MiniInfo roomInfo, out int current, out int max) + { + current = 0; max = 4; + current = roomInfo.GamePlaySlotList.Count(w => w.PlayerUID > 0); + } + + private static Dictionary s_RomFileCahcesInRoomInfo = new Dictionary(); + public static void FetchRomFileInRoomInfo(this Protobuf_Room_MiniInfo roomInfo, Action callback) + { + RomFile romFile; + + if (s_RomFileCahcesInRoomInfo.TryGetValue(roomInfo.GameRomID, out romFile)) + { + callback.Invoke(roomInfo, romFile); + return; } App.StartCoroutine(App.httpAPI.GetRomInfo(roomInfo.GameRomID, (romWebData) => @@ -51,17 +51,17 @@ namespace AxibugEmuOnline.Client s_RomFileCahcesInRoomInfo[roomInfo.GameRomID] = _romFile; callback.Invoke(roomInfo, _romFile); - })); - - } - + })); + + } + public static byte[] ToJPG(this Texture texture, Vector2 scale) { Texture2D outputTex = ConvertFromRenderTexture(texture, scale); return outputTex.EncodeToJPG(); - } - + } + private static Texture2D ConvertFromRenderTexture(Texture src, Vector2 scale) { float offsetX = (scale.x < 0) ? 1 : 0; @@ -83,6 +83,6 @@ namespace AxibugEmuOnline.Client RenderTexture.active = null; RenderTexture.ReleaseTemporary(tempRT); return tex; - } - } -} + } + } +}