合并Switch版本修改

This commit is contained in:
sin365 2025-08-21 10:34:57 +08:00
parent ccf2279947
commit a1aa816426
70 changed files with 7723 additions and 7600 deletions

View File

@ -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<SonyVitaCommonDialog>();
#endif
#if UNITY_SWITCH
//创建创建Switch
switchCommon = new GameObject().AddComponent<SwitchCommon>();
#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>();
switchCommon.gameObject.name = "[SwitchCommon]";
GameObject.DontDestroyOnLoad(switchCommon);
#endif
}

View File

@ -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);
}
}
}
}
}

View File

@ -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

View File

@ -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
{
/// <summary> 获得模拟器核心中的状态快照对象 </summary>
public abstract object GetState();
public abstract object GetState();
/// <summary> 获得模拟器核心中的状态快照字节数据 </summary>
public abstract byte[] GetStateBytes();
public abstract byte[] GetStateBytes();
/// <summary> 加载状态快照 </summary>
/// <param name="state">该对象应该来自核心的<see cref="GetState"/>方法的返回值,或是从<see cref="GetStateBytes"/>返回的byte数组构建</param>
public abstract void LoadState(object state);
/// <param name="state">该对象应该来自核心的<see cref="GetState"/>方法的返回值,或是从<see cref="GetStateBytes"/>返回的byte数组构建</param>
public abstract void LoadState(object state);
/// <summary> 加载状态快照 </summary>
/// <param name="data">该对象应该来自核心的<see cref="GetStateBytes"/>返回的byte数组</param>
public abstract void LoadStateFromBytes(byte[] data);
/// <summary> 暂停核心推帧 </summary>
public abstract void Pause();
/// <summary> 恢复核心推帧(从Pause状态恢复) </summary>
public abstract void Resume();
/// <summary> 启动模拟器逻辑 </summary>
public abstract MsgBool StartGame(RomFile romFile);
/// <summary> 释放模拟器核心 </summary>
public abstract void Dispose();
/// <summary> 重置核心,通常由模拟器核心提供的功能 </summary>
/// <param name="data">该对象应该来自核心的<see cref="GetStateBytes"/>返回的byte数组</param>
public abstract void LoadStateFromBytes(byte[] data);
/// <summary> 暂停核心推帧 </summary>
public abstract void Pause();
/// <summary> 恢复核心推帧(从Pause状态恢复) </summary>
public abstract void Resume();
/// <summary> 启动模拟器逻辑 </summary>
public abstract MsgBool StartGame(RomFile romFile);
/// <summary> 释放模拟器核心 </summary>
public abstract void Dispose();
/// <summary> 重置核心,通常由模拟器核心提供的功能 </summary>
public abstract void DoReset();
/// <summary> 获得模拟器核心的控制器设置器 </summary>
/// <returns></returns>
public abstract IControllerSetuper GetControllerSetuper();
/// <summary> 核心所属平台 </summary>
public abstract RomPlatformType Platform { get; }
public abstract RomPlatformType Platform { get; }
/// <summary> 获取当前模拟器帧序号,在加载快照和Reset后,应当重置为0 </summary>
public abstract uint Frame { get; }
public abstract void PushEmulatorFrame();
public abstract uint Frame { get; }
public abstract void PushEmulatorFrame();
/// <summary> 模拟器核心推帧结束 </summary>
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; }
/// <summary> 指示该游戏实例是否处于联机模式 </summary>
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;
}
}
/// <summary> 指示该游戏实例是否处于联机模式 </summary>
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;
}
}
}
/// <typeparam name="INPUTDATA">输入数据类型</typeparam>
public abstract class EmuCore<INPUTDATA> : 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);
/// <summary> 模拟器核心推帧 </summary>
protected abstract bool OnPushEmulatorFrame(INPUTDATA InputData);
}
}
}
}

View File

@ -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<ulong>
{
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<RomInfo> HadGameList = new List<RomInfo>();
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<Text>();
mCanvas = GameObject.Find("Canvas").GetComponent<Canvas>();
mCanvas.worldCamera = Camera.main;
emu = new MAMEEmu();
mUniLog = new UniLog();
mUniMouse = this.gameObject.AddComponent<UniMouse>();
mUniVideoPlayer = this.gameObject.AddComponent<UniVideoPlayer>();
mUniSoundPlayer = GameObject.Find("Audio").transform.GetComponent<UniSoundPlayer>();
mUniKeyboard = this.gameObject.AddComponent<UniKeyboard>();
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<ulong>
{
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<RomInfo> HadGameList = new List<RomInfo>();
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<Text>();
mCanvas = GameObject.Find("Canvas").GetComponent<Canvas>();
mCanvas.worldCamera = Camera.main;
emu = new MAMEEmu();
mUniLog = new UniLog();
mUniMouse = this.gameObject.AddComponent<UniMouse>();
mUniVideoPlayer = this.gameObject.AddComponent<UniVideoPlayer>();
mUniSoundPlayer = GameObject.Find("Audio").transform.GetComponent<UniSoundPlayer>();
mUniKeyboard = this.gameObject.AddComponent<UniKeyboard>();
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<ulong>
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();
}

View File

@ -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<string> 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<string> 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<uint> s_temp = new HashSet<uint>();
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);
}
}
/// <summary>
/// MAME控制器
/// </summary>
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<uint> s_temp = new HashSet<uint>();
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);
}
}
/// <summary>
/// MAME控制器
/// </summary>
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;
/// <summary>
/// 指示该手柄连接的手柄插槽
/// <para><c>这个值代表了该手柄在实际游戏中控制的Player</c></para>
/// <value>[0,3] 例外:为空代表未连接</value>
/// </summary>
public uint? ConnectSlot
{
get { return mConnectSlot; }
set { mConnectSlot = value; this.ResetTargetMotionKey(); }
}
/// <summary>
/// 控制器编号
/// <para><c>此编号并非对应游戏中的player1,player2,player3,player4,仅仅作为本地4个手柄的实例</c></para>
/// <value>[0,3]</value>
/// </summary>
public int ControllerIndex
{
get { return mControllerIndex; }
private MAMEKeyBinding m_keyMapper;
int mControllerIndex;
uint? mConnectSlot;
/// <summary>
/// 指示该手柄连接的手柄插槽
/// <para><c>这个值代表了该手柄在实际游戏中控制的Player</c></para>
/// <value>[0,3] 例外:为空代表未连接</value>
/// </summary>
public uint? ConnectSlot
{
get { return mConnectSlot; }
set { mConnectSlot = value; this.ResetTargetMotionKey(); }
}
/// <summary>
/// 控制器编号
/// <para><c>此编号并非对应游戏中的player1,player2,player3,player4,仅仅作为本地4个手柄的实例</c></para>
/// <value>[0,3]</value>
/// </summary>
public int ControllerIndex
{
get { return mControllerIndex; }
set
{
mControllerIndex = value;
//this.LoadControlKeyForConfig();
//走统一配置
}
}
public MameSingleConoller(int controllerIndex)
{
ControllerIndex = controllerIndex;
m_keyMapper = App.settings.KeyMapper.GetBinder<MAMEKeyBinding>(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<MAMEKeyBinding>(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;
}
}
}

View File

@ -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<TextAsset>("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<RomDB>("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<TextAsset>("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<RomDB>("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;
}
}
}

View File

@ -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<ControllerState>
{
public VideoProvider VideoProvider;
public AudioProvider AudioProvider;
//模拟器核心实例化对象
public NES NesCore { get; private set; }
/// <summary> 是否暂停 </summary>
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;
/// <summary>
/// 指定ROM开始游戏
/// </summary>
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();
}
/// <summary>
/// 获取即时存档
/// </summary>
/// <returns></returns>
public override byte[] GetStateBytes()
{
return NesCore.GetState().ToBytes();
}
/// <summary>
/// 加载即时存档
/// </summary>
/// <param
/// name="data">
/// </param>
public override void LoadStateFromBytes(byte[] data)
{
var st = new State();
st.FromByte(data);
NesCore.LoadState(st);
}
public override uint Frame => NesCore.FrameCount;
/// <summary>
/// 停止游戏
/// </summary>
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<ControllerState>
{
public VideoProvider VideoProvider;
public AudioProvider AudioProvider;
//模拟器核心实例化对象
public NES NesCore { get; private set; }
/// <summary> 是否暂停 </summary>
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;
/// <summary>
/// 指定ROM开始游戏
/// </summary>
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();
}
/// <summary>
/// 获取即时存档
/// </summary>
/// <returns></returns>
public override byte[] GetStateBytes()
{
return NesCore.GetState().ToBytes();
}
/// <summary>
/// 加载即时存档
/// </summary>
/// <param
/// name="data">
/// </param>
public override void LoadStateFromBytes(byte[] data)
{
var st = new State();
st.FromByte(data);
NesCore.LoadState(st);
}
public override uint Frame => NesCore.FrameCount;
/// <summary>
/// 停止游戏
/// </summary>
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
/// <summary>
/// 编辑器用
/// </summary>
[Conditional("UNITY_EDITOR")]
[ContextMenu("ImportNesDB")]
public void ImportNesDB()
{
var db = Resources.Load<RomDB>("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
/// <summary>
/// 编辑器用
/// </summary>
[Conditional("UNITY_EDITOR")]
[ContextMenu("ImportNesDB")]
public void ImportNesDB()
{
var db = Resources.Load<RomDB>("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
}
}

View File

@ -1,73 +1,73 @@
namespace AxibugEmuOnline.Client.Event
{
public enum EEvent
{
// 添加你自己需要的事件类型
/// <summary>
/// 登录成功
/// </summary>
OnLoginSucceed,
namespace AxibugEmuOnline.Client.Event
{
public enum EEvent
{
// 添加你自己需要的事件类型
/// <summary>
/// 登录成功
/// </summary>
OnLoginSucceed,
/// <summary>
/// 当登录被置为false时
/// </summary>
OnLossLoginState,
/// <summary>
/// 登录失败
/// </summary>
OnLoginFailed,
OnChatMsg,
//自己的信息更新(比如改名更新)
OnSelfInfoUpdate,
//更新其他用户信息
OnOtherUserInfoUpdate,
//用户列表,登录和离开
OnUserListAllUpdate,
OnUserLogin,
OnUserLoginOut,
OnRoomListAllUpdate,//房间列表全量刷新
OnRoomListSingleAdd,//房间列表中新增房间
OnRoomListSingleUpdate,//房间列表中单个更新
OnRoomListSingleClose,//房间关闭
OnRoomGetRoomScreen,//获取到房间数据
/// <summary>
/// 我的房间创建成功
/// </summary>
OnMineRoomCreated,
/// <summary>
/// 我进入房间
/// </summary>
OnMineJoinRoom,
/// <summary>
/// 我离开房间
/// </summary>
OnMineLeavnRoom,
/// <summary>
/// 其他人进入房间
/// </summary>
OnOtherPlayerJoinRoom,
/// <summary>
/// 其他人离开房间
/// </summary>
OnOtherPlayerLeavnRoom,
/// <summary>
/// 服务器等待Step更新
/// </summary>
/// </summary>
OnLossLoginState,
/// <summary>
/// 登录失败
/// </summary>
OnLoginFailed,
OnChatMsg,
//自己的信息更新(比如改名更新)
OnSelfInfoUpdate,
//更新其他用户信息
OnOtherUserInfoUpdate,
//用户列表,登录和离开
OnUserListAllUpdate,
OnUserLogin,
OnUserLoginOut,
OnRoomListAllUpdate,//房间列表全量刷新
OnRoomListSingleAdd,//房间列表中新增房间
OnRoomListSingleUpdate,//房间列表中单个更新
OnRoomListSingleClose,//房间关闭
OnRoomGetRoomScreen,//获取到房间数据
/// <summary>
/// 我的房间创建成功
/// </summary>
OnMineRoomCreated,
/// <summary>
/// 我进入房间
/// </summary>
OnMineJoinRoom,
/// <summary>
/// 我离开房间
/// </summary>
OnMineLeavnRoom,
/// <summary>
/// 其他人进入房间
/// </summary>
OnOtherPlayerJoinRoom,
/// <summary>
/// 其他人离开房间
/// </summary>
OnOtherPlayerLeavnRoom,
/// <summary>
/// 服务器等待Step更新
/// </summary>
OnRoomWaitStepChange,
/// <summary>
/// 当房间中手柄位信息发生任何变化时触发,进入房间后也应该触发
/// </summary>
/// <summary>
/// 当房间中手柄位信息发生任何变化时触发,进入房间后也应该触发
/// </summary>
OnRoomSlotDataChanged,
/// <summary>
/// 当手柄连接设置发生变化时触发
@ -92,5 +92,5 @@
/// 网络即时存档删除
/// </summary>
OnNetGameSavDeleted,
}
}
}
}

View File

@ -1,66 +1,66 @@
using AxibugEmuOnline.Client.ClientCore;
using AxibugEmuOnline.Client.Event;
using AxibugProtobuf;
using UnityEngine;
namespace AxibugEmuOnline.Client.Manager
{
public class AppEmu
{
/// <summary>
/// unity的c#实现有bug,以接口类型保存的monobehaviour引用,!=和==运算符没有调用到monobehaviour重写过的运算符
/// 但是Equals方法可以,所以,这个接口判断为空请使用Equals
/// </summary>
private EmuCore m_emuCore;
private IControllerSetuper m_controllerSetuper;
/// <summary>
/// unity的c#实现有bug,以接口类型保存的monobehaviour引用,!=和==运算符没有调用到monobehaviour重写过的运算符
/// 但是Equals方法可以,所以,这个接口判断为空请使用Equals
/// </summary>
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<GameObject>("NES/NesEmulator")).GetComponent<EmuCore>();
using AxibugEmuOnline.Client.ClientCore;
using AxibugEmuOnline.Client.Event;
using AxibugProtobuf;
using UnityEngine;
namespace AxibugEmuOnline.Client.Manager
{
public class AppEmu
{
/// <summary>
/// unity的c#实现有bug,以接口类型保存的monobehaviour引用,!=和==运算符没有调用到monobehaviour重写过的运算符
/// 但是Equals方法可以,所以,这个接口判断为空请使用Equals
/// </summary>
private EmuCore m_emuCore;
private IControllerSetuper m_controllerSetuper;
/// <summary>
/// unity的c#实现有bug,以接口类型保存的monobehaviour引用,!=和==运算符没有调用到monobehaviour重写过的运算符
/// 但是Equals方法可以,所以,这个接口判断为空请使用Equals
/// </summary>
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<GameObject>("NES/NesEmulator")).GetComponent<EmuCore>();
break;
case RomPlatformType.Cps1:
case RomPlatformType.Cps2:
case RomPlatformType.Igs:
case RomPlatformType.Neogeo:
case RomPlatformType.ArcadeOld:
m_emuCore = GameObject.Instantiate(Resources.Load<GameObject>("MAME/UMAME")).GetComponent<EmuCore>();
case RomPlatformType.ArcadeOld:
m_emuCore = GameObject.Instantiate(Resources.Load<GameObject>("MAME/UMAME")).GetComponent<EmuCore>();
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<GameObject>("EssgeeUnity/EssgeeUnity")).GetComponent<EmuCore>();
case RomPlatformType.Sg1000:
m_emuCore = GameObject.Instantiate(Resources.Load<GameObject>("EssgeeUnity/EssgeeUnity")).GetComponent<EmuCore>();
break;
case RomPlatformType.WonderSwan:
case RomPlatformType.WonderSwan:
case RomPlatformType.WonderSwanColor:
m_emuCore = GameObject.Instantiate(Resources.Load<GameObject>("StoicGooseUnity/StoicGooseUnity")).GetComponent<EmuCore>();
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();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +1,24 @@
using AxibugEmuOnline.Client.Settings;
namespace AxibugEmuOnline.Client
{
public class AppSettings
{
/// <summary> 背景颜色设定 </summary>
public BgColorSettings BgColor { get; private set; }
/// <summary> 滤镜设置 </summary>
public FilterManager Filter { get; private set; }
/// <summary> 画面比例设置 </summary>
using AxibugEmuOnline.Client.Settings;
namespace AxibugEmuOnline.Client
{
public class AppSettings
{
/// <summary> 背景颜色设定 </summary>
public BgColorSettings BgColor { get; private set; }
/// <summary> 滤镜设置 </summary>
public FilterManager Filter { get; private set; }
/// <summary> 画面比例设置 </summary>
public ScreenScaler ScreenScaler { get; private set; }
/// <summary> 键位设置 </summary>
/// <summary> 键位设置 </summary>
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();
}
}
}

View File

@ -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);
}
}
}

View File

@ -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<EditableParamerter> EditableParam => m_editableParamList.AsReadOnly();
List<EditableParamerter> 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<EditableParamerter> EditableParam => m_editableParamList.AsReadOnly();
List<EditableParamerter> 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<EditableParamerter>();
foreach (var param in parameters)
{
var paramObj = (FilterParameter)param.GetValue(this);
var rangeAtt = param.GetCustomAttribute<RangeAttribute>();
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<EditableParamerter>();
foreach (var param in parameters)
{
var paramObj = (FilterParameter)param.GetValue(this);
var rangeAtt = param.GetCustomAttribute<RangeAttribute>();
float min = 0;
float max = 10;
if (rangeAtt != null) { min = rangeAtt.min; max = rangeAtt.max; }
var descrip = param.GetCustomAttribute<DescriptionAttribute>();
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<DescriptionAttribute>();
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<RuntimePlatform> m_stripPlats;
/// <summary>
/// 指示一个滤镜是否会在指定的平台被剔除
/// </summary>
/// <param name="strip">会被剔除的平台</param>
public StripAttribute(params RuntimePlatform[] stripPlatform)
{
m_stripPlats = new HashSet<RuntimePlatform>(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<RuntimePlatform> m_stripPlats;
/// <summary>
/// 指示一个滤镜是否会在指定的平台被剔除
/// </summary>
/// <param name="strip">会被剔除的平台</param>
public StripAttribute(params RuntimePlatform[] stripPlatform)
{
m_stripPlats = new HashSet<RuntimePlatform>(stripPlatform);
}
public bool NeedStrip => m_stripPlats.Contains(Application.platform);
}
}
}

View File

@ -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;
/// <summary>
/// 滤镜列表
/// </summary>
/// <summary>
/// 滤镜列表
/// </summary>
public IReadOnlyList<Filter> Filters => m_filters;
public FilterManager()
@ -104,24 +104,24 @@ namespace AxibugEmuOnline.Client.Settings
}
/// <summary> 关闭滤镜预览 </summary>
/// <summary> 关闭滤镜预览 </summary>
public void ShutDownFilterPreview()
{
if (m_previewFilterWraper == null) m_previewFilterWraper = new AlphaWraper(Initer.XMBBg, Initer.FilterPreview, false);
m_previewFilterWraper.On = false;
}
/// <summary> 开启滤镜预览 </summary>
/// <summary> 开启滤镜预览 </summary>
public void EnableFilterPreview()
{
if (m_previewFilterWraper == null) m_previewFilterWraper = new AlphaWraper(Initer.XMBBg, Initer.FilterPreview, false);
m_previewFilterWraper.On = true;
}
/// <summary>
/// 打开滤镜
/// </summary>
/// <param name="filter"></param>
/// <summary>
/// 打开滤镜
/// </summary>
/// <param name="filter"></param>
public void EnableFilter(Filter filter)
{
foreach (var selfFiler in Filters)
@ -131,9 +131,9 @@ namespace AxibugEmuOnline.Client.Settings
}
}
/// <summary>
/// 关闭滤镜效果
/// </summary>
/// <summary>
/// 关闭滤镜效果
/// </summary>
public void ShutDownFilter()
{
//关闭所有后处理效果
@ -141,12 +141,12 @@ namespace AxibugEmuOnline.Client.Settings
filter.m_setting.Enable = false;
}
/// <summary>
/// 为指定rom设置滤镜以及滤镜的预设
/// </summary>
/// <param name="rom">rom对象</param>
/// <param name="filter">滤镜</param>
/// <param name="preset">滤镜预设</param>
/// <summary>
/// 为指定rom设置滤镜以及滤镜的预设
/// </summary>
/// <param name="rom">rom对象</param>
/// <param name="filter">滤镜</param>
/// <param name="preset">滤镜预设</param>
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);
}
/// <summary>
/// 获得指定rom配置的滤镜设置
/// </summary>
/// <param name="rom">rom对象</param>
/// <returns>此元组任意内任意成员都有可能为空</returns>
/// <summary>
/// 获得指定rom配置的滤镜设置
/// </summary>
/// <param name="rom">rom对象</param>
/// <returns>此元组任意内任意成员都有可能为空</returns>
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<EditableParamerter> Paramerters => m_setting.EditableParam;
/// <summary> 滤镜预设 </summary>
/// <summary> 滤镜预设 </summary>
public List<FilterPreset> Presets = new List<FilterPreset>();
/// <summary> 滤镜默认预设 </summary>
/// <summary> 滤镜默认预设 </summary>
public FilterPreset DefaultPreset = new FilterPreset("DEFAULT");
internal FilterEffect m_setting;
@ -445,5 +445,5 @@ namespace AxibugEmuOnline.Client.Settings
public string PresetName;
}
}
}
}
}
}

View File

@ -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<T> : 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<T> : 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<T> value)
@ -38,26 +38,26 @@ namespace Assets.Script.AppMain.Filter
public static implicit operator FilterParameter<T>(T value)
{
return new FilterParameter<T>(value);
}
}
public class BoolParameter : FilterParameter<bool>
{
public BoolParameter(bool defaultValue) : base(defaultValue) { }
}
}
public class BoolParameter : FilterParameter<bool>
{
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<Vector2>
{
}
}
public class Vector2Parameter : FilterParameter<Vector2>
{
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<float>
{
public FloatParameter(float defaultValue) : base(defaultValue) { }
}
}
public class FloatParameter : FilterParameter<float>
{
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<int>
{
public IntParameter(int defaultValue) : base(defaultValue) { }
@ -99,5 +99,5 @@ namespace Assets.Script.AppMain.Filter
{
return new IntParameter(value);
}
}
}
}

View File

@ -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);
}
}
}

View File

@ -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<EnumQuality> Quality = new FilterParameter<EnumQuality>(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
}
}
}
}

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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

View File

@ -16,7 +16,8 @@ public abstract class EmuCoreBinder<T> : InternalEmuCoreBinder,
IDeviceBinder<T, DualShockController_D>,
IDeviceBinder<T, XboxController_D>,
IDeviceBinder<T, PSVController_D>,
IDeviceBinder<T, ScreenGamepad_D>
IDeviceBinder<T, ScreenGamepad_D>,
IDeviceBinder<T, SwitchJoyCon_D>
where T : Enum
{
//每一个实例代表一个对应模拟器平台的控制器索引
@ -83,6 +84,7 @@ public abstract class EmuCoreBinder<T> : 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<T> : 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);
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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<Sprite, string> callback)
{
GetCacheData(url, TextureCacheDirPath, callback);
}
/// <summary> 移除文件缓存 </summary>
public void ClearCaches()
{
if (AxiIO.Directory.Exists(CacheDirPath))
AxiIO.Directory.Delete(CacheDirPath, true);
}
IEnumerator DownloadFromURL(string url, string path, Action<byte[]> 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<Sprite, string> 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);
}
/// <summary> 移除文件缓存 </summary>
public void ClearCaches()
{
if (AxiIO.Directory.Exists(CacheDirPath))
AxiIO.Directory.Delete(CacheDirPath, true);
}
IEnumerator DownloadFromURL(string url, string path, Action<byte[]> 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<string, object> cachesInMemory = new Dictionary<string, object>();
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<string, object> cachesInMemory = new Dictionary<string, object>();
void GetCacheData<T>(string url, string path, Action<T, string> 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<T>(rawData);
cachesInMemory[url] = @out;
callback.Invoke(@out, url);
}
else
{
App.StartCoroutine(DownloadFromURL(url, path, (data) =>
{
var @out = RawDataConvert<T>(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<T>(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<T>(rawData);
cachesInMemory[url] = @out;
callback.Invoke(@out, url);
}
else
{
App.StartCoroutine(DownloadFromURL(url, path, (data) =>
{
var @out = RawDataConvert<T>(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<T>(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<Sprite>("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}");
}
}
}

View File

@ -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<int, Resp_GameList> 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<int, Resp_GameList> callback, AxibugProtobuf.RomPlatformType Platform, int page, int pageSize = 10);
public delegate void SearchRomListAPI(Action<int, Resp_GameList> callback, AxibugProtobuf.RomPlatformType Platform, string searchKey, int page, int pageSize = 10);
public delegate void GetStarRomListAPI(Action<int, Resp_GameList> callback, AxibugProtobuf.RomPlatformType platform, int page, int pageSize = 10);
public void GetRomList(Action<int, Resp_GameList> callback, AxibugProtobuf.RomPlatformType platform, int page, int pageSize = 10)
{
App.StartCoroutine(GetRomListFlow(platform, page, pageSize, callback));
}
public void SearchRomList(Action<int, Resp_GameList> 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<int, Resp_GameList> 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<Resp_GameList>(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<int, Resp_GameList> 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<Resp_GameList>(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<int, Resp_GameList> callback, AxibugProtobuf.RomPlatformType platform, int page, int pageSize = 10)
{
App.StartCoroutine(GetRomListFlow(platform, page, pageSize, callback));
}
public void SearchRomList(Action<int, Resp_GameList> 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<int, Resp_GameList> 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<Resp_GameList>(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<int, Resp_GameList> 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<Resp_GameList>(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<int, Resp_GameList> callback, AxibugProtobuf.RomPlatformType platform, int page, int pageSize = 10)
{
App.StartCoroutine(GetMarkListFlow(platform, page, pageSize, callback));
}
public void SearchMarkList(Action<int, Resp_GameList> 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<int, Resp_GameList> 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<Resp_GameList>(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<int, Resp_GameList> 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<Resp_GameList>(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<Resp_RomInfo> 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<Resp_RomInfo>(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,
/// <summary>
/// 合卡
/// </summary>
ALLINONE,
}
[Serializable]
public class Resp_GameList
{
public int page;
public int maxPage;
public int resultAllCount;
public List<Resp_RomInfo> gameList;
}
[Serializable]
public class Resp_RomInfo
{
public void GetMarkList(Action<int, Resp_GameList> callback, AxibugProtobuf.RomPlatformType platform, int page, int pageSize = 10)
{
App.StartCoroutine(GetMarkListFlow(platform, page, pageSize, callback));
}
public void SearchMarkList(Action<int, Resp_GameList> 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<int, Resp_GameList> 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<Resp_GameList>(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<int, Resp_GameList> 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<Resp_GameList>(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<Resp_RomInfo> 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<Resp_RomInfo>(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,
/// <summary>
/// 合卡
/// </summary>
ALLINONE,
}
[Serializable]
public class Resp_GameList
{
public int page;
public int maxPage;
public int resultAllCount;
public List<Resp_RomInfo> 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;
/// <summary>
/// 游玩计数
/// </summary>
public int playcount;
public int playcount;
/// <summary>
/// 是否收藏
/// </summary>
/// </summary>
public int isStar;
public List<int> parentRomIdsList;
}
[Serializable]
public class Resp_CheckStandInfo
{
public int needUpdateClient;
public string serverIp;
public ushort serverPort;
public string clientVersion;
public string downLoadUrl;
}
}
}
public List<int> parentRomIdsList;
}
[Serializable]
public class Resp_CheckStandInfo
{
public int needUpdateClient;
public string serverIp;
public ushort serverPort;
public string clientVersion;
public string downLoadUrl;
}
}
}

View File

@ -73,32 +73,48 @@ namespace AxibugEmuOnline.Client.InputDevices
{
return m_devices.Values;
}
List<string> templog = new List<string>();
/// <summary> 由外部驱动的逻辑更新入口 </summary>
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}");
//}
}
}
}

View File

@ -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;
/// <summary> 依赖的Rom文件 </summary>
private List<RomFile> dependencies = new List<RomFile>();
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;
/// <summary> 依赖的Rom文件 </summary>
private List<RomFile> dependencies = new List<RomFile>();
RomPlatformType m_defaultPlatform;
/// <summary> 指示该Rom是否是多文件Rom </summary>
/// <summary> 指示该Rom是否是多文件Rom </summary>
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;
}
}
/// <summary> 指示该Rom文件的存放路径 </summary>
public string LocalFilePath => $"{App.PersistentDataPath(Platform)}/RemoteRoms/{FileName}";
/// <summary> 指示该Rom文件是否已下载完毕 </summary>
}
/// <summary> 指示该Rom文件的存放路径 </summary>
public string LocalFilePath => $"{App.PersistentDataPath(Platform)}/RemoteRoms/{FileName}";
/// <summary> 指示该Rom文件是否已下载完毕 </summary>
public bool RomReady
{
get
@ -99,8 +99,8 @@ namespace AxibugEmuOnline.Client
return true;
}
}
/// <summary> 指示是否正在下载Rom文件 </summary>
}
/// <summary> 指示是否正在下载Rom文件 </summary>
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;
/// <summary> 指示该Rom信息是否已填充 </summary>
}
public RomPlatformType Platform => webData != null ? (RomPlatformType)webData.ptype : m_defaultPlatform;
/// <summary> 指示该Rom信息是否已填充 </summary>
public bool InfoReady
{
get
@ -158,23 +158,23 @@ namespace AxibugEmuOnline.Client
return true;
}
}
/// <summary> 唯一标识 </summary>
public int ID => webData != null ? webData.id : -1;
/// <summary> 别名 </summary>
public string Alias => webData.romName;
/// <summary> 描述 </summary>
public string Descript => webData.desc;
/// <summary> 游戏类型 </summary>
public string GameTypeDes => webData.gType;
/// <summary> 小图URL </summary>
public string ImageURL => webData.imgUrl;
/// <summary> 文件名 </summary>
public string FileName { get; private set; }
/// <summary> 在查询结果中的索引 </summary>
public int Index { get; private set; }
/// <summary> 在查询结果中的所在页 </summary>
}
/// <summary> 唯一标识 </summary>
public int ID => webData != null ? webData.id : -1;
/// <summary> 别名 </summary>
public string Alias => webData.romName;
/// <summary> 描述 </summary>
public string Descript => webData.desc;
/// <summary> 游戏类型 </summary>
public string GameTypeDes => webData.gType;
/// <summary> 小图URL </summary>
public string ImageURL => webData.imgUrl;
/// <summary> 文件名 </summary>
public string FileName { get; private set; }
/// <summary> 在查询结果中的索引 </summary>
public int Index { get; private set; }
/// <summary> 在查询结果中的所在页 </summary>
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<RomFile> OnDownloadOver;
public event Action OnInfoFilled;
public RomFile(int index, int insidePage, RomPlatformType defaultPlatform)
{
Index = index;
Page = insidePage;
m_defaultPlatform = defaultPlatform;
}
public event Action<RomFile> 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<string> depth0Files = new List<string>();
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();
}
}
}
}
}
}

View File

@ -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
{
/// <summary> Rom请求,一页的大小 </summary>
/// <summary> Rom请求,一页的大小 </summary>
private const int PAGE_SIZE = 10;
/// <summary> 请求指令 </summary>
/// <summary> 请求指令 </summary>
private HashSet<int> FetchPageCmd = new HashSet<int>();
private RomFile[] RomFetchList;
private Dictionary<int, RomFile> RomFileIdMapper = new Dictionary<int, RomFile>();
@ -57,23 +57,23 @@ namespace AxibugEmuOnline.Client
return romFile;
}
/// <summary> 清除所有下载的Rom文件 </summary>
/// <summary> 清除所有下载的Rom文件 </summary>
public void ClearRomFile()
{
var path = $"{App.PersistentDataPath(m_platform)}/RemoteRoms";
if (AxiIO.Directory.Exists(path)) AxiIO.Directory.Delete(path, true);
}
/// <summary> 移除一个已下载的Rom </summary>
/// <summary> 移除一个已下载的Rom </summary>
public void RemoveOneRomFile(RomFile romFile)
{
if (romFile.RomReady)
AxiIO.File.Delete(romFile.LocalFilePath);
}
/// <summary>
/// 获得所有Rom文件
/// </summary>
/// <summary>
/// 获得所有Rom文件
/// </summary>
public void FetchRomCount(Action<RomFile[]> callback, string searchKey = null)
{
lastSearchKey = searchKey;
@ -186,5 +186,5 @@ namespace AxibugEmuOnline.Client
{
RomFileNameMapper[rom.FileName] = rom;
}
}
}
}
}

View File

@ -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
{
/// <summary>
/// 负责存档的云端保存和获取功能
/// </summary>
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<int> m_fetchingRomIDs = new HashSet<int>();
/// <summary>
/// 发送请求即时存档列表
/// </summary>
/// <param name="RomID"></param>
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)
{
/// </summary>
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<int> m_fetchingRomIDs = new HashSet<int>();
/// <summary>
/// 发送请求即时存档列表
/// </summary>
/// <param name="RomID"></param>
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<Protobuf_Mine_GetGameSavList_RESP>(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);
}
/// <summary>
/// 发送删除即时存档
/// </summary>
/// <param name="RomID"></param>
/// <param name="SavDataIdx"></param>
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<Protobuf_Mine_DelGameSav_RESP>(reqData);
Eventer.Instance.PostEvent(EEvent.OnNetGameSavDeleted, msg.RomID, msg.SavDataIdx);
}
/// <summary>
/// 上传即时存档
/// </summary>
/// <param name="RomID"></param>
/// <param name="SavDataIdx"></param>
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);
}
/// <summary>
/// 发送删除即时存档
/// </summary>
/// <param name="RomID"></param>
/// <param name="SavDataIdx"></param>
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<Protobuf_Mine_DelGameSav_RESP>(reqData);
Eventer.Instance.PostEvent(EEvent.OnNetGameSavDeleted, msg.RomID, msg.SavDataIdx);
}
/// <summary>
/// 上传即时存档
/// </summary>
/// <param name="RomID"></param>
/// <param name="SavDataIdx"></param>
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<Protobuf_Mine_UpLoadGameSav_RESP>(reqData);
OnUploadedSavData?.Invoke(msg.RomID, msg.SavDataIdx, msg.UploadSevInfo);
}
/// <summary>
/// 即时存档或网络截图下载完成之后,需要先解压再使用
/// </summary>
/// <returns></returns>
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<Protobuf_Mine_UpLoadGameSav_RESP>(reqData);
OnUploadedSavData?.Invoke(msg.RomID, msg.SavDataIdx, msg.UploadSevInfo);
}
/// <summary>
/// 即时存档或网络截图下载完成之后,需要先解压再使用
/// </summary>
/// <returns></returns>
public byte[] UnGzipData(byte[] data)
{
return Helper.DecompressByteArray(data);
}
}
}

View File

@ -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

View File

@ -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<SyncFailedState>().Error = m_downloadTaskImg.downloadHandler.ErrInfo;
FSM.ChangeState<SyncFailedState>();
FSM.ChangeState<IdleState>();
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<SyncedState>();
}
catch
{
FSM.GetState<SyncFailedState>().Error = "云存档解压失败";
FSM.ChangeState<SyncFailedState>();
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<SyncedState>();
}
}

View File

@ -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<long, UserDataBase> DictUID2User = new Dictionary<long, UserDataBase>();
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<long, UserDataBase> DictUID2User = new Dictionary<long, UserDataBase>();
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
//以及其他数据初始化
//...
}
/// <summary>
/// 登出
/// </summary>
public void LoginOutData()
{
userdata.IsLoggedIn = false;
//以及其他数据清理
//...
}
/// <summary>
/// 当重连成功
/// </summary>
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
/// <summary>
/// 请求拉取房间列表
/// </summary>
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<Protobuf_UserList_RESP>(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<Protobuf_UserJoin_RESP>(reqData);
bool isNewUser;
UpdateOrAddUser(msg.UserInfo, out isNewUser);
if (isNewUser)
}
/// <summary>
/// 登出
/// </summary>
public void LoginOutData()
{
userdata.IsLoggedIn = false;
//以及其他数据清理
//...
}
/// <summary>
/// 当重连成功
/// </summary>
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<Protobuf_UserLeave_RESP>(reqData);
RemoveUser(msg.UID);
}
/// <summary>
/// 发送修改昵称请求
/// </summary>
/// <param name="NickName"></param>
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<Protobuf_Modify_NickName_RESP>(reqData);
}
private void RecvUpdateSelfUserInfo(byte[] reqData)
{
Protobuf_Update_UserInfo_RESP msg = ProtoBufHelper.DeSerizlize<Protobuf_Update_UserInfo_RESP>(reqData);
userdata.NickName = msg.UserInfo.NickName;
Eventer.Instance.PostEvent(EEvent.OnSelfInfoUpdate);
}
private void RecvUpdateOtherUserInfo(byte[] reqData)
{
Protobuf_Update_OtherUserInfo_RESP msg = ProtoBufHelper.DeSerizlize<Protobuf_Update_OtherUserInfo_RESP>(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
/// <summary>
/// 请求拉取房间列表
/// </summary>
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<Protobuf_UserList_RESP>(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<Protobuf_UserJoin_RESP>(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<Protobuf_UserLeave_RESP>(reqData);
RemoveUser(msg.UID);
}
/// <summary>
/// 发送修改昵称请求
/// </summary>
/// <param name="NickName"></param>
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<Protobuf_Modify_NickName_RESP>(reqData);
}
private void RecvUpdateSelfUserInfo(byte[] reqData)
{
Protobuf_Update_UserInfo_RESP msg = ProtoBufHelper.DeSerizlize<Protobuf_Update_UserInfo_RESP>(reqData);
userdata.NickName = msg.UserInfo.NickName;
Eventer.Instance.PostEvent(EEvent.OnSelfInfoUpdate);
}
private void RecvUpdateOtherUserInfo(byte[] reqData)
{
Protobuf_Update_OtherUserInfo_RESP msg = ProtoBufHelper.DeSerizlize<Protobuf_Update_OtherUserInfo_RESP>(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);
}
}
}

View File

@ -1,39 +1,39 @@
/// <summary>
/// String和Bool的缝合怪
/// </summary>
public struct MsgBool
{
public string ErrorMsg;
/// <summary>
/// String和Bool的缝合怪
/// </summary>
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();
}
}

View File

@ -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<int, List<Delegate>> netEventDic = new Dictionary<int, List<Delegate>>(128);
private Queue<ValueTuple<int, int, byte[]>> queueNetMsg = new Queue<ValueTuple<int, int, byte[]>>();
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<Action> queueEventFromNet = new Queue<Action>();
namespace AxibugEmuOnline.Client.Network
{
public class NetMsg
{
private static NetMsg instance = new NetMsg();
public static NetMsg Instance { get { return instance; } }
private Dictionary<int, List<Delegate>> netEventDic = new Dictionary<int, List<Delegate>>(128);
private Queue<ValueTuple<int, int, byte[]>> queueNetMsg = new Queue<ValueTuple<int, int, byte[]>>();
public static object lockQueueNetMsg = new object();
private Queue<Action> queueEventFromNet = new Queue<Action>();
public static object lockQueueEventFromNet = new object();
private NetMsg() { }
#region RegisterMsgEvent
public void RegNetMsgEvent(int cmd, Action<byte[]> 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<Delegate>() { callback });
}
}
#endregion
#region UnregisterCMD
public void UnregisterCMD(int evt, Action<byte[]> 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<byte[]> 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<Delegate>() { callback });
}
}
#endregion
#region UnregisterCMD
public void UnregisterCMD(int evt, Action<byte[]> 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<int, int, byte[]>(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<int, int, byte[]>(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<Delegate> eventList = GetNetEventDicList(cmd);
if (eventList != null)
{
foreach (Delegate callback in eventList)
{
try
{
((Action<byte[]>)callback)(arg);
}
catch (Exception e)
{
App.log.Error(e.ToString());
}
}
}
}
#endregion
/// <summary>
/// 获取所有事件
/// </summary>
/// <param name="cmd"></param>
/// <returns></returns>
private List<Delegate> GetNetEventDicList(int cmd)
{
if (netEventDic.ContainsKey(cmd))
{
List<Delegate> 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<Delegate> eventList = GetNetEventDicList(cmd);
if (eventList != null)
{
foreach (Delegate callback in eventList)
{
try
{
((Action<byte[]>)callback)(arg);
}
catch (Exception e)
{
App.log.Error(e.ToString());
}
}
}
}
#endregion
/// <summary>
/// 获取所有事件
/// </summary>
/// <param name="cmd"></param>
/// <returns></returns>
private List<Delegate> GetNetEventDicList(int cmd)
{
if (netEventDic.ContainsKey(cmd))
{
List<Delegate> tempList = netEventDic[cmd];
if (null != tempList)
{
return tempList;
}
}
return null;
}
}
}

View File

@ -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;
}

View File

@ -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<object> list = new List<object>();
}
protected override void GetVirtualListDatas(VirtualListDataHandle callback)
{
List<object> list = new List<object>();
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);
}
}
}

View File

@ -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
{
/// <summary>
/// 背景颜色设置UI
/// </summary>
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
{
/// <summary>
/// 背景颜色设置UI
/// </summary>
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<Material>("Materials/XMBBackGroundPreview"));
ui.IconUI.GetMaterial().SetColor("_Color1", Color.color1);
ui.IconUI.GetMaterial().SetColor("_Color2", Color.color2);
}
private static TweenerCore<float, float, FloatOptions> 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<Material>("Materials/XMBBackGroundPreview"));
ui.IconUI.GetMaterial().SetColor("_Color1", Color.color1);
ui.IconUI.GetMaterial().SetColor("_Color2", Color.color2);
}
private static TweenerCore<float, float, FloatOptions> 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) { }
}
}
}

View File

@ -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
{
/// <summary>
/// 滤镜预览UI
/// </summary>
/// <summary>
/// 滤镜预览UI
/// </summary>
public class UI_FilterItem : MenuItem, IVirtualItem
{
public int Index { get; set; }
@ -199,5 +199,5 @@ namespace AxibugEmuOnline.Client
}
}
}
}
}

View File

@ -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
{
/// <summary>
/// 画面比例模式选项UI
/// </summary>
/// <summary>
/// 画面比例模式选项UI
/// </summary>
public class UI_ScalerModeItem : MenuItem, IVirtualItem
{
public int Index { get; set; }
@ -52,5 +52,5 @@ namespace AxibugEmuOnline.Client
{
return false;
}
}
}
}
}

View File

@ -1,118 +1,118 @@
using System.Collections.Generic;
using UnityEngine;
namespace AxibugEmuOnline.Client
{
public class CommandDispatcher : MonoBehaviour
{
public static CommandDispatcher Instance { get; private set; }
/// <summary> 平级注册对象,都会响应指令 </summary>
List<CommandExecuter> m_register = new List<CommandExecuter>();
/// <summary> 独占注册对象,指令会被列表中最后一个对象独占 </summary>
List<CommandExecuter> m_registerHigh = new List<CommandExecuter>();
CommandListener m_listener;
using System.Collections.Generic;
using UnityEngine;
namespace AxibugEmuOnline.Client
{
public class CommandDispatcher : MonoBehaviour
{
public static CommandDispatcher Instance { get; private set; }
/// <summary> 平级注册对象,都会响应指令 </summary>
List<CommandExecuter> m_register = new List<CommandExecuter>();
/// <summary> 独占注册对象,指令会被列表中最后一个对象独占 </summary>
List<CommandExecuter> m_registerHigh = new List<CommandExecuter>();
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<CommandExecuter> oneFrameRegister = new List<CommandExecuter>();
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<CommandExecuter> peekRegister(List<CommandExecuter> 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<CommandExecuter> normal, out IReadOnlyList<CommandExecuter> 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<CommandExecuter> oneFrameRegister = new List<CommandExecuter>();
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<CommandExecuter> peekRegister(List<CommandExecuter> 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<CommandExecuter> normal, out IReadOnlyList<CommandExecuter> alone)
{
normal = m_register;
alone = m_registerHigh;
}
#endif
}
}

View File

@ -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<CommandState> m_commands = new List<CommandState>();
using AxibugEmuOnline.Client.ClientCore;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace AxibugEmuOnline.Client
{
public class CommandListener
{
EnumCommand[] m_checkCmds;
List<CommandState> m_commands = new List<CommandState>();
long CheckFrame = -1;
XMBKeyBinding m_keyBinder;
public ScheduleType Schedule { get; set; }
@ -17,16 +17,16 @@ namespace AxibugEmuOnline.Client
{
m_keyBinder = App.settings.KeyMapper.GetBinder<XMBKeyBinding>();
m_checkCmds = Enum.GetValues(typeof(EnumCommand)) as EnumCommand[];
}
IEnumerable<CommandState> GetCommand()
{
if (CheckFrame == Time.frameCount)
return m_commands;
CheckFrame = Time.frameCount;
m_commands.Clear();
}
IEnumerable<CommandState> 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<CommandExecuter> 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<CommandExecuter> 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
}
}
}
}
}
}

View File

@ -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<int>(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();
}
}
}

View File

@ -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<InternalOptionMenu> m_options;
protected override void Awake()
{
base.Awake();
m_options = new List<InternalOptionMenu>()
{
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<InternalOptionMenu> m_options;
protected override void Awake()
{
base.Awake();
m_options = new List<InternalOptionMenu>()
{
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);
}
}
}
}
}
}
}

View File

@ -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<InternalOptionMenu> menus = new List<InternalOptionMenu>();
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<InternalOptionMenu> menus = new List<InternalOptionMenu>();
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();
}
/// <summary> 保存快速快照 </summary>
public void SaveQuickState(object state)
{
m_state = state;
}
/// <summary>
/// 读取快速快照
/// </summary>
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<int>(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();
}
/// <summary> 保存快速快照 </summary>
public void SaveQuickState(object state)
{
m_state = state;
}
/// <summary>
/// 读取快速快照
/// </summary>
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<int>(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<int>(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<int>(EEvent.OnRoomWaitStepChange, OnServerStepUpdate);
Eventer.Instance.UnregisterEvent(EEvent.OnLoginSucceed, OnLoggedIn);
Eventer.Instance.UnregisterEvent(EEvent.OnMineRoomCreated, OnRoomCreated);
App.roomMgr.SendLeavnRoom();
App.emu.StopGame();
}
}
}

View File

@ -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<InternalOptionMenu> GetOptionMenus()
{
List<InternalOptionMenu> menus = new List<InternalOptionMenu>();
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<InternalOptionMenu> GetOptionMenus()
{
List<InternalOptionMenu> menus = new List<InternalOptionMenu>();
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<InternalOptionMenu> m_presetsMenuItems;
}
public class FilterMenu : ExpandMenu
{
private Filter m_filter;
private List<InternalOptionMenu> 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<InternalOptionMenu> { 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<InternalOptionMenu> 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<InternalOptionMenu> { 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<InternalOptionMenu> 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);
}
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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();
}
}
}
}

View File

@ -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<SaveFile.IdleState>();
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<SaveFile.DownloadingState>();
}
}
@ -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<SaveFile.UploadingState>();
}
}

View File

@ -1,59 +1,59 @@
using System.Collections.Generic;
using UnityEngine;
public static class GameObjectPool
{
private static GameObject PoolAttach;
private static Dictionary<GameObject, Queue<GameObject>> s_poolMap = new Dictionary<GameObject, Queue<GameObject>>();
private static Dictionary<GameObject, GameObject> s_instanceToSrc = new Dictionary<GameObject, GameObject>();
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>();
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<GameObject, Queue<GameObject>> s_poolMap = new Dictionary<GameObject, Queue<GameObject>>();
private static Dictionary<GameObject, GameObject> s_instanceToSrc = new Dictionary<GameObject, GameObject>();
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>();
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<GameObject> 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);
}
}
}

View File

@ -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<GameObject, ScripteInterface> CacheItemScripts { get; }
List<object> 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();
}

View File

@ -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<Vector2, Vector2, VectorOptions> m_layoutTween;
AlphaWraper romPreviewWraper;
private void Awake()
{
Instance = this;
m_mainLayoutPosition = MainMenuRoot.anchoredPosition;
MainMenu.ListenControlAction = true;
romPreviewWraper = new AlphaWraper(XMBCG_For_RomPreviewBigPic, RomPreviewBigPic.GetComponent<CanvasGroup>(), 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<Vector2, Vector2, VectorOptions> m_layoutTween;
AlphaWraper romPreviewWraper;
private void Awake()
{
Instance = this;
m_mainLayoutPosition = MainMenuRoot.anchoredPosition;
MainMenu.ListenControlAction = true;
romPreviewWraper = new AlphaWraper(XMBCG_For_RomPreviewBigPic, RomPreviewBigPic.GetComponent<CanvasGroup>(), 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();
}
}
}

View File

@ -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<Type, OptionUI_MenuItem> m_menuUI_templates = new Dictionary<Type, OptionUI_MenuItem>();
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<OptionUI_MenuItem> m_runtimeMenuItems = new List<OptionUI_MenuItem>();
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<Type, OptionUI_MenuItem> m_menuUI_templates = new Dictionary<Type, OptionUI_MenuItem>();
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<OptionUI_MenuItem> m_runtimeMenuItems = new List<OptionUI_MenuItem>();
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<OptionUI_MenuItem>(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<Vector2, Vector2, VectorOptions> m_popTween;
private TweenerCore<Vector2, Vector2, VectorOptions> m_hideTween;
CommandListener.ScheduleType? m_lastCS;
private Action m_onClose;
/// <summary>
/// 当菜单弹出时,动态添加一个菜单选项
/// </summary>
/// <param name="menu"></param>
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<T>(List<T> 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<Vector2, Vector2, VectorOptions> m_popTween;
private TweenerCore<Vector2, Vector2, VectorOptions> m_hideTween;
CommandListener.ScheduleType? m_lastCS;
private Action m_onClose;
/// <summary>
/// 当菜单弹出时,动态添加一个菜单选项
/// </summary>
/// <param name="menu"></param>
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<T>(List<T> 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;
}
}
/// <summary>
/// 关闭这个侧边栏选项UI
/// </summary>
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;
}
/// <summary>
/// 展开下级菜单
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="menus"></param>
/// <param name="defaultIndex"></param>
/// <param name="onClose"></param>
public void ExpandSubMenu<T>(List<T> menus, int defaultIndex = 0, Action onClose = null) where T : InternalOptionMenu
{
if (m_child == null)
{
var sourcePrefab = Resources.Load<GameObject>("UIPrefabs/OptionUI");
m_child = Instantiate(sourcePrefab, transform).GetComponent<OptionUI>();
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();
}
}
/// <summary>
/// 带有执行行为的菜单
/// </summary>
public abstract class ExecuteMenu : InternalOptionMenu
{
public override Type MenuUITemplateType => typeof(OptionUI_ExecuteItem);
/// <summary> 设置这个值以控制菜单中显示"已应用"标记 </summary>
public virtual bool IsApplied { get; }
public abstract void OnExcute(OptionUI optionUI, ref bool cancelHide);
}
/// <summary>
/// 带有展开行为的可执行菜单
/// </summary>
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<InternalOptionMenu> GetOptionMenus();
App.audioMgr.PlaySFX(AudioMgr.E_SFXTYPE.Option);
return false;
}
/// <summary>
/// 展开下级菜单
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="menus"></param>
/// <param name="defaultIndex"></param>
/// <param name="onClose"></param>
public void ExpandSubMenu<T>(List<T> menus, int defaultIndex = 0, Action onClose = null) where T : InternalOptionMenu
{
if (m_child == null)
{
var sourcePrefab = Resources.Load<GameObject>("UIPrefabs/OptionUI");
m_child = Instantiate(sourcePrefab, transform).GetComponent<OptionUI>();
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();
}
}
/// <summary>
/// 带有值类型显示和编辑的菜单
/// </summary>
public abstract class ValueSetMenu : InternalOptionMenu
{
/// <summary>
/// 带有执行行为的菜单
/// </summary>
public abstract class ExecuteMenu : InternalOptionMenu
{
public override Type MenuUITemplateType => typeof(OptionUI_ExecuteItem);
/// <summary> 设置这个值以控制菜单中显示"已应用"标记 </summary>
public virtual bool IsApplied { get; }
public abstract void OnExcute(OptionUI optionUI, ref bool cancelHide);
}
/// <summary>
/// 带有展开行为的可执行菜单
/// </summary>
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<InternalOptionMenu> GetOptionMenus();
}
/// <summary>
/// 带有值类型显示和编辑的菜单
/// </summary>
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; }
}
/// <summary> 不要直接继承这个类 </summary>
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; }
}
/// <summary> 不要直接继承这个类 </summary>
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() { }
}
}
}
}

View File

@ -1,28 +1,28 @@
using UnityEngine;
namespace AxibugEmuOnline.Client
{
public class OptionUI_ExecuteItem : OptionUI_MenuItem<ExecuteMenu>
{
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<ExecuteMenu>
{
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);
}
}
}
}
}
}

View File

@ -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<SaveSlotMenu>
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<SaveSlotMenu>
{
public RawImage UI_ScreenShot;
public Image UI_Empty;
@ -113,5 +113,5 @@ namespace AxibugEmuOnline.Client
{
MenuData.OnExcute(optionUI, ref cancelHide);
}
}
}
}
}

View File

@ -1,84 +1,84 @@
using AxibugEmuOnline.Client.ClientCore;
using UnityEngine;
namespace AxibugEmuOnline.Client
{
public class OptionUI_ValueEditItem : OptionUI_MenuItem<ValueSetMenu>
{
[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<ValueSetMenu>
{
[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();
}
}

View File

@ -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);
}
}
}

View File

@ -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();
}
}
}
}

View File

@ -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<MenuData>
{
[SerializeField]
MenuItem SubMenuItemTemplate;
[SerializeField]
CanvasGroup alphaGroup;
private TweenerCore<float, float, FloatOptions> selectTween;
private bool m_selected;
private TweenerCore<int, int, NoOptions> rollTween;
protected override void Awake()
{
m_selected = false;
if (alphaGroup != null) alphaGroup.alpha = 0;
base.Awake();
}
public override void Init(List<MenuData> 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<MenuData>
{
[SerializeField]
MenuItem SubMenuItemTemplate;
[SerializeField]
CanvasGroup alphaGroup;
private TweenerCore<float, float, FloatOptions> selectTween;
private bool m_selected;
private TweenerCore<int, int, NoOptions> 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<MenuData> 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<Vector2> m_itemUIPosition = new List<Vector2>();
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<Vector2> m_itemUIPosition = new List<Vector2>();
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<MenuItem>();
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<MenuItem>();
if (Application.isPlaying)
{
var item = GameObject.Instantiate(template.gameObject, parent).GetComponent<MenuItem>();
item.transform.localPosition = Vector3.zero;
return item;
}
#else
var item = GameObject.Instantiate(template.gameObject, parent).GetComponent<MenuItem>();
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<MenuItem>();
}
#else
var item = GameObject.Instantiate(template.gameObject, parent).GetComponent<MenuItem>();
item.transform.localPosition = Vector3.zero;
return item;
#endif
//========================套娃宏 End========================
#else
return GameObject.Instantiate(SubMenuItemTemplate.gameObject, parent).GetComponent<MenuItem>();
#endif
#else
return GameObject.Instantiate(SubMenuItemTemplate.gameObject, parent).GetComponent<MenuItem>();
#endif
}
}
}
}
}

View File

@ -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
{
/// <summary>
/// 用于指定一对CanvasGroup,做透明度切换
/// </summary>
public class AlphaWraper
{
private bool m_on;
private CanvasGroup m_offUI;
private CanvasGroup m_onUI;
private TweenerCore<float, float, FloatOptions> m_onTween;
private TweenerCore<float, float, FloatOptions> 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);
}
}
}
}
/// </summary>
public class AlphaWraper
{
private bool m_on;
private CanvasGroup m_offUI;
private CanvasGroup m_onUI;
private TweenerCore<float, float, FloatOptions> m_onTween;
private TweenerCore<float, float, FloatOptions> 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);
}
}
}
}

View File

@ -1,19 +1,19 @@
using UnityEngine;
namespace AxibugEmuOnline.Client
{
using UnityEngine;
namespace AxibugEmuOnline.Client
{
/// <summary>
/// 自动根据canvasgroup的alpha控制blocksRaycasts的开启状态
/// </summary>
[RequireComponent(typeof(CanvasGroup))]
public class AutoRaycastCanvasGroup : MonoBehaviour
{
private CanvasGroup canvasGroup;
private void Update()
{
if (canvasGroup == null) canvasGroup = gameObject.GetComponent<CanvasGroup>();
canvasGroup.blocksRaycasts = canvasGroup.alpha == 0 ? false : true;
}
}
}
/// </summary>
[RequireComponent(typeof(CanvasGroup))]
public class AutoRaycastCanvasGroup : MonoBehaviour
{
private CanvasGroup canvasGroup;
private void Update()
{
if (canvasGroup == null) canvasGroup = gameObject.GetComponent<CanvasGroup>();
canvasGroup.blocksRaycasts = canvasGroup.alpha == 0 ? false : true;
}
}
}

View File

@ -1,62 +1,62 @@
using System;
namespace AxibugEmuOnline.Client.UI
{
using System;
namespace AxibugEmuOnline.Client.UI
{
/// <summary>
/// 用于周期性触发回调的工具,带有触发周期和延迟触发的参数可调
/// </summary>
public class PulseInvoker
{
private Action _action;
private float _interval;
private float _delay;
private float _elapsedTime;
private bool _isActive;
/// </summary>
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();
}
}
}
}
}

View File

@ -21,6 +21,8 @@ namespace AxibugEmuOnline.Client
get => m_target;
set
{
if (m_target == value) return;
m_target = value;
if (m_target == null)
{

View File

@ -1,38 +1,38 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace AxibugEmuOnline.Client
{
public static class UITool
{
private static Dictionary<Graphic, Material> _caches = new Dictionary<Graphic, Material>();
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<Graphic, Material> _caches = new Dictionary<Graphic, Material>();
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;
}
}
}

View File

@ -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<float, float, FloatOptions> 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<float, float, FloatOptions> 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;
}
}
}

View File

@ -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();
}
/// <summary>
/// (uint lastFrame, float lastTime)
/// </summary>
ValueTuple<uint, float> 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();
}
/// <summary>
/// (uint lastFrame, float lastTime)
/// </summary>
ValueTuple<uint, float> 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);
}
}
}

View File

@ -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<int, RomFile> s_RomFileCahcesInRoomInfo = new Dictionary<int, RomFile>();
public static void FetchRomFileInRoomInfo(this Protobuf_Room_MiniInfo roomInfo, Action<Protobuf_Room_MiniInfo, RomFile> 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<int, RomFile> s_RomFileCahcesInRoomInfo = new Dictionary<int, RomFile>();
public static void FetchRomFileInRoomInfo(this Protobuf_Room_MiniInfo roomInfo, Action<Protobuf_Room_MiniInfo, RomFile> 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;
}
}
}
}
}
}