forked from sin365/AxibugEmuOnline
代码目录结构调整
This commit is contained in:
parent
5b9cb9bc5e
commit
2dc84085eb
1
.gitignore
vendored
1
.gitignore
vendored
@ -17,3 +17,4 @@
|
|||||||
/virtuanessrc097-master
|
/virtuanessrc097-master
|
||||||
/AxibugEmuOnline.Server/config.cfg
|
/AxibugEmuOnline.Server/config.cfg
|
||||||
/AxibugEmuOnline.Server/bin/
|
/AxibugEmuOnline.Server/bin/
|
||||||
|
/AxibugEmuOnline.Client/.editorconfig
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1476,7 +1476,7 @@ MonoBehaviour:
|
|||||||
m_MinHeight: -1
|
m_MinHeight: -1
|
||||||
m_PreferredWidth: -1
|
m_PreferredWidth: -1
|
||||||
m_PreferredHeight: -1
|
m_PreferredHeight: -1
|
||||||
m_FlexibleWidth: 20
|
m_FlexibleWidth: 5
|
||||||
m_FlexibleHeight: -1
|
m_FlexibleHeight: -1
|
||||||
m_LayoutPriority: 1
|
m_LayoutPriority: 1
|
||||||
--- !u!1 &6998597834321643812
|
--- !u!1 &6998597834321643812
|
||||||
@ -1612,7 +1612,7 @@ RectTransform:
|
|||||||
m_AnchorMin: {x: 0, y: 0}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
m_AnchorMax: {x: 0, y: 0}
|
m_AnchorMax: {x: 0, y: 0}
|
||||||
m_AnchoredPosition: {x: 0, y: 0}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 20, y: 0}
|
m_SizeDelta: {x: 20, y: -20}
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
--- !u!222 &2285457357903007277
|
--- !u!222 &2285457357903007277
|
||||||
CanvasRenderer:
|
CanvasRenderer:
|
||||||
@ -1642,8 +1642,8 @@ MonoBehaviour:
|
|||||||
m_OnCullStateChanged:
|
m_OnCullStateChanged:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
m_Sprite: {fileID: 10913, guid: 0000000000000000f000000000000000, type: 0}
|
m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0}
|
||||||
m_Type: 0
|
m_Type: 1
|
||||||
m_PreserveAspect: 0
|
m_PreserveAspect: 0
|
||||||
m_FillCenter: 1
|
m_FillCenter: 1
|
||||||
m_FillMethod: 4
|
m_FillMethod: 4
|
||||||
@ -1936,16 +1936,16 @@ MonoBehaviour:
|
|||||||
m_Font: {fileID: 12800000, guid: 33a3bdf8f6bd1ec4eba7c4bc58183212, type: 3}
|
m_Font: {fileID: 12800000, guid: 33a3bdf8f6bd1ec4eba7c4bc58183212, type: 3}
|
||||||
m_FontSize: 20
|
m_FontSize: 20
|
||||||
m_FontStyle: 0
|
m_FontStyle: 0
|
||||||
m_BestFit: 0
|
m_BestFit: 1
|
||||||
m_MinSize: 2
|
m_MinSize: 2
|
||||||
m_MaxSize: 40
|
m_MaxSize: 20
|
||||||
m_Alignment: 3
|
m_Alignment: 4
|
||||||
m_AlignByGeometry: 0
|
m_AlignByGeometry: 0
|
||||||
m_RichText: 1
|
m_RichText: 1
|
||||||
m_HorizontalOverflow: 0
|
m_HorizontalOverflow: 0
|
||||||
m_VerticalOverflow: 1
|
m_VerticalOverflow: 1
|
||||||
m_LineSpacing: 1
|
m_LineSpacing: 1
|
||||||
m_Text: 99
|
m_Text: 0
|
||||||
--- !u!114 &5172613673109503612
|
--- !u!114 &5172613673109503612
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -1961,9 +1961,9 @@ MonoBehaviour:
|
|||||||
m_IgnoreLayout: 0
|
m_IgnoreLayout: 0
|
||||||
m_MinWidth: -1
|
m_MinWidth: -1
|
||||||
m_MinHeight: -1
|
m_MinHeight: -1
|
||||||
m_PreferredWidth: -1
|
m_PreferredWidth: 50
|
||||||
m_PreferredHeight: -1
|
m_PreferredHeight: -1
|
||||||
m_FlexibleWidth: 1
|
m_FlexibleWidth: -1
|
||||||
m_FlexibleHeight: -1
|
m_FlexibleHeight: -1
|
||||||
m_LayoutPriority: 1
|
m_LayoutPriority: 1
|
||||||
--- !u!1 &8884391103430529053
|
--- !u!1 &8884391103430529053
|
||||||
|
@ -15800,6 +15800,30 @@ PrefabInstance:
|
|||||||
serializedVersion: 3
|
serializedVersion: 3
|
||||||
m_TransformParent: {fileID: 1599240741}
|
m_TransformParent: {fileID: 1599240741}
|
||||||
m_Modifications:
|
m_Modifications:
|
||||||
|
- target: {fileID: 231194784974113132, guid: 1de15a80c8c1aa94486563740a15d91c, type: 3}
|
||||||
|
propertyPath: m_AnchorMax.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 231194784974113132, guid: 1de15a80c8c1aa94486563740a15d91c, type: 3}
|
||||||
|
propertyPath: m_AnchorMin.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 231194784974113132, guid: 1de15a80c8c1aa94486563740a15d91c, type: 3}
|
||||||
|
propertyPath: m_SizeDelta.x
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 231194784974113132, guid: 1de15a80c8c1aa94486563740a15d91c, type: 3}
|
||||||
|
propertyPath: m_SizeDelta.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 231194784974113132, guid: 1de15a80c8c1aa94486563740a15d91c, type: 3}
|
||||||
|
propertyPath: m_AnchoredPosition.x
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 231194784974113132, guid: 1de15a80c8c1aa94486563740a15d91c, type: 3}
|
||||||
|
propertyPath: m_AnchoredPosition.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 321727879374672331, guid: 1de15a80c8c1aa94486563740a15d91c, type: 3}
|
- target: {fileID: 321727879374672331, guid: 1de15a80c8c1aa94486563740a15d91c, type: 3}
|
||||||
propertyPath: m_AnchorMax.y
|
propertyPath: m_AnchorMax.y
|
||||||
value: 0
|
value: 0
|
||||||
@ -15832,6 +15856,38 @@ PrefabInstance:
|
|||||||
propertyPath: m_AnchoredPosition.y
|
propertyPath: m_AnchoredPosition.y
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 391878975413806388, guid: 1de15a80c8c1aa94486563740a15d91c, type: 3}
|
||||||
|
propertyPath: m_AnchorMax.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 391878975413806388, guid: 1de15a80c8c1aa94486563740a15d91c, type: 3}
|
||||||
|
propertyPath: m_AnchorMin.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 391878975413806388, guid: 1de15a80c8c1aa94486563740a15d91c, type: 3}
|
||||||
|
propertyPath: m_SizeDelta.x
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 391878975413806388, guid: 1de15a80c8c1aa94486563740a15d91c, type: 3}
|
||||||
|
propertyPath: m_SizeDelta.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 391878975413806388, guid: 1de15a80c8c1aa94486563740a15d91c, type: 3}
|
||||||
|
propertyPath: m_LocalPosition.x
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 391878975413806388, guid: 1de15a80c8c1aa94486563740a15d91c, type: 3}
|
||||||
|
propertyPath: m_LocalPosition.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 391878975413806388, guid: 1de15a80c8c1aa94486563740a15d91c, type: 3}
|
||||||
|
propertyPath: m_AnchoredPosition.x
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 391878975413806388, guid: 1de15a80c8c1aa94486563740a15d91c, type: 3}
|
||||||
|
propertyPath: m_AnchoredPosition.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 736530578155193984, guid: 1de15a80c8c1aa94486563740a15d91c, type: 3}
|
- target: {fileID: 736530578155193984, guid: 1de15a80c8c1aa94486563740a15d91c, type: 3}
|
||||||
propertyPath: m_AnchorMax.x
|
propertyPath: m_AnchorMax.x
|
||||||
value: 0
|
value: 0
|
||||||
|
@ -1,11 +1,2 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 37a06c0960dd38d48a93b9642efa11f6
|
guid: d8c50df5df7b4834c84889fbdad9eb9b
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
8
AxibugEmuOnline.Client/Assets/Script/AppMain.meta
Normal file
8
AxibugEmuOnline.Client/Assets/Script/AppMain.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bad0f9bf28f67de428fed5977006db1a
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
180
AxibugEmuOnline.Client/Assets/Script/AppMain/App.cs
Normal file
180
AxibugEmuOnline.Client/Assets/Script/AppMain/App.cs
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
using AxibugEmuOnline.Client.Manager;
|
||||||
|
using AxibugEmuOnline.Client.Network;
|
||||||
|
using System.Collections;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Networking;
|
||||||
|
using static AxibugEmuOnline.Client.HttpAPI;
|
||||||
|
using static AxibugEmuOnline.Client.Manager.LogManager;
|
||||||
|
|
||||||
|
namespace AxibugEmuOnline.Client.ClientCore
|
||||||
|
{
|
||||||
|
public static class App
|
||||||
|
{
|
||||||
|
public static string TokenStr;
|
||||||
|
public static string IP;
|
||||||
|
public static int Port;
|
||||||
|
public static LogManager log;
|
||||||
|
public static NetworkHelper network;
|
||||||
|
public static AppLogin login;
|
||||||
|
public static AppChat chat;
|
||||||
|
public static UserDataManager user;
|
||||||
|
//public static AppNetGame netgame;
|
||||||
|
public static AppEmu emu;
|
||||||
|
public static RomLib nesRomLib;
|
||||||
|
public static HttpAPI httpAPI;
|
||||||
|
public static CacheManager CacheMgr;
|
||||||
|
public static AppRoom roomMgr;
|
||||||
|
public static AppSettings settings;
|
||||||
|
public static FilterManager filter;
|
||||||
|
public static AppShare share;
|
||||||
|
#region Mono
|
||||||
|
public static TickLoop tickLoop;
|
||||||
|
private static CoroutineRunner coRunner;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#if UNITY_PSP2
|
||||||
|
public static string PersistentDataPath => "ux0:data/AxibugEmu";
|
||||||
|
#else
|
||||||
|
public static string PersistentDataPath => Application.persistentDataPath;
|
||||||
|
#endif
|
||||||
|
public static void Init(Initer initer)
|
||||||
|
{
|
||||||
|
settings = new AppSettings();
|
||||||
|
|
||||||
|
log = new LogManager();
|
||||||
|
LogManager.OnLog += OnNoSugarNetLog;
|
||||||
|
network = new NetworkHelper();
|
||||||
|
login = new AppLogin();
|
||||||
|
chat = new AppChat();
|
||||||
|
user = new UserDataManager();
|
||||||
|
emu = new AppEmu();
|
||||||
|
//netgame = new AppNetGame();
|
||||||
|
httpAPI = new HttpAPI();
|
||||||
|
nesRomLib = new RomLib(EnumPlatform.NES);
|
||||||
|
CacheMgr = new CacheManager();
|
||||||
|
roomMgr = new AppRoom();
|
||||||
|
share = new AppShare();
|
||||||
|
filter = new FilterManager(initer.m_filterVolume, initer.m_filterPreview, initer.m_xmbBg);
|
||||||
|
var go = new GameObject("[AppAxibugEmuOnline]");
|
||||||
|
GameObject.DontDestroyOnLoad(go);
|
||||||
|
tickLoop = go.AddComponent<TickLoop>();
|
||||||
|
coRunner = go.AddComponent<CoroutineRunner>();
|
||||||
|
|
||||||
|
if (UnityEngine.Application.platform == RuntimePlatform.PSP2)
|
||||||
|
{
|
||||||
|
//PSV 等平台需要手动创建目录
|
||||||
|
PersistentDataPathDir();
|
||||||
|
}
|
||||||
|
|
||||||
|
var importNode = GameObject.Find("IMPORTENT");
|
||||||
|
if (importNode != null) GameObject.DontDestroyOnLoad(importNode);
|
||||||
|
|
||||||
|
StartCoroutine(AppTickFlow());
|
||||||
|
RePullNetInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void PersistentDataPathDir()
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(PersistentDataPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(PersistentDataPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerator AppTickFlow()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
Tick();
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RePullNetInfo()
|
||||||
|
{
|
||||||
|
StartCoroutine(StartNetInit());
|
||||||
|
}
|
||||||
|
|
||||||
|
static IEnumerator StartNetInit()
|
||||||
|
{
|
||||||
|
if (App.network.isConnected)
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
int platform = 0;
|
||||||
|
bool bTest = false;
|
||||||
|
if (bTest)
|
||||||
|
{
|
||||||
|
yield return null;
|
||||||
|
Connect("192.168.0.47", 10492);
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnityWebRequest request = UnityWebRequest.Get($"{App.httpAPI.WebSiteApi}/CheckStandInfo?platform={platform}&version={Application.version}");
|
||||||
|
yield return request.SendWebRequest();
|
||||||
|
|
||||||
|
if (request.result != UnityWebRequest.Result.Success)
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
App.log.Debug($"ApiResp => {request.downloadHandler.text}");
|
||||||
|
Resp_CheckStandInfo resp = JsonUtility.FromJson<Resp_CheckStandInfo>(request.downloadHandler.text);
|
||||||
|
//需要更新
|
||||||
|
if (resp.needUpdateClient == 1)
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return null;
|
||||||
|
//Connect("127.0.0.1", 10492);
|
||||||
|
Connect(resp.serverIp, resp.serverPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Tick()
|
||||||
|
{
|
||||||
|
nesRomLib.ExecuteFetchRomInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Coroutine StartCoroutine(IEnumerator itor)
|
||||||
|
{
|
||||||
|
return coRunner.StartCoroutine(itor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void StopCoroutine(Coroutine cor)
|
||||||
|
{
|
||||||
|
coRunner.StopCoroutine(cor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Connect(string IP, int port)
|
||||||
|
{
|
||||||
|
Task task = new Task(() =>
|
||||||
|
{
|
||||||
|
network.Init(IP, port);
|
||||||
|
});
|
||||||
|
task.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Close()
|
||||||
|
{
|
||||||
|
App.log.Info("停止");
|
||||||
|
}
|
||||||
|
static void OnNoSugarNetLog(int LogLevel, string msg)
|
||||||
|
{
|
||||||
|
E_LogType logType = (E_LogType)LogLevel;
|
||||||
|
switch (logType)
|
||||||
|
{
|
||||||
|
case E_LogType.Debug:
|
||||||
|
case E_LogType.Info:
|
||||||
|
Debug.Log("[AxiEmu]:" + msg);
|
||||||
|
break;
|
||||||
|
case E_LogType.Warning:
|
||||||
|
Debug.LogWarning("[AxiEmu]:" + msg);
|
||||||
|
break;
|
||||||
|
case E_LogType.Error:
|
||||||
|
Debug.LogError("[AxiEmu]:" + msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
11
AxibugEmuOnline.Client/Assets/Script/AppMain/App.cs.meta
Normal file
11
AxibugEmuOnline.Client/Assets/Script/AppMain/App.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 37a06c0960dd38d48a93b9642efa11f6
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -1,10 +1,10 @@
|
|||||||
namespace AxibugEmuOnline.Client
|
namespace AxibugEmuOnline.Client
|
||||||
{
|
{
|
||||||
public static class EventInvoker
|
public static class EventInvoker
|
||||||
{
|
{
|
||||||
public delegate void OnFilterPresetRemovedHandle(FilterManager.Filter filter, FilterManager.FilterPreset removedPreset);
|
public delegate void OnFilterPresetRemovedHandle(FilterManager.Filter filter, FilterManager.FilterPreset removedPreset);
|
||||||
public static event OnFilterPresetRemovedHandle OnFilterPresetRemoved;
|
public static event OnFilterPresetRemovedHandle OnFilterPresetRemoved;
|
||||||
public static void RaiseFilterPresetRemoved(FilterManager.Filter filter, FilterManager.FilterPreset removedPreset)
|
public static void RaiseFilterPresetRemoved(FilterManager.Filter filter, FilterManager.FilterPreset removedPreset)
|
||||||
=> OnFilterPresetRemoved.Invoke(filter, removedPreset);
|
=> OnFilterPresetRemoved.Invoke(filter, removedPreset);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,96 +1,96 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Rendering.PostProcessing;
|
using UnityEngine.Rendering.PostProcessing;
|
||||||
|
|
||||||
namespace AxibugEmuOnline.Client
|
namespace AxibugEmuOnline.Client
|
||||||
{
|
{
|
||||||
public abstract class FilterEffect : PostProcessEffectSettings
|
public abstract class FilterEffect : PostProcessEffectSettings
|
||||||
{
|
{
|
||||||
private List<EditableParamerter> m_editableParamList;
|
private List<EditableParamerter> m_editableParamList;
|
||||||
|
|
||||||
public IReadOnlyCollection<EditableParamerter> EditableParam => m_editableParamList.AsReadOnly();
|
public IReadOnlyCollection<EditableParamerter> EditableParam => m_editableParamList.AsReadOnly();
|
||||||
|
|
||||||
public abstract string Name { get; }
|
public abstract string Name { get; }
|
||||||
|
|
||||||
public FilterEffect()
|
public FilterEffect()
|
||||||
{
|
{
|
||||||
GetEditableFilterParamters();
|
GetEditableFilterParamters();
|
||||||
}
|
}
|
||||||
protected void GetEditableFilterParamters()
|
protected void GetEditableFilterParamters()
|
||||||
{
|
{
|
||||||
var parameters = (from t in GetType().GetFields(BindingFlags.Instance | BindingFlags.Public)
|
var parameters = (from t in GetType().GetFields(BindingFlags.Instance | BindingFlags.Public)
|
||||||
where t.FieldType.IsSubclassOf(typeof(ParameterOverride))
|
where t.FieldType.IsSubclassOf(typeof(ParameterOverride))
|
||||||
where t.DeclaringType.IsSubclassOf(typeof(FilterEffect))
|
where t.DeclaringType.IsSubclassOf(typeof(FilterEffect))
|
||||||
orderby t.MetadataToken
|
orderby t.MetadataToken
|
||||||
select t);
|
select t);
|
||||||
|
|
||||||
m_editableParamList = new List<EditableParamerter>();
|
m_editableParamList = new List<EditableParamerter>();
|
||||||
foreach (var param in parameters)
|
foreach (var param in parameters)
|
||||||
{
|
{
|
||||||
var paramObj = (ParameterOverride)param.GetValue(this);
|
var paramObj = (ParameterOverride)param.GetValue(this);
|
||||||
var rangeAtt = param.GetCustomAttribute<RangeAttribute>();
|
var rangeAtt = param.GetCustomAttribute<RangeAttribute>();
|
||||||
float min = 0;
|
float min = 0;
|
||||||
float max = 10;
|
float max = 10;
|
||||||
if (rangeAtt != null)
|
if (rangeAtt != null)
|
||||||
{
|
{
|
||||||
min = rangeAtt.min; max = rangeAtt.max;
|
min = rangeAtt.min; max = rangeAtt.max;
|
||||||
}
|
}
|
||||||
|
|
||||||
var editableParam = new EditableParamerter(param.Name, paramObj, min, max);
|
var editableParam = new EditableParamerter(param.Name, paramObj, min, max);
|
||||||
m_editableParamList.Add(editableParam);
|
m_editableParamList.Add(editableParam);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class EditableParamerter
|
public class EditableParamerter
|
||||||
{
|
{
|
||||||
private ParameterOverride m_paramObject;
|
private ParameterOverride m_paramObject;
|
||||||
private FieldInfo valueFieldInfo;
|
private FieldInfo valueFieldInfo;
|
||||||
|
|
||||||
public Type ValueType { get; private set; }
|
public Type ValueType { get; private set; }
|
||||||
public string Name { get; private set; }
|
public string Name { get; private set; }
|
||||||
public object Value
|
public object Value
|
||||||
{
|
{
|
||||||
get => valueFieldInfo.GetValue(m_paramObject);
|
get => valueFieldInfo.GetValue(m_paramObject);
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
valueFieldInfo.SetValue(m_paramObject, value);
|
valueFieldInfo.SetValue(m_paramObject, value);
|
||||||
m_paramObject.overrideState = true;
|
m_paramObject.overrideState = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public object MinValue { get; private set; }
|
public object MinValue { get; private set; }
|
||||||
public object MaxValue { get; private set; }
|
public object MaxValue { get; private set; }
|
||||||
|
|
||||||
public EditableParamerter(string name, ParameterOverride paramObject, object minValue, object maxValue)
|
public EditableParamerter(string name, ParameterOverride paramObject, object minValue, object maxValue)
|
||||||
{
|
{
|
||||||
m_paramObject = paramObject;
|
m_paramObject = paramObject;
|
||||||
Name = name;
|
Name = name;
|
||||||
|
|
||||||
var paramType = paramObject.GetType();
|
var paramType = paramObject.GetType();
|
||||||
|
|
||||||
valueFieldInfo = paramType.GetField("value", BindingFlags.Public | BindingFlags.Instance);
|
valueFieldInfo = paramType.GetField("value", BindingFlags.Public | BindingFlags.Instance);
|
||||||
if (valueFieldInfo != null)
|
if (valueFieldInfo != null)
|
||||||
{
|
{
|
||||||
ValueType = valueFieldInfo.FieldType;
|
ValueType = valueFieldInfo.FieldType;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ValueType = typeof(object);
|
ValueType = typeof(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
MinValue = minValue;
|
MinValue = minValue;
|
||||||
MaxValue = maxValue;
|
MaxValue = maxValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResetToDefault() => m_paramObject.overrideState = false;
|
public void ResetToDefault() => m_paramObject.overrideState = false;
|
||||||
|
|
||||||
|
|
||||||
public void Apply(object overrideValue)
|
public void Apply(object overrideValue)
|
||||||
{
|
{
|
||||||
Value = overrideValue;
|
Value = overrideValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,106 +1,106 @@
|
|||||||
using AxibugEmuOnline.Client;
|
using AxibugEmuOnline.Client;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Rendering.PostProcessing;
|
using UnityEngine.Rendering.PostProcessing;
|
||||||
|
|
||||||
[System.Serializable]
|
[System.Serializable]
|
||||||
[PostProcess(typeof(FixingPixelArtGrilleRenderer), PostProcessEvent.BeforeStack, "Filter/FixingPixelArtGrille")]
|
[PostProcess(typeof(FixingPixelArtGrilleRenderer), PostProcessEvent.BeforeStack, "Filter/FixingPixelArtGrille")]
|
||||||
public sealed class FixingPixelArtGrille : FilterEffect
|
public sealed class FixingPixelArtGrille : FilterEffect
|
||||||
{
|
{
|
||||||
public override string Name => nameof(FixingPixelArtGrille);
|
public override string Name => nameof(FixingPixelArtGrille);
|
||||||
|
|
||||||
public ParameterOverride<EnumMaskStyle> MaskStyle = new ParameterOverride<EnumMaskStyle> { value = EnumMaskStyle.ApertureGrille };
|
public ParameterOverride<EnumMaskStyle> MaskStyle = new ParameterOverride<EnumMaskStyle> { value = EnumMaskStyle.ApertureGrille };
|
||||||
|
|
||||||
[Tooltip("Emulated input resolution\nOptimize for resize")]
|
[Tooltip("Emulated input resolution\nOptimize for resize")]
|
||||||
public Vector2Parameter DrawResolution = new Vector2Parameter
|
public Vector2Parameter DrawResolution = new Vector2Parameter
|
||||||
{
|
{
|
||||||
value = new Vector2(272, 240)
|
value = new Vector2(272, 240)
|
||||||
};
|
};
|
||||||
|
|
||||||
[Tooltip("Hardness of scanline")]
|
[Tooltip("Hardness of scanline")]
|
||||||
[Range(-32, 0)]
|
[Range(-32, 0)]
|
||||||
public FloatParameter HardScan = new FloatParameter { value = -10 };
|
public FloatParameter HardScan = new FloatParameter { value = -10 };
|
||||||
|
|
||||||
[Tooltip("Hardness of pixels in scanline")]
|
[Tooltip("Hardness of pixels in scanline")]
|
||||||
[Range(-6, 0)]
|
[Range(-6, 0)]
|
||||||
public FloatParameter HardPix = new FloatParameter { value = -2 };
|
public FloatParameter HardPix = new FloatParameter { value = -2 };
|
||||||
|
|
||||||
[Tooltip("Hardness of short vertical bloom")]
|
[Tooltip("Hardness of short vertical bloom")]
|
||||||
[Range(-8, 0)]
|
[Range(-8, 0)]
|
||||||
public FloatParameter HardBloomScan = new FloatParameter { value = -4.0f };
|
public FloatParameter HardBloomScan = new FloatParameter { value = -4.0f };
|
||||||
|
|
||||||
[Tooltip("Hardness of short horizontal bloom")]
|
[Tooltip("Hardness of short horizontal bloom")]
|
||||||
[Range(-4, 0)]
|
[Range(-4, 0)]
|
||||||
public FloatParameter HardBloomPix = new FloatParameter { value = -1.5f };
|
public FloatParameter HardBloomPix = new FloatParameter { value = -1.5f };
|
||||||
|
|
||||||
[Tooltip("Amount of small bloom effect")]
|
[Tooltip("Amount of small bloom effect")]
|
||||||
[Range(0, 1)]
|
[Range(0, 1)]
|
||||||
public FloatParameter BloomAmount = new FloatParameter { value = 1 / 16f };
|
public FloatParameter BloomAmount = new FloatParameter { value = 1 / 16f };
|
||||||
|
|
||||||
[Tooltip("Display warp")]
|
[Tooltip("Display warp")]
|
||||||
public Vector2Parameter Warp = new Vector2Parameter { value = new Vector2(1f / 64f, 1f / 24f) };
|
public Vector2Parameter Warp = new Vector2Parameter { value = new Vector2(1f / 64f, 1f / 24f) };
|
||||||
|
|
||||||
[Tooltip("Amount of shadow mask Light")]
|
[Tooltip("Amount of shadow mask Light")]
|
||||||
[Range(1, 3)]
|
[Range(1, 3)]
|
||||||
public FloatParameter MaskLight = new FloatParameter { value = 1.5f };
|
public FloatParameter MaskLight = new FloatParameter { value = 1.5f };
|
||||||
[Range(0.1f, 1)]
|
[Range(0.1f, 1)]
|
||||||
[Tooltip("Amount of shadow mask Dark")]
|
[Tooltip("Amount of shadow mask Dark")]
|
||||||
public FloatParameter MaskDrak = new FloatParameter { value = 0.5f };
|
public FloatParameter MaskDrak = new FloatParameter { value = 0.5f };
|
||||||
|
|
||||||
public enum EnumMaskStyle
|
public enum EnumMaskStyle
|
||||||
{
|
{
|
||||||
TVStyle,
|
TVStyle,
|
||||||
ApertureGrille,
|
ApertureGrille,
|
||||||
StretchedVGA,
|
StretchedVGA,
|
||||||
VGAStyle
|
VGAStyle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class FixingPixelArtGrilleRenderer : PostProcessEffectRenderer<FixingPixelArtGrille>
|
public sealed class FixingPixelArtGrilleRenderer : PostProcessEffectRenderer<FixingPixelArtGrille>
|
||||||
{
|
{
|
||||||
private Shader shader;
|
private Shader shader;
|
||||||
private Material material;
|
private Material material;
|
||||||
|
|
||||||
public override void Init()
|
public override void Init()
|
||||||
{
|
{
|
||||||
shader = Shader.Find("PostEffect/FixingPixcelArtGrille");
|
shader = Shader.Find("PostEffect/FixingPixcelArtGrille");
|
||||||
material = new Material(shader);
|
material = new Material(shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Render(PostProcessRenderContext context)
|
public override void Render(PostProcessRenderContext context)
|
||||||
{
|
{
|
||||||
material.SetVector("_iResolution", new Vector4(Screen.width, Screen.height, 0, 0));
|
material.SetVector("_iResolution", new Vector4(Screen.width, Screen.height, 0, 0));
|
||||||
var res = settings.DrawResolution;
|
var res = settings.DrawResolution;
|
||||||
material.SetVector("_res", new Vector4(res.value.x, res.value.y, 0, 0));
|
material.SetVector("_res", new Vector4(res.value.x, res.value.y, 0, 0));
|
||||||
material.SetFloat("_hardScan", settings.HardScan.value);
|
material.SetFloat("_hardScan", settings.HardScan.value);
|
||||||
material.SetFloat("_hardPix", settings.HardPix.value);
|
material.SetFloat("_hardPix", settings.HardPix.value);
|
||||||
material.SetFloat("_hardBloomScan", settings.HardBloomScan.value);
|
material.SetFloat("_hardBloomScan", settings.HardBloomScan.value);
|
||||||
material.SetFloat("_hardBloomPix", settings.HardBloomPix.value);
|
material.SetFloat("_hardBloomPix", settings.HardBloomPix.value);
|
||||||
material.SetFloat("_bloomAmount", settings.BloomAmount.value);
|
material.SetFloat("_bloomAmount", settings.BloomAmount.value);
|
||||||
material.SetVector("_warp", settings.Warp.value);
|
material.SetVector("_warp", settings.Warp.value);
|
||||||
material.SetFloat("_maskDark", settings.MaskDrak.value);
|
material.SetFloat("_maskDark", settings.MaskDrak.value);
|
||||||
material.SetFloat("_maskLight", settings.MaskLight.value);
|
material.SetFloat("_maskLight", settings.MaskLight.value);
|
||||||
|
|
||||||
material.DisableKeyword("_MASKSTYLE_VGASTYLE");
|
material.DisableKeyword("_MASKSTYLE_VGASTYLE");
|
||||||
material.DisableKeyword("_MASKSTYLE_TVSTYLE");
|
material.DisableKeyword("_MASKSTYLE_TVSTYLE");
|
||||||
material.DisableKeyword("_MASKSTYLE_APERTUREGRILLE");
|
material.DisableKeyword("_MASKSTYLE_APERTUREGRILLE");
|
||||||
material.DisableKeyword("_MASKSTYLE_STRETCHEDVGA");
|
material.DisableKeyword("_MASKSTYLE_STRETCHEDVGA");
|
||||||
|
|
||||||
switch (settings.MaskStyle.value)
|
switch (settings.MaskStyle.value)
|
||||||
{
|
{
|
||||||
case FixingPixelArtGrille.EnumMaskStyle.VGAStyle:
|
case FixingPixelArtGrille.EnumMaskStyle.VGAStyle:
|
||||||
material.EnableKeyword("_MASKSTYLE_VGASTYLE");
|
material.EnableKeyword("_MASKSTYLE_VGASTYLE");
|
||||||
break;
|
break;
|
||||||
case FixingPixelArtGrille.EnumMaskStyle.TVStyle:
|
case FixingPixelArtGrille.EnumMaskStyle.TVStyle:
|
||||||
material.EnableKeyword("_MASKSTYLE_TVSTYLE");
|
material.EnableKeyword("_MASKSTYLE_TVSTYLE");
|
||||||
break;
|
break;
|
||||||
case FixingPixelArtGrille.EnumMaskStyle.ApertureGrille:
|
case FixingPixelArtGrille.EnumMaskStyle.ApertureGrille:
|
||||||
material.EnableKeyword("_MASKSTYLE_APERTUREGRILLE");
|
material.EnableKeyword("_MASKSTYLE_APERTUREGRILLE");
|
||||||
break;
|
break;
|
||||||
case FixingPixelArtGrille.EnumMaskStyle.StretchedVGA:
|
case FixingPixelArtGrille.EnumMaskStyle.StretchedVGA:
|
||||||
material.EnableKeyword("_MASKSTYLE_STRETCHEDVGA");
|
material.EnableKeyword("_MASKSTYLE_STRETCHEDVGA");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.command.Blit(context.source, context.destination, material);
|
context.command.Blit(context.source, context.destination, material);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,293 +1,293 @@
|
|||||||
|
|
||||||
Shader "PostEffect/FixingPixcelArtGrille"
|
Shader "PostEffect/FixingPixcelArtGrille"
|
||||||
{
|
{
|
||||||
Properties
|
Properties
|
||||||
{
|
{
|
||||||
_MainTex ("Base (RGB)", 2D) = "white" {}
|
_MainTex ("Base (RGB)", 2D) = "white" {}
|
||||||
}
|
}
|
||||||
SubShader
|
SubShader
|
||||||
{
|
{
|
||||||
Pass
|
Pass
|
||||||
{
|
{
|
||||||
CGPROGRAM
|
CGPROGRAM
|
||||||
|
|
||||||
#pragma shader_feature_local _MASKSTYLE_TVSTYLE _MASKSTYLE_APERTUREGRILLE _MASKSTYLE_STRETCHEDVGA _MASKSTYLE_VGASTYLE
|
#pragma shader_feature_local _MASKSTYLE_TVSTYLE _MASKSTYLE_APERTUREGRILLE _MASKSTYLE_STRETCHEDVGA _MASKSTYLE_VGASTYLE
|
||||||
#pragma vertex vert_img
|
#pragma vertex vert_img
|
||||||
#pragma fragment frag
|
#pragma fragment frag
|
||||||
#include "UnityCG.cginc"
|
#include "UnityCG.cginc"
|
||||||
|
|
||||||
sampler2D _MainTex;
|
sampler2D _MainTex;
|
||||||
float4 _MainTex_TexelSize;
|
float4 _MainTex_TexelSize;
|
||||||
|
|
||||||
//
|
//
|
||||||
// PUBLIC DOMAIN CRT STYLED SCAN-LINE SHADER
|
// PUBLIC DOMAIN CRT STYLED SCAN-LINE SHADER
|
||||||
//
|
//
|
||||||
// by Timothy Lottes
|
// by Timothy Lottes
|
||||||
//
|
//
|
||||||
// This is more along the style of a really good CGA arcade monitor.
|
// This is more along the style of a really good CGA arcade monitor.
|
||||||
// With RGB inputs instead of NTSC.
|
// With RGB inputs instead of NTSC.
|
||||||
// The shadow mask example has the mask rotated 90 degrees for less chromatic aberration.
|
// The shadow mask example has the mask rotated 90 degrees for less chromatic aberration.
|
||||||
//
|
//
|
||||||
// Left it unoptimized to show the theory behind the algorithm.
|
// Left it unoptimized to show the theory behind the algorithm.
|
||||||
//
|
//
|
||||||
// It is an example what I personally would want as a display option for pixel art games.
|
// It is an example what I personally would want as a display option for pixel art games.
|
||||||
// Please take and use, change, or whatever.
|
// Please take and use, change, or whatever.
|
||||||
//
|
//
|
||||||
|
|
||||||
float2 _iResolution = float2(1920,1080);
|
float2 _iResolution = float2(1920,1080);
|
||||||
|
|
||||||
// Emulated input resolution.
|
// Emulated input resolution.
|
||||||
// Optimize for resize.
|
// Optimize for resize.
|
||||||
float2 _res = float2(272.0,240.0);
|
float2 _res = float2(272.0,240.0);
|
||||||
|
|
||||||
// Hardness of scanline.
|
// Hardness of scanline.
|
||||||
// -8.0 = soft
|
// -8.0 = soft
|
||||||
// -16.0 = medium
|
// -16.0 = medium
|
||||||
float _hardScan = -10.0;
|
float _hardScan = -10.0;
|
||||||
|
|
||||||
// Hardness of pixels in scanline.
|
// Hardness of pixels in scanline.
|
||||||
// -2.0 = soft
|
// -2.0 = soft
|
||||||
// -4.0 = hard
|
// -4.0 = hard
|
||||||
float _hardPix =-2.0;
|
float _hardPix =-2.0;
|
||||||
|
|
||||||
// Hardness of short vertical bloom.
|
// Hardness of short vertical bloom.
|
||||||
// -1.0 = wide to the point of clipping (bad)
|
// -1.0 = wide to the point of clipping (bad)
|
||||||
// -1.5 = wide
|
// -1.5 = wide
|
||||||
// -4.0 = not very wide at all
|
// -4.0 = not very wide at all
|
||||||
float _hardBloomScan = -4.0;
|
float _hardBloomScan = -4.0;
|
||||||
|
|
||||||
// Hardness of short horizontal bloom.
|
// Hardness of short horizontal bloom.
|
||||||
// -0.5 = wide to the point of clipping (bad)
|
// -0.5 = wide to the point of clipping (bad)
|
||||||
// -1.0 = wide
|
// -1.0 = wide
|
||||||
// -2.0 = not very wide at all
|
// -2.0 = not very wide at all
|
||||||
float _hardBloomPix = -1.5;
|
float _hardBloomPix = -1.5;
|
||||||
|
|
||||||
// Amount of small bloom effect.
|
// Amount of small bloom effect.
|
||||||
// 1.0/1.0 = only bloom
|
// 1.0/1.0 = only bloom
|
||||||
// 1.0/16.0 = what I think is a good amount of small bloom
|
// 1.0/16.0 = what I think is a good amount of small bloom
|
||||||
// 0.0 = no bloom
|
// 0.0 = no bloom
|
||||||
float _bloomAmount = 1.0/16.0;
|
float _bloomAmount = 1.0/16.0;
|
||||||
|
|
||||||
// Display warp.
|
// Display warp.
|
||||||
// 0.0 = none
|
// 0.0 = none
|
||||||
// 1.0/8.0 = extreme
|
// 1.0/8.0 = extreme
|
||||||
float2 _warp = float2(1.0/64.0,1.0/24.0);
|
float2 _warp = float2(1.0/64.0,1.0/24.0);
|
||||||
|
|
||||||
// Amount of shadow mask.
|
// Amount of shadow mask.
|
||||||
float _maskDark = 0.5;
|
float _maskDark = 0.5;
|
||||||
float _maskLight = 1.5;
|
float _maskLight = 1.5;
|
||||||
|
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
|
|
||||||
float fract(float x){
|
float fract(float x){
|
||||||
return x-floor(x);
|
return x-floor(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sRGB to Linear.
|
// sRGB to Linear.
|
||||||
// Assuing using sRGB typed textures this should not be needed.
|
// Assuing using sRGB typed textures this should not be needed.
|
||||||
float ToLinear1(float c){return(c<=0.04045)?c/12.92:pow((c+0.055)/1.055,2.4);}
|
float ToLinear1(float c){return(c<=0.04045)?c/12.92:pow((c+0.055)/1.055,2.4);}
|
||||||
float3 ToLinear(float3 c){return float3(ToLinear1(c.r),ToLinear1(c.g),ToLinear1(c.b));}
|
float3 ToLinear(float3 c){return float3(ToLinear1(c.r),ToLinear1(c.g),ToLinear1(c.b));}
|
||||||
|
|
||||||
// Linear to sRGB.
|
// Linear to sRGB.
|
||||||
// Assuing using sRGB typed textures this should not be needed.
|
// Assuing using sRGB typed textures this should not be needed.
|
||||||
float ToSrgb1(float c){return(c<0.0031308?c*12.92:1.055*pow(c,0.41666)-0.055);}
|
float ToSrgb1(float c){return(c<0.0031308?c*12.92:1.055*pow(c,0.41666)-0.055);}
|
||||||
float3 ToSrgb(float3 c){return float3(ToSrgb1(c.r),ToSrgb1(c.g),ToSrgb1(c.b));}
|
float3 ToSrgb(float3 c){return float3(ToSrgb1(c.r),ToSrgb1(c.g),ToSrgb1(c.b));}
|
||||||
|
|
||||||
|
|
||||||
float3 Test(float3 c){return c*(1.0/64.0)+c*c*c;}
|
float3 Test(float3 c){return c*(1.0/64.0)+c*c*c;}
|
||||||
|
|
||||||
// Nearest emulated sample given floating point position and texel offset.
|
// Nearest emulated sample given floating point position and texel offset.
|
||||||
// Also zero's off screen.
|
// Also zero's off screen.
|
||||||
float3 Fetch( float2 pos,float2 off){
|
float3 Fetch( float2 pos,float2 off){
|
||||||
pos=floor(pos*_res+off)/_res;
|
pos=floor(pos*_res+off)/_res;
|
||||||
if(max(abs(pos.x-0.5),abs(pos.y-0.5))>0.5)return float3(0.0,0.0,0.0);
|
if(max(abs(pos.x-0.5),abs(pos.y-0.5))>0.5)return float3(0.0,0.0,0.0);
|
||||||
return Test(ToLinear(tex2D(_MainTex,pos.xy).rgb));}
|
return Test(ToLinear(tex2D(_MainTex,pos.xy).rgb));}
|
||||||
|
|
||||||
// Distance in emulated pixels to nearest texel.
|
// Distance in emulated pixels to nearest texel.
|
||||||
float2 Dist(float2 pos){pos=pos*_res;return -((pos-floor(pos))-float2(0.5,0.5));}
|
float2 Dist(float2 pos){pos=pos*_res;return -((pos-floor(pos))-float2(0.5,0.5));}
|
||||||
|
|
||||||
// 1D Gaussian.
|
// 1D Gaussian.
|
||||||
float Gaus(float pos,float scale){return exp2(scale*pos*pos);}
|
float Gaus(float pos,float scale){return exp2(scale*pos*pos);}
|
||||||
|
|
||||||
// 3-tap Gaussian filter along horz line.
|
// 3-tap Gaussian filter along horz line.
|
||||||
float3 Horz3(float2 pos,float off){
|
float3 Horz3(float2 pos,float off){
|
||||||
float3 b=Fetch(pos,float2(-1.0,off));
|
float3 b=Fetch(pos,float2(-1.0,off));
|
||||||
float3 c=Fetch(pos,float2( 0.0,off));
|
float3 c=Fetch(pos,float2( 0.0,off));
|
||||||
float3 d=Fetch(pos,float2( 1.0,off));
|
float3 d=Fetch(pos,float2( 1.0,off));
|
||||||
float dst=Dist(pos).x;
|
float dst=Dist(pos).x;
|
||||||
// Convert distance to weight.
|
// Convert distance to weight.
|
||||||
float scale=_hardPix;
|
float scale=_hardPix;
|
||||||
float wb=Gaus(dst-1.0,scale);
|
float wb=Gaus(dst-1.0,scale);
|
||||||
float wc=Gaus(dst+0.0,scale);
|
float wc=Gaus(dst+0.0,scale);
|
||||||
float wd=Gaus(dst+1.0,scale);
|
float wd=Gaus(dst+1.0,scale);
|
||||||
// Return filtered sample.
|
// Return filtered sample.
|
||||||
return (b*wb+c*wc+d*wd)/(wb+wc+wd);}
|
return (b*wb+c*wc+d*wd)/(wb+wc+wd);}
|
||||||
|
|
||||||
// 5-tap Gaussian filter along horz line.
|
// 5-tap Gaussian filter along horz line.
|
||||||
float3 Horz5(float2 pos,float off){
|
float3 Horz5(float2 pos,float off){
|
||||||
float3 a=Fetch(pos,float2(-2.0,off));
|
float3 a=Fetch(pos,float2(-2.0,off));
|
||||||
float3 b=Fetch(pos,float2(-1.0,off));
|
float3 b=Fetch(pos,float2(-1.0,off));
|
||||||
float3 c=Fetch(pos,float2( 0.0,off));
|
float3 c=Fetch(pos,float2( 0.0,off));
|
||||||
float3 d=Fetch(pos,float2( 1.0,off));
|
float3 d=Fetch(pos,float2( 1.0,off));
|
||||||
float3 e=Fetch(pos,float2( 2.0,off));
|
float3 e=Fetch(pos,float2( 2.0,off));
|
||||||
float dst=Dist(pos).x;
|
float dst=Dist(pos).x;
|
||||||
// Convert distance to weight.
|
// Convert distance to weight.
|
||||||
float scale=_hardPix;
|
float scale=_hardPix;
|
||||||
float wa=Gaus(dst-2.0,scale);
|
float wa=Gaus(dst-2.0,scale);
|
||||||
float wb=Gaus(dst-1.0,scale);
|
float wb=Gaus(dst-1.0,scale);
|
||||||
float wc=Gaus(dst+0.0,scale);
|
float wc=Gaus(dst+0.0,scale);
|
||||||
float wd=Gaus(dst+1.0,scale);
|
float wd=Gaus(dst+1.0,scale);
|
||||||
float we=Gaus(dst+2.0,scale);
|
float we=Gaus(dst+2.0,scale);
|
||||||
// Return filtered sample.
|
// Return filtered sample.
|
||||||
return (a*wa+b*wb+c*wc+d*wd+e*we)/(wa+wb+wc+wd+we);}
|
return (a*wa+b*wb+c*wc+d*wd+e*we)/(wa+wb+wc+wd+we);}
|
||||||
|
|
||||||
// 7-tap Gaussian filter along horz line.
|
// 7-tap Gaussian filter along horz line.
|
||||||
float3 Horz7(float2 pos,float off){
|
float3 Horz7(float2 pos,float off){
|
||||||
float3 a=Fetch(pos,float2(-3.0,off));
|
float3 a=Fetch(pos,float2(-3.0,off));
|
||||||
float3 b=Fetch(pos,float2(-2.0,off));
|
float3 b=Fetch(pos,float2(-2.0,off));
|
||||||
float3 c=Fetch(pos,float2(-1.0,off));
|
float3 c=Fetch(pos,float2(-1.0,off));
|
||||||
float3 d=Fetch(pos,float2( 0.0,off));
|
float3 d=Fetch(pos,float2( 0.0,off));
|
||||||
float3 e=Fetch(pos,float2( 1.0,off));
|
float3 e=Fetch(pos,float2( 1.0,off));
|
||||||
float3 f=Fetch(pos,float2( 2.0,off));
|
float3 f=Fetch(pos,float2( 2.0,off));
|
||||||
float3 g=Fetch(pos,float2( 3.0,off));
|
float3 g=Fetch(pos,float2( 3.0,off));
|
||||||
float dst=Dist(pos).x;
|
float dst=Dist(pos).x;
|
||||||
// Convert distance to weight.
|
// Convert distance to weight.
|
||||||
float scale=_hardBloomPix;
|
float scale=_hardBloomPix;
|
||||||
float wa=Gaus(dst-3.0,scale);
|
float wa=Gaus(dst-3.0,scale);
|
||||||
float wb=Gaus(dst-2.0,scale);
|
float wb=Gaus(dst-2.0,scale);
|
||||||
float wc=Gaus(dst-1.0,scale);
|
float wc=Gaus(dst-1.0,scale);
|
||||||
float wd=Gaus(dst+0.0,scale);
|
float wd=Gaus(dst+0.0,scale);
|
||||||
float we=Gaus(dst+1.0,scale);
|
float we=Gaus(dst+1.0,scale);
|
||||||
float wf=Gaus(dst+2.0,scale);
|
float wf=Gaus(dst+2.0,scale);
|
||||||
float wg=Gaus(dst+3.0,scale);
|
float wg=Gaus(dst+3.0,scale);
|
||||||
// Return filtered sample.
|
// Return filtered sample.
|
||||||
return (a*wa+b*wb+c*wc+d*wd+e*we+f*wf+g*wg)/(wa+wb+wc+wd+we+wf+wg);}
|
return (a*wa+b*wb+c*wc+d*wd+e*we+f*wf+g*wg)/(wa+wb+wc+wd+we+wf+wg);}
|
||||||
|
|
||||||
// Return scanline weight.
|
// Return scanline weight.
|
||||||
float Scan(float2 pos,float off){
|
float Scan(float2 pos,float off){
|
||||||
float dst=Dist(pos).y;
|
float dst=Dist(pos).y;
|
||||||
return Gaus(dst+off,_hardScan);}
|
return Gaus(dst+off,_hardScan);}
|
||||||
|
|
||||||
// Return scanline weight for bloom.
|
// Return scanline weight for bloom.
|
||||||
float BloomScan(float2 pos,float off){
|
float BloomScan(float2 pos,float off){
|
||||||
float dst=Dist(pos).y;
|
float dst=Dist(pos).y;
|
||||||
return Gaus(dst+off,_hardBloomScan);}
|
return Gaus(dst+off,_hardBloomScan);}
|
||||||
|
|
||||||
// Allow nearest three lines to effect pixel.
|
// Allow nearest three lines to effect pixel.
|
||||||
float3 Tri(float2 pos){
|
float3 Tri(float2 pos){
|
||||||
float3 a=Horz3(pos,-1.0);
|
float3 a=Horz3(pos,-1.0);
|
||||||
float3 b=Horz5(pos, 0.0);
|
float3 b=Horz5(pos, 0.0);
|
||||||
float3 c=Horz3(pos, 1.0);
|
float3 c=Horz3(pos, 1.0);
|
||||||
float wa=Scan(pos,-1.0);
|
float wa=Scan(pos,-1.0);
|
||||||
float wb=Scan(pos, 0.0);
|
float wb=Scan(pos, 0.0);
|
||||||
float wc=Scan(pos, 1.0);
|
float wc=Scan(pos, 1.0);
|
||||||
return a*wa+b*wb+c*wc;}
|
return a*wa+b*wb+c*wc;}
|
||||||
|
|
||||||
// Small bloom.
|
// Small bloom.
|
||||||
float3 Bloom(float2 pos){
|
float3 Bloom(float2 pos){
|
||||||
float3 a=Horz5(pos,-2.0);
|
float3 a=Horz5(pos,-2.0);
|
||||||
float3 b=Horz7(pos,-1.0);
|
float3 b=Horz7(pos,-1.0);
|
||||||
float3 c=Horz7(pos, 0.0);
|
float3 c=Horz7(pos, 0.0);
|
||||||
float3 d=Horz7(pos, 1.0);
|
float3 d=Horz7(pos, 1.0);
|
||||||
float3 e=Horz5(pos, 2.0);
|
float3 e=Horz5(pos, 2.0);
|
||||||
float wa=BloomScan(pos,-2.0);
|
float wa=BloomScan(pos,-2.0);
|
||||||
float wb=BloomScan(pos,-1.0);
|
float wb=BloomScan(pos,-1.0);
|
||||||
float wc=BloomScan(pos, 0.0);
|
float wc=BloomScan(pos, 0.0);
|
||||||
float wd=BloomScan(pos, 1.0);
|
float wd=BloomScan(pos, 1.0);
|
||||||
float we=BloomScan(pos, 2.0);
|
float we=BloomScan(pos, 2.0);
|
||||||
return a*wa+b*wb+c*wc+d*wd+e*we;}
|
return a*wa+b*wb+c*wc+d*wd+e*we;}
|
||||||
|
|
||||||
// Distortion of scanlines, and end of screen alpha.
|
// Distortion of scanlines, and end of screen alpha.
|
||||||
float2 Warp(float2 pos){
|
float2 Warp(float2 pos){
|
||||||
|
|
||||||
pos=pos*2.0-1.0;
|
pos=pos*2.0-1.0;
|
||||||
pos*=float2(1.0+(pos.y*pos.y)*_warp.x,1.0+(pos.x*pos.x)*_warp.y);
|
pos*=float2(1.0+(pos.y*pos.y)*_warp.x,1.0+(pos.x*pos.x)*_warp.y);
|
||||||
return pos*0.5+0.5;}
|
return pos*0.5+0.5;}
|
||||||
|
|
||||||
#if defined(_MASKSTYLE_TVSTYLE)
|
#if defined(_MASKSTYLE_TVSTYLE)
|
||||||
// Very compressed TV style shadow mask.
|
// Very compressed TV style shadow mask.
|
||||||
float3 Mask(float2 pos){
|
float3 Mask(float2 pos){
|
||||||
float lineee=_maskLight;
|
float lineee=_maskLight;
|
||||||
float odd=0.0;
|
float odd=0.0;
|
||||||
if(fract(pos.x/6.0)<0.5)odd=1.0;
|
if(fract(pos.x/6.0)<0.5)odd=1.0;
|
||||||
if(fract((pos.y+odd)/2.0)<0.5) lineee=_maskDark;
|
if(fract((pos.y+odd)/2.0)<0.5) lineee=_maskDark;
|
||||||
pos.x=fract(pos.x/3.0);
|
pos.x=fract(pos.x/3.0);
|
||||||
float3 mask=float3(_maskDark,_maskDark,_maskDark);
|
float3 mask=float3(_maskDark,_maskDark,_maskDark);
|
||||||
if(pos.x<0.333)mask.r=_maskLight;
|
if(pos.x<0.333)mask.r=_maskLight;
|
||||||
else if(pos.x<0.666)mask.g=_maskLight;
|
else if(pos.x<0.666)mask.g=_maskLight;
|
||||||
else mask.b=_maskLight;
|
else mask.b=_maskLight;
|
||||||
mask*=lineee;
|
mask*=lineee;
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
#elif defined(_MASKSTYLE_APERTUREGRILLE)
|
#elif defined(_MASKSTYLE_APERTUREGRILLE)
|
||||||
// Aperture-grille.
|
// Aperture-grille.
|
||||||
float3 Mask(float2 pos){
|
float3 Mask(float2 pos){
|
||||||
pos.x=fract(pos.x/3.0);
|
pos.x=fract(pos.x/3.0);
|
||||||
float3 mask=float3(_maskDark,_maskDark,_maskDark);
|
float3 mask=float3(_maskDark,_maskDark,_maskDark);
|
||||||
if(pos.x<0.333)mask.r=_maskLight;
|
if(pos.x<0.333)mask.r=_maskLight;
|
||||||
else if(pos.x<0.666)mask.g=_maskLight;
|
else if(pos.x<0.666)mask.g=_maskLight;
|
||||||
else mask.b=_maskLight;
|
else mask.b=_maskLight;
|
||||||
return mask;}
|
return mask;}
|
||||||
#elif defined(_MASKSTYLE_STRETCHEDVGA)
|
#elif defined(_MASKSTYLE_STRETCHEDVGA)
|
||||||
// Stretched VGA style shadow mask (same as prior shaders).
|
// Stretched VGA style shadow mask (same as prior shaders).
|
||||||
float3 Mask(float2 pos){
|
float3 Mask(float2 pos){
|
||||||
pos.x+=pos.y*3.0;
|
pos.x+=pos.y*3.0;
|
||||||
float3 mask=float3(_maskDark,_maskDark,_maskDark);
|
float3 mask=float3(_maskDark,_maskDark,_maskDark);
|
||||||
pos.x=fract(pos.x/6.0);
|
pos.x=fract(pos.x/6.0);
|
||||||
if(pos.x<0.333)mask.r=_maskLight;
|
if(pos.x<0.333)mask.r=_maskLight;
|
||||||
else if(pos.x<0.666)mask.g=_maskLight;
|
else if(pos.x<0.666)mask.g=_maskLight;
|
||||||
else mask.b=_maskLight;
|
else mask.b=_maskLight;
|
||||||
return mask;}
|
return mask;}
|
||||||
#elif defined(_MASKSTYLE_VGASTYLE)
|
#elif defined(_MASKSTYLE_VGASTYLE)
|
||||||
// VGA style shadow mask.
|
// VGA style shadow mask.
|
||||||
float3 Mask(float2 pos){
|
float3 Mask(float2 pos){
|
||||||
pos.xy=floor(pos.xy*float2(1.0,0.5));
|
pos.xy=floor(pos.xy*float2(1.0,0.5));
|
||||||
pos.x+=pos.y*3.0;
|
pos.x+=pos.y*3.0;
|
||||||
float3 mask=float3(_maskDark,_maskDark,_maskDark);
|
float3 mask=float3(_maskDark,_maskDark,_maskDark);
|
||||||
pos.x=fract(pos.x/6.0);
|
pos.x=fract(pos.x/6.0);
|
||||||
if(pos.x<0.333)mask.r=_maskLight;
|
if(pos.x<0.333)mask.r=_maskLight;
|
||||||
else if(pos.x<0.666)mask.g=_maskLight;
|
else if(pos.x<0.666)mask.g=_maskLight;
|
||||||
else mask.b=_maskLight;
|
else mask.b=_maskLight;
|
||||||
return mask;}
|
return mask;}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Draw dividing bars.
|
// Draw dividing bars.
|
||||||
float Bar(float pos,float bar){pos-=bar;return pos*pos<4.0?0.0:1.0;}
|
float Bar(float pos,float bar){pos-=bar;return pos*pos<4.0?0.0:1.0;}
|
||||||
|
|
||||||
// Entry.
|
// Entry.
|
||||||
float4 mainImage(float2 fragCoord){
|
float4 mainImage(float2 fragCoord){
|
||||||
|
|
||||||
float4 fragColor = float4(1,1,1,1);
|
float4 fragColor = float4(1,1,1,1);
|
||||||
float2 pos=Warp(fragCoord.xy/_iResolution.xy);
|
float2 pos=Warp(fragCoord.xy/_iResolution.xy);
|
||||||
|
|
||||||
fragColor.rgb=Tri(pos)*Mask(fragCoord.xy);
|
fragColor.rgb=Tri(pos)*Mask(fragCoord.xy);
|
||||||
|
|
||||||
fragColor.rgb+=Bloom(pos)*_bloomAmount;
|
fragColor.rgb+=Bloom(pos)*_bloomAmount;
|
||||||
|
|
||||||
fragColor.a=1.0;
|
fragColor.a=1.0;
|
||||||
fragColor.rgb=ToSrgb(fragColor.rgb);
|
fragColor.rgb=ToSrgb(fragColor.rgb);
|
||||||
|
|
||||||
return fragColor;
|
return fragColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct v2f
|
struct v2f
|
||||||
{
|
{
|
||||||
float4 pos : POSITION;
|
float4 pos : POSITION;
|
||||||
float2 uv : TEXCOORD0;
|
float2 uv : TEXCOORD0;
|
||||||
};
|
};
|
||||||
|
|
||||||
fixed4 frag (v2f i) : SV_Target
|
fixed4 frag (v2f i) : SV_Target
|
||||||
{
|
{
|
||||||
float2 pos = _iResolution.xy*i.uv;
|
float2 pos = _iResolution.xy*i.uv;
|
||||||
fixed4 col = mainImage(pos);
|
fixed4 col = mainImage(pos);
|
||||||
return col;
|
return col;
|
||||||
}
|
}
|
||||||
ENDCG
|
ENDCG
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,28 +1,28 @@
|
|||||||
using AxibugEmuOnline.Client;
|
using AxibugEmuOnline.Client;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Rendering.PostProcessing;
|
using UnityEngine.Rendering.PostProcessing;
|
||||||
|
|
||||||
[System.Serializable]
|
[System.Serializable]
|
||||||
[PostProcess(typeof(MattiasCRTRenderer), PostProcessEvent.BeforeStack, "Filter/MattiasCRT")]
|
[PostProcess(typeof(MattiasCRTRenderer), PostProcessEvent.BeforeStack, "Filter/MattiasCRT")]
|
||||||
public sealed class MattiasCRT : FilterEffect
|
public sealed class MattiasCRT : FilterEffect
|
||||||
{
|
{
|
||||||
public override string Name => nameof(MattiasCRT);
|
public override string Name => nameof(MattiasCRT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class MattiasCRTRenderer : PostProcessEffectRenderer<MattiasCRT>
|
public sealed class MattiasCRTRenderer : PostProcessEffectRenderer<MattiasCRT>
|
||||||
{
|
{
|
||||||
private Shader shader;
|
private Shader shader;
|
||||||
private Material material;
|
private Material material;
|
||||||
|
|
||||||
public override void Init()
|
public override void Init()
|
||||||
{
|
{
|
||||||
shader = Shader.Find("Filter/MattiasCRT");
|
shader = Shader.Find("Filter/MattiasCRT");
|
||||||
material = new Material(shader);
|
material = new Material(shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Render(PostProcessRenderContext context)
|
public override void Render(PostProcessRenderContext context)
|
||||||
{
|
{
|
||||||
material.SetVector("_iResolution", new Vector4(Screen.width, Screen.height, 0, 0));
|
material.SetVector("_iResolution", new Vector4(Screen.width, Screen.height, 0, 0));
|
||||||
context.command.Blit(context.source, context.destination, material);
|
context.command.Blit(context.source, context.destination, material);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,98 +1,98 @@
|
|||||||
|
|
||||||
Shader "Filter/MattiasCRT"
|
Shader "Filter/MattiasCRT"
|
||||||
{
|
{
|
||||||
Properties
|
Properties
|
||||||
{
|
{
|
||||||
_MainTex ("Base (RGB)", 2D) = "white" {}
|
_MainTex ("Base (RGB)", 2D) = "white" {}
|
||||||
}
|
}
|
||||||
SubShader
|
SubShader
|
||||||
{
|
{
|
||||||
Pass
|
Pass
|
||||||
{
|
{
|
||||||
CGPROGRAM
|
CGPROGRAM
|
||||||
|
|
||||||
#pragma vertex vert_img
|
#pragma vertex vert_img
|
||||||
#pragma fragment frag
|
#pragma fragment frag
|
||||||
#include "UnityCG.cginc"
|
#include "UnityCG.cginc"
|
||||||
|
|
||||||
sampler2D _MainTex;
|
sampler2D _MainTex;
|
||||||
float4 _MainTex_TexelSize;
|
float4 _MainTex_TexelSize;
|
||||||
float2 _iResolution;
|
float2 _iResolution;
|
||||||
|
|
||||||
float2 curve(float2 uv)
|
float2 curve(float2 uv)
|
||||||
{
|
{
|
||||||
uv = (uv - 0.5) * 2.0;
|
uv = (uv - 0.5) * 2.0;
|
||||||
uv *= 1.1;
|
uv *= 1.1;
|
||||||
uv.x *= 1.0 + pow((abs(uv.y) / 5.0), 2.0);
|
uv.x *= 1.0 + pow((abs(uv.y) / 5.0), 2.0);
|
||||||
uv.y *= 1.0 + pow((abs(uv.x) / 4.0), 2.0);
|
uv.y *= 1.0 + pow((abs(uv.x) / 4.0), 2.0);
|
||||||
uv = (uv / 2.0) + 0.5;
|
uv = (uv / 2.0) + 0.5;
|
||||||
uv = uv *0.92 + 0.04;
|
uv = uv *0.92 + 0.04;
|
||||||
return uv;
|
return uv;
|
||||||
}
|
}
|
||||||
|
|
||||||
float4 mainImage( float2 fragCoord )
|
float4 mainImage( float2 fragCoord )
|
||||||
{
|
{
|
||||||
float4 fragColor = float4(0,0,0,1);
|
float4 fragColor = float4(0,0,0,1);
|
||||||
|
|
||||||
float2 q = fragCoord.xy / _iResolution.xy;
|
float2 q = fragCoord.xy / _iResolution.xy;
|
||||||
float2 uv = q;
|
float2 uv = q;
|
||||||
uv = curve( uv );
|
uv = curve( uv );
|
||||||
float3 oricol = tex2D(_MainTex,uv).xyz;
|
float3 oricol = tex2D(_MainTex,uv).xyz;
|
||||||
float3 col;
|
float3 col;
|
||||||
float x = sin(0.3*_Time+uv.y*21.0)*sin(0.7*_Time+uv.y*29.0)*sin(0.3+0.33*_Time+uv.y*31.0)*0.0017;
|
float x = sin(0.3*_Time+uv.y*21.0)*sin(0.7*_Time+uv.y*29.0)*sin(0.3+0.33*_Time+uv.y*31.0)*0.0017;
|
||||||
|
|
||||||
col.r = tex2D(_MainTex,float2(x+uv.x+0.001,uv.y+0.001)).x+0.05;
|
col.r = tex2D(_MainTex,float2(x+uv.x+0.001,uv.y+0.001)).x+0.05;
|
||||||
col.g = tex2D(_MainTex,float2(x+uv.x+0.000,uv.y-0.002)).y+0.05;
|
col.g = tex2D(_MainTex,float2(x+uv.x+0.000,uv.y-0.002)).y+0.05;
|
||||||
col.b = tex2D(_MainTex,float2(x+uv.x-0.002,uv.y+0.000)).z+0.05;
|
col.b = tex2D(_MainTex,float2(x+uv.x-0.002,uv.y+0.000)).z+0.05;
|
||||||
col.r += 0.08*tex2D(_MainTex,0.75*float2(x+0.025, -0.027)+float2(uv.x+0.001,uv.y+0.001)).x;
|
col.r += 0.08*tex2D(_MainTex,0.75*float2(x+0.025, -0.027)+float2(uv.x+0.001,uv.y+0.001)).x;
|
||||||
col.g += 0.05*tex2D(_MainTex,0.75*float2(x+-0.022, -0.02)+float2(uv.x+0.000,uv.y-0.002)).y;
|
col.g += 0.05*tex2D(_MainTex,0.75*float2(x+-0.022, -0.02)+float2(uv.x+0.000,uv.y-0.002)).y;
|
||||||
col.b += 0.08*tex2D(_MainTex,0.75*float2(x+-0.02, -0.018)+float2(uv.x-0.002,uv.y+0.000)).z;
|
col.b += 0.08*tex2D(_MainTex,0.75*float2(x+-0.02, -0.018)+float2(uv.x-0.002,uv.y+0.000)).z;
|
||||||
|
|
||||||
col = clamp(col*0.6+0.4*col*col*1.0,0.0,1.0);
|
col = clamp(col*0.6+0.4*col*col*1.0,0.0,1.0);
|
||||||
|
|
||||||
float vig = (0.0 + 1.0*16.0*uv.x*uv.y*(1.0-uv.x)*(1.0-uv.y));
|
float vig = (0.0 + 1.0*16.0*uv.x*uv.y*(1.0-uv.x)*(1.0-uv.y));
|
||||||
col *= pow(vig,0.3);
|
col *= pow(vig,0.3);
|
||||||
|
|
||||||
col *= float3(0.95,1.05,0.95);
|
col *= float3(0.95,1.05,0.95);
|
||||||
col *= 2.8;
|
col *= 2.8;
|
||||||
|
|
||||||
float scans = clamp( 0.35+0.35*sin(3.5*_Time+uv.y*_iResolution.y*1.5), 0.0, 1.0);
|
float scans = clamp( 0.35+0.35*sin(3.5*_Time+uv.y*_iResolution.y*1.5), 0.0, 1.0);
|
||||||
|
|
||||||
float s = pow(scans,1.7);
|
float s = pow(scans,1.7);
|
||||||
col = col*( 0.4+0.7*s) ;
|
col = col*( 0.4+0.7*s) ;
|
||||||
|
|
||||||
col *= 1.0+0.01*sin(110.0*_Time);
|
col *= 1.0+0.01*sin(110.0*_Time);
|
||||||
if (uv.x < 0.0 || uv.x > 1.0)
|
if (uv.x < 0.0 || uv.x > 1.0)
|
||||||
col *= 0.0;
|
col *= 0.0;
|
||||||
if (uv.y < 0.0 || uv.y > 1.0)
|
if (uv.y < 0.0 || uv.y > 1.0)
|
||||||
col *= 0.0;
|
col *= 0.0;
|
||||||
|
|
||||||
|
|
||||||
col*=1.0-0.65*clamp((fragCoord.x % 2.0 -1.0 )*2.0,0.0,1.0);
|
col*=1.0-0.65*clamp((fragCoord.x % 2.0 -1.0 )*2.0,0.0,1.0);
|
||||||
|
|
||||||
float comp = smoothstep( 0.1, 0.9, sin(_Time) );
|
float comp = smoothstep( 0.1, 0.9, sin(_Time) );
|
||||||
|
|
||||||
fragColor = float4(col,1.0);
|
fragColor = float4(col,1.0);
|
||||||
|
|
||||||
return fragColor;
|
return fragColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct v2f
|
struct v2f
|
||||||
{
|
{
|
||||||
float4 pos : POSITION;
|
float4 pos : POSITION;
|
||||||
float2 uv : TEXCOORD0;
|
float2 uv : TEXCOORD0;
|
||||||
};
|
};
|
||||||
|
|
||||||
fixed4 frag (v2f i) : SV_Target
|
fixed4 frag (v2f i) : SV_Target
|
||||||
{
|
{
|
||||||
float2 pos = _iResolution.xy*i.uv;
|
float2 pos = _iResolution.xy*i.uv;
|
||||||
fixed4 col = mainImage(pos);
|
fixed4 col = mainImage(pos);
|
||||||
return col;
|
return col;
|
||||||
}
|
}
|
||||||
ENDCG
|
ENDCG
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,30 +1,30 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace AxibugEmuOnline.Client
|
namespace AxibugEmuOnline.Client
|
||||||
{
|
{
|
||||||
public interface IEmuCore
|
public interface IEmuCore
|
||||||
{
|
{
|
||||||
GameObject gameObject { get; }
|
GameObject gameObject { get; }
|
||||||
|
|
||||||
object GetState();
|
object GetState();
|
||||||
byte[] GetStateBytes();
|
byte[] GetStateBytes();
|
||||||
void LoadState(object state);
|
void LoadState(object state);
|
||||||
void LoadStateFromBytes(byte[] data);
|
void LoadStateFromBytes(byte[] data);
|
||||||
void Pause();
|
void Pause();
|
||||||
void Resume();
|
void Resume();
|
||||||
void SetupScheme();
|
void SetupScheme();
|
||||||
void StartGame(RomFile romFile);
|
void StartGame(RomFile romFile);
|
||||||
void DoReset();
|
void DoReset();
|
||||||
EnumPlatform Platform { get; }
|
EnumPlatform Platform { get; }
|
||||||
uint Frame { get; }
|
uint Frame { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class IEnumCoreTool
|
public static class IEnumCoreTool
|
||||||
{
|
{
|
||||||
public static bool IsNull(this IEmuCore core)
|
public static bool IsNull(this IEmuCore core)
|
||||||
{
|
{
|
||||||
if (core == null) return true;
|
if (core == null) return true;
|
||||||
return core.Equals(null);
|
return core.Equals(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,8 +1,8 @@
|
|||||||
namespace AxibugEmuOnline.Client
|
namespace AxibugEmuOnline.Client
|
||||||
{
|
{
|
||||||
public abstract class CommandChanger : IKeyMapperChanger
|
public abstract class CommandChanger : IKeyMapperChanger
|
||||||
{
|
{
|
||||||
public string Name => GetType().Name;
|
public string Name => GetType().Name;
|
||||||
public abstract object GetConfig();
|
public abstract object GetConfig();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,26 +1,26 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace AxibugEmuOnline.Client
|
namespace AxibugEmuOnline.Client
|
||||||
{
|
{
|
||||||
public class GamingChanger : CommandChanger
|
public class GamingChanger : CommandChanger
|
||||||
{
|
{
|
||||||
|
|
||||||
Dictionary<KeyCode, EnumCommand> m_uiKeyMapper = new Dictionary<KeyCode, EnumCommand>();
|
Dictionary<KeyCode, EnumCommand> m_uiKeyMapper = new Dictionary<KeyCode, EnumCommand>();
|
||||||
public GamingChanger()
|
public GamingChanger()
|
||||||
{
|
{
|
||||||
m_uiKeyMapper[KeyCode.Escape] = EnumCommand.OptionMenu;
|
m_uiKeyMapper[KeyCode.Escape] = EnumCommand.OptionMenu;
|
||||||
|
|
||||||
if (Application.platform == RuntimePlatform.PSP2)
|
if (Application.platform == RuntimePlatform.PSP2)
|
||||||
{
|
{
|
||||||
m_uiKeyMapper[Common.PSVitaKey.L] = EnumCommand.OptionMenu;
|
m_uiKeyMapper[Common.PSVitaKey.L] = EnumCommand.OptionMenu;
|
||||||
m_uiKeyMapper[Common.PSVitaKey.R] = EnumCommand.OptionMenu;
|
m_uiKeyMapper[Common.PSVitaKey.R] = EnumCommand.OptionMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
//PC XBOX
|
//PC XBOX
|
||||||
m_uiKeyMapper[Common.PC_XBOXKEY.Y] = EnumCommand.OptionMenu;
|
m_uiKeyMapper[Common.PC_XBOXKEY.Y] = EnumCommand.OptionMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override object GetConfig() => m_uiKeyMapper;
|
public override object GetConfig() => m_uiKeyMapper;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,54 +1,54 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace AxibugEmuOnline.Client
|
namespace AxibugEmuOnline.Client
|
||||||
{
|
{
|
||||||
|
|
||||||
public class NormalChanger : CommandChanger
|
public class NormalChanger : CommandChanger
|
||||||
{
|
{
|
||||||
Dictionary<KeyCode, EnumCommand> m_uiKeyMapper = new Dictionary<KeyCode, EnumCommand>();
|
Dictionary<KeyCode, EnumCommand> m_uiKeyMapper = new Dictionary<KeyCode, EnumCommand>();
|
||||||
public NormalChanger()
|
public NormalChanger()
|
||||||
{
|
{
|
||||||
m_uiKeyMapper[KeyCode.A] = EnumCommand.SelectItemLeft;
|
m_uiKeyMapper[KeyCode.A] = EnumCommand.SelectItemLeft;
|
||||||
m_uiKeyMapper[KeyCode.D] = EnumCommand.SelectItemRight;
|
m_uiKeyMapper[KeyCode.D] = EnumCommand.SelectItemRight;
|
||||||
m_uiKeyMapper[KeyCode.W] = EnumCommand.SelectItemUp;
|
m_uiKeyMapper[KeyCode.W] = EnumCommand.SelectItemUp;
|
||||||
m_uiKeyMapper[KeyCode.S] = EnumCommand.SelectItemDown;
|
m_uiKeyMapper[KeyCode.S] = EnumCommand.SelectItemDown;
|
||||||
m_uiKeyMapper[KeyCode.K] = EnumCommand.Enter;
|
m_uiKeyMapper[KeyCode.K] = EnumCommand.Enter;
|
||||||
m_uiKeyMapper[KeyCode.L] = EnumCommand.Back;
|
m_uiKeyMapper[KeyCode.L] = EnumCommand.Back;
|
||||||
m_uiKeyMapper[KeyCode.I] = EnumCommand.OptionMenu;
|
m_uiKeyMapper[KeyCode.I] = EnumCommand.OptionMenu;
|
||||||
|
|
||||||
m_uiKeyMapper[KeyCode.LeftArrow] = EnumCommand.SelectItemLeft;
|
m_uiKeyMapper[KeyCode.LeftArrow] = EnumCommand.SelectItemLeft;
|
||||||
m_uiKeyMapper[KeyCode.RightArrow] = EnumCommand.SelectItemRight;
|
m_uiKeyMapper[KeyCode.RightArrow] = EnumCommand.SelectItemRight;
|
||||||
m_uiKeyMapper[KeyCode.UpArrow] = EnumCommand.SelectItemUp;
|
m_uiKeyMapper[KeyCode.UpArrow] = EnumCommand.SelectItemUp;
|
||||||
m_uiKeyMapper[KeyCode.DownArrow] = EnumCommand.SelectItemDown;
|
m_uiKeyMapper[KeyCode.DownArrow] = EnumCommand.SelectItemDown;
|
||||||
m_uiKeyMapper[KeyCode.Return] = EnumCommand.Enter;
|
m_uiKeyMapper[KeyCode.Return] = EnumCommand.Enter;
|
||||||
m_uiKeyMapper[KeyCode.Escape] = EnumCommand.Back;
|
m_uiKeyMapper[KeyCode.Escape] = EnumCommand.Back;
|
||||||
m_uiKeyMapper[KeyCode.RightShift] = EnumCommand.OptionMenu;
|
m_uiKeyMapper[KeyCode.RightShift] = EnumCommand.OptionMenu;
|
||||||
m_uiKeyMapper[KeyCode.LeftShift] = EnumCommand.OptionMenu;
|
m_uiKeyMapper[KeyCode.LeftShift] = EnumCommand.OptionMenu;
|
||||||
|
|
||||||
if (Application.platform == RuntimePlatform.PSP2)
|
if (Application.platform == RuntimePlatform.PSP2)
|
||||||
{
|
{
|
||||||
m_uiKeyMapper[Common.PSVitaKey.Left] = EnumCommand.SelectItemLeft;
|
m_uiKeyMapper[Common.PSVitaKey.Left] = EnumCommand.SelectItemLeft;
|
||||||
m_uiKeyMapper[Common.PSVitaKey.Right] = EnumCommand.SelectItemRight;
|
m_uiKeyMapper[Common.PSVitaKey.Right] = EnumCommand.SelectItemRight;
|
||||||
m_uiKeyMapper[Common.PSVitaKey.Up] = EnumCommand.SelectItemUp;
|
m_uiKeyMapper[Common.PSVitaKey.Up] = EnumCommand.SelectItemUp;
|
||||||
m_uiKeyMapper[Common.PSVitaKey.Down] = EnumCommand.SelectItemDown;
|
m_uiKeyMapper[Common.PSVitaKey.Down] = EnumCommand.SelectItemDown;
|
||||||
m_uiKeyMapper[Common.PSVitaKey.Circle] = EnumCommand.Enter;
|
m_uiKeyMapper[Common.PSVitaKey.Circle] = EnumCommand.Enter;
|
||||||
m_uiKeyMapper[Common.PSVitaKey.Cross] = EnumCommand.Back;
|
m_uiKeyMapper[Common.PSVitaKey.Cross] = EnumCommand.Back;
|
||||||
m_uiKeyMapper[Common.PSVitaKey.Triangle] = EnumCommand.OptionMenu;
|
m_uiKeyMapper[Common.PSVitaKey.Triangle] = EnumCommand.OptionMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
//PC XBOX
|
//PC XBOX
|
||||||
|
|
||||||
//m_uiKeyMapper[Common.PC_XBOXKEY.Left] = EnumCommand.SelectItemLeft;
|
//m_uiKeyMapper[Common.PC_XBOXKEY.Left] = EnumCommand.SelectItemLeft;
|
||||||
//m_uiKeyMapper[Common.PSVitaKey.Right] = EnumCommand.SelectItemRight;
|
//m_uiKeyMapper[Common.PSVitaKey.Right] = EnumCommand.SelectItemRight;
|
||||||
//m_uiKeyMapper[Common.PSVitaKey.Up] = EnumCommand.SelectItemUp;
|
//m_uiKeyMapper[Common.PSVitaKey.Up] = EnumCommand.SelectItemUp;
|
||||||
//m_uiKeyMapper[Common.PSVitaKey.Down] = EnumCommand.SelectItemDown;
|
//m_uiKeyMapper[Common.PSVitaKey.Down] = EnumCommand.SelectItemDown;
|
||||||
m_uiKeyMapper[Common.PC_XBOXKEY.MenuBtn] = EnumCommand.Enter;
|
m_uiKeyMapper[Common.PC_XBOXKEY.MenuBtn] = EnumCommand.Enter;
|
||||||
m_uiKeyMapper[Common.PC_XBOXKEY.ViewBtn] = EnumCommand.Back;
|
m_uiKeyMapper[Common.PC_XBOXKEY.ViewBtn] = EnumCommand.Back;
|
||||||
m_uiKeyMapper[Common.PC_XBOXKEY.Y] = EnumCommand.OptionMenu;
|
m_uiKeyMapper[Common.PC_XBOXKEY.Y] = EnumCommand.OptionMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override object GetConfig() => m_uiKeyMapper;
|
public override object GetConfig() => m_uiKeyMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
20
AxibugEmuOnline.Client/Assets/Script/AppMain/Initer.cs
Normal file
20
AxibugEmuOnline.Client/Assets/Script/AppMain/Initer.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using AxibugEmuOnline.Client.ClientCore;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Rendering.PostProcessing;
|
||||||
|
|
||||||
|
namespace AxibugEmuOnline.Client
|
||||||
|
{
|
||||||
|
public class Initer : MonoBehaviour
|
||||||
|
{
|
||||||
|
public PostProcessVolume m_filterVolume;
|
||||||
|
public CanvasGroup m_filterPreview;
|
||||||
|
public CanvasGroup m_xmbBg;
|
||||||
|
public static string dev_UUID;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
App.Init(this);
|
||||||
|
dev_UUID = SystemInfo.deviceUniqueIdentifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
AxibugEmuOnline.Client/Assets/Script/AppMain/Initer.cs.meta
Normal file
11
AxibugEmuOnline.Client/Assets/Script/AppMain/Initer.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 980f937ad27ad8540afeb8b7f100997e
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: -1100
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 437646a1943eaf34dbe1a56eb38494bb
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -1,80 +1,80 @@
|
|||||||
using AxibugEmuOnline.Client.ClientCore;
|
using AxibugEmuOnline.Client.ClientCore;
|
||||||
using AxibugEmuOnline.Client.Event;
|
using AxibugEmuOnline.Client.Event;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace AxibugEmuOnline.Client.Manager
|
namespace AxibugEmuOnline.Client.Manager
|
||||||
{
|
{
|
||||||
public class AppEmu
|
public class AppEmu
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// unity的c#实现有bug,以接口类型保存的monobehaviour引用,!=和==运算符没有调用到monobehaviour重写过的运算符
|
/// unity的c#实现有bug,以接口类型保存的monobehaviour引用,!=和==运算符没有调用到monobehaviour重写过的运算符
|
||||||
/// 但是Equals方法可以,所以,这个接口判断为空请使用Equals
|
/// 但是Equals方法可以,所以,这个接口判断为空请使用Equals
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private IEmuCore m_emuCore;
|
private IEmuCore m_emuCore;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// unity的c#实现有bug,以接口类型保存的monobehaviour引用,!=和==运算符没有调用到monobehaviour重写过的运算符
|
/// unity的c#实现有bug,以接口类型保存的monobehaviour引用,!=和==运算符没有调用到monobehaviour重写过的运算符
|
||||||
/// 但是Equals方法可以,所以,这个接口判断为空请使用Equals
|
/// 但是Equals方法可以,所以,这个接口判断为空请使用Equals
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEmuCore Core => m_emuCore;
|
public IEmuCore Core => m_emuCore;
|
||||||
|
|
||||||
public AppEmu()
|
public AppEmu()
|
||||||
{
|
{
|
||||||
Eventer.Instance.RegisterEvent(EEvent.OnMineJoinRoom, OnSelfJoinRoom);
|
Eventer.Instance.RegisterEvent(EEvent.OnMineJoinRoom, OnSelfJoinRoom);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSelfJoinRoom()
|
private void OnSelfJoinRoom()
|
||||||
{
|
{
|
||||||
//如果当前正在游戏中,就先结束游戏
|
//如果当前正在游戏中,就先结束游戏
|
||||||
if (!m_emuCore.IsNull()) StopGame();
|
if (!m_emuCore.IsNull()) StopGame();
|
||||||
|
|
||||||
var roomInfo = App.roomMgr.mineRoomMiniInfo;
|
var roomInfo = App.roomMgr.mineRoomMiniInfo;
|
||||||
roomInfo.FetchRomFileInRoomInfo(EnumPlatform.NES, (room, romFile) =>
|
roomInfo.FetchRomFileInRoomInfo(EnumPlatform.NES, (room, romFile) =>
|
||||||
{
|
{
|
||||||
if (!romFile.RomReady) //这个rom并没有下载,所以取消进入房间
|
if (!romFile.RomReady) //这个rom并没有下载,所以取消进入房间
|
||||||
{
|
{
|
||||||
App.roomMgr.SendLeavnRoom();
|
App.roomMgr.SendLeavnRoom();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BeginGame(romFile);
|
BeginGame(romFile);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void BeginGame(RomFile romFile)
|
public void BeginGame(RomFile romFile)
|
||||||
{
|
{
|
||||||
if (!m_emuCore.IsNull()) return;
|
if (!m_emuCore.IsNull()) return;
|
||||||
|
|
||||||
switch (romFile.Platform)
|
switch (romFile.Platform)
|
||||||
{
|
{
|
||||||
case EnumPlatform.NES:
|
case EnumPlatform.NES:
|
||||||
m_emuCore = GameObject.Instantiate(Resources.Load<GameObject>("NES/NesEmulator")).GetComponent<IEmuCore>();
|
m_emuCore = GameObject.Instantiate(Resources.Load<GameObject>("NES/NesEmulator")).GetComponent<IEmuCore>();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_emuCore.StartGame(romFile);
|
m_emuCore.StartGame(romFile);
|
||||||
LaunchUI.Instance.HideMainMenu();
|
LaunchUI.Instance.HideMainMenu();
|
||||||
InGameUI.Instance.Show(romFile, m_emuCore);
|
InGameUI.Instance.Show(romFile, m_emuCore);
|
||||||
|
|
||||||
m_emuCore.SetupScheme();
|
m_emuCore.SetupScheme();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StopGame()
|
public void StopGame()
|
||||||
{
|
{
|
||||||
if (m_emuCore.IsNull()) return;
|
if (m_emuCore.IsNull()) return;
|
||||||
GameObject.Destroy(m_emuCore.gameObject);
|
GameObject.Destroy(m_emuCore.gameObject);
|
||||||
m_emuCore = null;
|
m_emuCore = null;
|
||||||
|
|
||||||
InGameUI.Instance.Hide();
|
InGameUI.Instance.Hide();
|
||||||
LaunchUI.Instance.ShowMainMenu();
|
LaunchUI.Instance.ShowMainMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResetGame()
|
public void ResetGame()
|
||||||
{
|
{
|
||||||
if (m_emuCore.IsNull()) return;
|
if (m_emuCore.IsNull()) return;
|
||||||
|
|
||||||
m_emuCore.DoReset();
|
m_emuCore.DoReset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
456
AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppRoom.cs
Normal file
456
AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppRoom.cs
Normal file
@ -0,0 +1,456 @@
|
|||||||
|
using AxibugEmuOnline.Client.ClientCore;
|
||||||
|
using AxibugEmuOnline.Client.Common;
|
||||||
|
using AxibugEmuOnline.Client.Event;
|
||||||
|
using AxibugEmuOnline.Client.Network;
|
||||||
|
using AxibugProtobuf;
|
||||||
|
using AxiReplay;
|
||||||
|
using Google.Protobuf;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace AxibugEmuOnline.Client.Manager
|
||||||
|
{
|
||||||
|
public class AppRoom
|
||||||
|
{
|
||||||
|
public Protobuf_Room_MiniInfo mineRoomMiniInfo { get; private set; } = null;
|
||||||
|
public bool InRoom => mineRoomMiniInfo != null;
|
||||||
|
public bool IsHost => mineRoomMiniInfo?.HostPlayerUID == App.user.userdata.UID;
|
||||||
|
public bool IsScreenProviderUID => mineRoomMiniInfo?.ScreenProviderUID == App.user.userdata.UID;
|
||||||
|
public RoomGameState RoomState => mineRoomMiniInfo.GameState;
|
||||||
|
public int MinePlayerIdx => GetMinePlayerIndex();
|
||||||
|
public int WaitStep { get; private set; } = -1;
|
||||||
|
public byte[] RawData { get; private set; } = null;
|
||||||
|
public NetReplay netReplay { get; private set; }
|
||||||
|
|
||||||
|
Dictionary<int, Protobuf_Room_MiniInfo> dictRoomListID2Info = new Dictionary<int, Protobuf_Room_MiniInfo>();
|
||||||
|
|
||||||
|
struct S_PlayerMiniInfo
|
||||||
|
{
|
||||||
|
public long UID;
|
||||||
|
public string NickName;
|
||||||
|
}
|
||||||
|
|
||||||
|
Protobuf_Room_List _Protobuf_Room_List = new Protobuf_Room_List();
|
||||||
|
Protobuf_Room_Get_Screen _Protobuf_Room_Get_Screen = new Protobuf_Room_Get_Screen();
|
||||||
|
Protobuf_Room_Create _Protobuf_Room_Create = new Protobuf_Room_Create();
|
||||||
|
Protobuf_Room_Join _Protobuf_Room_Join = new Protobuf_Room_Join();
|
||||||
|
Protobuf_Room_Leave _Protobuf_Room_Leave = new Protobuf_Room_Leave();
|
||||||
|
Protobuf_Room_Player_Ready _Protobuf_Room_Player_Ready = new Protobuf_Room_Player_Ready();
|
||||||
|
Protobuf_Room_SinglePlayerInputData _Protobuf_Room_SinglePlayerInputData = new Protobuf_Room_SinglePlayerInputData();
|
||||||
|
Protobuf_Screnn_Frame _Protobuf_Screnn_Frame = new Protobuf_Screnn_Frame();
|
||||||
|
public AppRoom()
|
||||||
|
{
|
||||||
|
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomList, RecvGetRoomList);
|
||||||
|
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomListUpdate, RecvGetRoomListUpdate);
|
||||||
|
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomGetScreen, RecvRoomGetScreen);
|
||||||
|
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomCreate, RecvCreateRoom);
|
||||||
|
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomJoin, RecvJoinRoom);
|
||||||
|
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomLeave, RecvLeavnRoom);
|
||||||
|
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomMyRoomStateChanged, RecvRoomMyRoomStateChange);
|
||||||
|
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomWaitStep, RecvRoom_WaitStep);
|
||||||
|
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomHostPlayerUpdateStateRaw, RecvHostPlayer_UpdateStateRaw);
|
||||||
|
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdRoomSynPlayerInput, RecvHostSyn_RoomFrameAllInputData);
|
||||||
|
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdScreen, OnScreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region 房间列表管理
|
||||||
|
bool AddOrUpdateRoomList(Protobuf_Room_MiniInfo roomInfo)
|
||||||
|
{
|
||||||
|
bool bNew = !dictRoomListID2Info.ContainsKey(roomInfo.RoomID);
|
||||||
|
dictRoomListID2Info[roomInfo.RoomID] = roomInfo;
|
||||||
|
return bNew;
|
||||||
|
}
|
||||||
|
bool RemoveRoomList(int roomId)
|
||||||
|
{
|
||||||
|
if (dictRoomListID2Info.ContainsKey(roomId))
|
||||||
|
{
|
||||||
|
dictRoomListID2Info.Remove(roomId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 获取单个房间MiniInfo
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="roomId"></param>
|
||||||
|
/// <param name="MiniInfo"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool GetRoomListMiniInfo(int roomId, out Protobuf_Room_MiniInfo MiniInfo)
|
||||||
|
{
|
||||||
|
if (dictRoomListID2Info.ContainsKey(roomId))
|
||||||
|
{
|
||||||
|
MiniInfo = dictRoomListID2Info[roomId];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
MiniInfo = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public List<Protobuf_Room_MiniInfo> GetRoomList()
|
||||||
|
{
|
||||||
|
List<Protobuf_Room_MiniInfo> result = new List<Protobuf_Room_MiniInfo>();
|
||||||
|
foreach (var item in dictRoomListID2Info)
|
||||||
|
{
|
||||||
|
result.Add(item.Value);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Replay
|
||||||
|
public void InitRePlay()
|
||||||
|
{
|
||||||
|
netReplay = new NetReplay();
|
||||||
|
netReplay.ResetData();
|
||||||
|
}
|
||||||
|
public void ReleaseRePlay()
|
||||||
|
{
|
||||||
|
netReplay.ResetData();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 房间管理
|
||||||
|
int GetMinePlayerIndex()
|
||||||
|
{
|
||||||
|
if (mineRoomMiniInfo == null)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (mineRoomMiniInfo.Player1UID == App.user.userdata.UID)
|
||||||
|
return 0;
|
||||||
|
if (mineRoomMiniInfo.Player2UID == App.user.userdata.UID)
|
||||||
|
return 1;
|
||||||
|
if (mineRoomMiniInfo.Player3UID == App.user.userdata.UID)
|
||||||
|
return 2;
|
||||||
|
if (mineRoomMiniInfo.Player4UID == App.user.userdata.UID)
|
||||||
|
return 3;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
long[] GetRoom4PlayerUIDs()
|
||||||
|
{
|
||||||
|
if (mineRoomMiniInfo == null)
|
||||||
|
return null;
|
||||||
|
long[] result = new long[4];
|
||||||
|
if (mineRoomMiniInfo.Player1UID > 0)
|
||||||
|
result[0] = mineRoomMiniInfo.Player1UID;
|
||||||
|
if (mineRoomMiniInfo.Player2UID > 0)
|
||||||
|
result[1] = mineRoomMiniInfo.Player2UID;
|
||||||
|
if (mineRoomMiniInfo.Player3UID > 0)
|
||||||
|
result[2] = mineRoomMiniInfo.Player3UID;
|
||||||
|
if (mineRoomMiniInfo.Player4UID > 0)
|
||||||
|
result[3] = mineRoomMiniInfo.Player4UID;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
S_PlayerMiniInfo[] GetRoom4PlayerMiniInfos()
|
||||||
|
{
|
||||||
|
if (mineRoomMiniInfo == null)
|
||||||
|
return null;
|
||||||
|
S_PlayerMiniInfo[] result = new S_PlayerMiniInfo[4];
|
||||||
|
if (mineRoomMiniInfo.Player1UID > 0)
|
||||||
|
{
|
||||||
|
result[0].UID = mineRoomMiniInfo.Player1UID;
|
||||||
|
result[0].NickName = mineRoomMiniInfo.Player1NickName;
|
||||||
|
}
|
||||||
|
if (mineRoomMiniInfo.Player2UID > 0)
|
||||||
|
{
|
||||||
|
result[1].UID = mineRoomMiniInfo.Player2UID;
|
||||||
|
result[1].NickName = mineRoomMiniInfo.Player2NickName;
|
||||||
|
}
|
||||||
|
if (mineRoomMiniInfo.Player3UID > 0)
|
||||||
|
{
|
||||||
|
result[2].UID = mineRoomMiniInfo.Player3UID;
|
||||||
|
result[2].NickName = mineRoomMiniInfo.Player3NickName;
|
||||||
|
}
|
||||||
|
if (mineRoomMiniInfo.Player4UID > 0)
|
||||||
|
{
|
||||||
|
result[3].UID = mineRoomMiniInfo.Player4UID;
|
||||||
|
result[3].NickName = mineRoomMiniInfo.Player4NickName;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有房间列表
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ChatMsg"></param>
|
||||||
|
public void SendGetRoomList()
|
||||||
|
{
|
||||||
|
App.log.Info("拉取房间列表");
|
||||||
|
App.network.SendToServer((int)CommandID.CmdRoomList, ProtoBufHelper.Serizlize(_Protobuf_Room_List));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有房间列表
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reqData"></param>
|
||||||
|
void RecvGetRoomList(byte[] reqData)
|
||||||
|
{
|
||||||
|
App.log.Info("取得完整房间列表");
|
||||||
|
Protobuf_Room_List_RESP msg = ProtoBufHelper.DeSerizlize<Protobuf_Room_List_RESP>(reqData);
|
||||||
|
for (int i = 0; i < msg.RoomMiniInfoList.Count; i++)
|
||||||
|
AddOrUpdateRoomList(msg.RoomMiniInfoList[i]);
|
||||||
|
Eventer.Instance.PostEvent(EEvent.OnRoomListAllUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取单个列表更新
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reqData"></param>
|
||||||
|
void RecvGetRoomListUpdate(byte[] reqData)
|
||||||
|
{
|
||||||
|
App.log.Debug("单个房间状态更新");
|
||||||
|
Protobuf_Room_Update_RESP msg = ProtoBufHelper.DeSerizlize<Protobuf_Room_Update_RESP>(reqData);
|
||||||
|
if (msg.UpdateType == 0)
|
||||||
|
{
|
||||||
|
if (AddOrUpdateRoomList(msg.RoomMiniInfo))
|
||||||
|
{
|
||||||
|
Eventer.Instance.PostEvent(EEvent.OnRoomListSingleAdd, msg.RoomMiniInfo.RoomID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Eventer.Instance.PostEvent(EEvent.OnRoomListSingleUpdate, msg.RoomMiniInfo.RoomID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RemoveRoomList(msg.RoomMiniInfo.RoomID);
|
||||||
|
Eventer.Instance.PostEvent(EEvent.OnRoomListSingleClose, msg.RoomMiniInfo.RoomID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取房间画面快照
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="RoomID"></param>
|
||||||
|
public void SendGetRoomScreen(int RoomID)
|
||||||
|
{
|
||||||
|
_Protobuf_Room_Get_Screen.RoomID = RoomID;
|
||||||
|
App.log.Info($"获取房间画面快照");
|
||||||
|
App.network.SendToServer((int)CommandID.CmdRoomGetScreen, ProtoBufHelper.Serizlize(_Protobuf_Room_Get_Screen));
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 获取单个房间画面
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reqData"></param>
|
||||||
|
void RecvRoomGetScreen(byte[] reqData)
|
||||||
|
{
|
||||||
|
App.log.Debug("单个房间状态更新");
|
||||||
|
Protobuf_Room_Get_Screen_RESP msg = ProtoBufHelper.DeSerizlize<Protobuf_Room_Get_Screen_RESP>(reqData);
|
||||||
|
//解压
|
||||||
|
byte[] data = Helper.DecompressByteArray(msg.RawBitmap.ToArray());
|
||||||
|
Eventer.Instance.PostEvent(EEvent.OnRoomGetRoomScreen, msg.RoomID, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建房间
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="GameRomID"></param>
|
||||||
|
/// <param name="JoinPlayerIdx"></param>
|
||||||
|
/// <param name="GameRomHash"></param>
|
||||||
|
public void SendCreateRoom(int GameRomID, int JoinPlayerIdx, string GameRomHash = null)
|
||||||
|
{
|
||||||
|
_Protobuf_Room_Create.JoinPlayerIdx = JoinPlayerIdx;
|
||||||
|
_Protobuf_Room_Create.GameRomID = GameRomID;
|
||||||
|
_Protobuf_Room_Create.GameRomHash = GameRomHash;
|
||||||
|
App.log.Info($"创建房间");
|
||||||
|
App.network.SendToServer((int)CommandID.CmdRoomCreate, ProtoBufHelper.Serizlize(_Protobuf_Room_Create));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建房间成功
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reqData"></param>
|
||||||
|
void RecvCreateRoom(byte[] reqData)
|
||||||
|
{
|
||||||
|
App.log.Debug("创建房间成功");
|
||||||
|
Protobuf_Room_Create_RESP msg = ProtoBufHelper.DeSerizlize<Protobuf_Room_Create_RESP>(reqData);
|
||||||
|
mineRoomMiniInfo = msg.RoomMiniInfo;
|
||||||
|
InitRePlay();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建房间
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="GameRomID"></param>
|
||||||
|
/// <param name="JoinPlayerIdx"></param>
|
||||||
|
/// <param name="GameRomHash"></param>
|
||||||
|
public void SendJoinRoom(int RoomID, int JoinPlayerIdx)
|
||||||
|
{
|
||||||
|
_Protobuf_Room_Join.RoomID = RoomID;
|
||||||
|
_Protobuf_Room_Join.PlayerNum = JoinPlayerIdx;
|
||||||
|
App.log.Info($"创建房间");
|
||||||
|
App.network.SendToServer((int)CommandID.CmdRoomJoin, ProtoBufHelper.Serizlize(_Protobuf_Room_Join));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加入房间成功
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reqData"></param>
|
||||||
|
void RecvJoinRoom(byte[] reqData)
|
||||||
|
{
|
||||||
|
App.log.Debug("加入房间成功");
|
||||||
|
Protobuf_Room_Join_RESP msg = ProtoBufHelper.DeSerizlize<Protobuf_Room_Join_RESP>(reqData);
|
||||||
|
mineRoomMiniInfo = msg.RoomMiniInfo;
|
||||||
|
InitRePlay();
|
||||||
|
Eventer.Instance.PostEvent(EEvent.OnMineJoinRoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 离开房间
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="RoomID"></param>
|
||||||
|
public void SendLeavnRoom()
|
||||||
|
{
|
||||||
|
if (!InRoom)
|
||||||
|
return;
|
||||||
|
_Protobuf_Room_Leave.RoomID = mineRoomMiniInfo.RoomID;
|
||||||
|
App.log.Info($"LeavnRoom");
|
||||||
|
App.network.SendToServer((int)CommandID.CmdRoomLeave, ProtoBufHelper.Serizlize(_Protobuf_Room_Leave));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 离开房间成功
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reqData"></param>
|
||||||
|
void RecvLeavnRoom(byte[] reqData)
|
||||||
|
{
|
||||||
|
App.log.Debug("离开房间成功");
|
||||||
|
Protobuf_Room_Leave_RESP msg = ProtoBufHelper.DeSerizlize<Protobuf_Room_Leave_RESP>(reqData);
|
||||||
|
ReleaseRePlay();
|
||||||
|
mineRoomMiniInfo = null;
|
||||||
|
Eventer.Instance.PostEvent(EEvent.OnMineLeavnRoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RecvRoomMyRoomStateChange(byte[] reqData)
|
||||||
|
{
|
||||||
|
Protobuf_Room_MyRoom_State_Change msg = ProtoBufHelper.DeSerizlize<Protobuf_Room_MyRoom_State_Change>(reqData);
|
||||||
|
long[] oldRoomPlayer = GetRoom4PlayerUIDs();
|
||||||
|
mineRoomMiniInfo = msg.RoomMiniInfo;
|
||||||
|
long[] newRoomPlayer = GetRoom4PlayerUIDs();
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
long OldPlayer = oldRoomPlayer[i];
|
||||||
|
long NewPlayer = newRoomPlayer[i];
|
||||||
|
if (OldPlayer == NewPlayer)
|
||||||
|
continue;
|
||||||
|
//位置之前有人,但是离开了
|
||||||
|
if (OldPlayer > 0)
|
||||||
|
{
|
||||||
|
Eventer.Instance.PostEvent(EEvent.OnOtherPlayerLeavnRoom, i, OldPlayer);
|
||||||
|
if (NewPlayer > 0)//而且害换了一个玩家
|
||||||
|
Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, i, NewPlayer);
|
||||||
|
}
|
||||||
|
else //之前没人
|
||||||
|
Eventer.Instance.PostEvent(EEvent.OnOtherPlayerJoinRoom, i, NewPlayer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上报即时存档
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="RoomID"></param>
|
||||||
|
public void SendHostRaw(byte[] RawData)
|
||||||
|
{
|
||||||
|
//压缩
|
||||||
|
byte[] compressRawData = Helper.CompressByteArray(RawData);
|
||||||
|
Protobuf_Room_HostPlayer_UpdateStateRaw msg = new Protobuf_Room_HostPlayer_UpdateStateRaw()
|
||||||
|
{
|
||||||
|
LoadStateRaw = Google.Protobuf.ByteString.CopyFrom(compressRawData)
|
||||||
|
};
|
||||||
|
App.log.Info($"上报即时存档数据 原数据大小:{RawData.Length},压缩后;{compressRawData.Length}");
|
||||||
|
App.network.SendToServer((int)CommandID.CmdRoomHostPlayerUpdateStateRaw, ProtoBufHelper.Serizlize(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RecvRoom_WaitStep(byte[] reqData)
|
||||||
|
{
|
||||||
|
Protobuf_Room_WaitStep_RESP msg = ProtoBufHelper.DeSerizlize<Protobuf_Room_WaitStep_RESP>(reqData);
|
||||||
|
if (WaitStep != msg.WaitStep)
|
||||||
|
{
|
||||||
|
WaitStep = msg.WaitStep;
|
||||||
|
if (WaitStep == 1)
|
||||||
|
{
|
||||||
|
byte[] decompressRawData = Helper.DecompressByteArray(msg.LoadStateRaw.ToByteArray());
|
||||||
|
App.log.Info($"收到即时存档数据 解压后;{decompressRawData.Length}");
|
||||||
|
RawData = decompressRawData;
|
||||||
|
ReleaseRePlay();
|
||||||
|
}
|
||||||
|
Eventer.Instance.PostEvent(EEvent.OnRoomWaitStepChange, WaitStep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RecvHostPlayer_UpdateStateRaw(byte[] reqData)
|
||||||
|
{
|
||||||
|
Protobuf_Room_HostPlayer_UpdateStateRaw_RESP msg = ProtoBufHelper.DeSerizlize<Protobuf_Room_HostPlayer_UpdateStateRaw_RESP>(reqData);
|
||||||
|
App.log.Info($"鸡翅孙当上报成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 即时存档加载完毕
|
||||||
|
/// </summary>
|
||||||
|
public void SendRoomPlayerReady()
|
||||||
|
{
|
||||||
|
App.log.Debug("上报准备完毕");
|
||||||
|
App.network.SendToServer((int)CommandID.CmdRoomPlayerReady, ProtoBufHelper.Serizlize(_Protobuf_Room_Player_Ready));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 同步上行
|
||||||
|
/// </summary>
|
||||||
|
public void SendRoomSingelPlayerInput(uint FrameID, uint InputData)
|
||||||
|
{
|
||||||
|
_Protobuf_Room_SinglePlayerInputData.FrameID = FrameID;
|
||||||
|
_Protobuf_Room_SinglePlayerInputData.InputData = InputData;
|
||||||
|
App.network.SendToServer((int)CommandID.CmdRoomSingelPlayerInput, ProtoBufHelper.Serizlize(_Protobuf_Room_SinglePlayerInputData));
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong TestAllData = 0;
|
||||||
|
void RecvHostSyn_RoomFrameAllInputData(byte[] reqData)
|
||||||
|
{
|
||||||
|
Protobuf_Room_Syn_RoomFrameAllInputData msg = ProtoBufHelper.DeSerizlize<Protobuf_Room_Syn_RoomFrameAllInputData>(reqData);
|
||||||
|
if (TestAllData != msg.InputData)
|
||||||
|
{
|
||||||
|
TestAllData = msg.InputData;
|
||||||
|
App.log.Debug($"ServerFrameID->{msg.ServerFrameID} FrameID->{msg.FrameID} ClientFrame->{netReplay.mCurrClientFrameIdx} InputData->{msg.InputData}");
|
||||||
|
}
|
||||||
|
netReplay.InData(new ReplayStep() { FrameStartID = (int)msg.FrameID, InPut = msg.InputData }, (int)msg.ServerFrameID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendScreen(byte[] RenderBuffer)
|
||||||
|
{
|
||||||
|
//压缩
|
||||||
|
byte[] comData = Helper.CompressByteArray(RenderBuffer);
|
||||||
|
_Protobuf_Screnn_Frame.FrameID = 0;
|
||||||
|
_Protobuf_Screnn_Frame.RawBitmap = ByteString.CopyFrom(comData);
|
||||||
|
App.network.SendToServer((int)CommandID.CmdScreen, ProtoBufHelper.Serizlize(_Protobuf_Screnn_Frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnScreen(byte[] reqData)
|
||||||
|
{
|
||||||
|
Protobuf_Screnn_Frame msg = ProtoBufHelper.DeSerizlize<Protobuf_Screnn_Frame>(reqData);
|
||||||
|
//解压
|
||||||
|
byte[] data = Helper.DecompressByteArray(msg.RawBitmap.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class RoomEX
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获取房间空闲席位下标 (返回True表示由余位)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="roomMiniInfo"></param>
|
||||||
|
/// <param name="freeSlots"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool GetFreeSlot(this Protobuf_Room_MiniInfo roomMiniInfo, out int[] freeSlots)
|
||||||
|
{
|
||||||
|
List<int> temp = new List<int>();
|
||||||
|
if (roomMiniInfo.Player1UID <= 0) temp.Add(0);
|
||||||
|
if (roomMiniInfo.Player2UID <= 0) temp.Add(1);
|
||||||
|
if (roomMiniInfo.Player3UID <= 0) temp.Add(2);
|
||||||
|
if (roomMiniInfo.Player4UID <= 0) temp.Add(3);
|
||||||
|
freeSlots = temp.ToArray();
|
||||||
|
return freeSlots.Length > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 32566452eb52f484d92619b539b1d70f
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -1,8 +1,8 @@
|
|||||||
namespace AxibugEmuOnline.Client
|
namespace AxibugEmuOnline.Client
|
||||||
{
|
{
|
||||||
public class AppSettings
|
public class AppSettings
|
||||||
{
|
{
|
||||||
/// <summary> 背景颜色设定 </summary>
|
/// <summary> 背景颜色设定 </summary>
|
||||||
public BgColorSettings BgColor { get; set; } = new BgColorSettings();
|
public BgColorSettings BgColor { get; set; } = new BgColorSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,83 +1,83 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace AxibugEmuOnline.Client
|
namespace AxibugEmuOnline.Client
|
||||||
{
|
{
|
||||||
/// <summary> 颜色设置 </summary>
|
/// <summary> 颜色设置 </summary>
|
||||||
public class BgColorSettings
|
public class BgColorSettings
|
||||||
{
|
{
|
||||||
public delegate void OnColorChangedHandle(XMBColor color);
|
public delegate void OnColorChangedHandle(XMBColor color);
|
||||||
public event OnColorChangedHandle OnColorChanged;
|
public event OnColorChangedHandle OnColorChanged;
|
||||||
|
|
||||||
/// <summary> 当前颜色 </summary>
|
/// <summary> 当前颜色 </summary>
|
||||||
public XMBColor CurrentColor
|
public XMBColor CurrentColor
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var color1 = PlayerPrefs.GetString($"{nameof(BgColorSettings)}.{nameof(CurrentColor)}.{nameof(CurrentColor.color1)}", null);
|
var color1 = PlayerPrefs.GetString($"{nameof(BgColorSettings)}.{nameof(CurrentColor)}.{nameof(CurrentColor.color1)}", null);
|
||||||
var color2 = PlayerPrefs.GetString($"{nameof(BgColorSettings)}.{nameof(CurrentColor)}.{nameof(CurrentColor.color2)}", null);
|
var color2 = PlayerPrefs.GetString($"{nameof(BgColorSettings)}.{nameof(CurrentColor)}.{nameof(CurrentColor.color2)}", null);
|
||||||
var name = PlayerPrefs.GetString($"{nameof(BgColorSettings)}.{nameof(CurrentColor)}.{nameof(CurrentColor.Name)}", null);
|
var name = PlayerPrefs.GetString($"{nameof(BgColorSettings)}.{nameof(CurrentColor)}.{nameof(CurrentColor.Name)}", null);
|
||||||
if (string.IsNullOrWhiteSpace(color1) || string.IsNullOrWhiteSpace(color2) || string.IsNullOrWhiteSpace(name))
|
if (string.IsNullOrWhiteSpace(color1) || string.IsNullOrWhiteSpace(color2) || string.IsNullOrWhiteSpace(name))
|
||||||
return DEFAULT;
|
return DEFAULT;
|
||||||
else
|
else
|
||||||
return new XMBColor(name, color1, color2);
|
return new XMBColor(name, color1, color2);
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
PlayerPrefs.SetString($"{nameof(BgColorSettings)}.{nameof(CurrentColor)}.{nameof(CurrentColor.color1)}", $"#{ColorUtility.ToHtmlStringRGB(value.color1)}");
|
PlayerPrefs.SetString($"{nameof(BgColorSettings)}.{nameof(CurrentColor)}.{nameof(CurrentColor.color1)}", $"#{ColorUtility.ToHtmlStringRGB(value.color1)}");
|
||||||
PlayerPrefs.SetString($"{nameof(BgColorSettings)}.{nameof(CurrentColor)}.{nameof(CurrentColor.color2)}", $"#{ColorUtility.ToHtmlStringRGB(value.color2)}");
|
PlayerPrefs.SetString($"{nameof(BgColorSettings)}.{nameof(CurrentColor)}.{nameof(CurrentColor.color2)}", $"#{ColorUtility.ToHtmlStringRGB(value.color2)}");
|
||||||
PlayerPrefs.SetString($"{nameof(BgColorSettings)}.{nameof(CurrentColor)}.{nameof(CurrentColor.Name)}", value.Name);
|
PlayerPrefs.SetString($"{nameof(BgColorSettings)}.{nameof(CurrentColor)}.{nameof(CurrentColor.Name)}", value.Name);
|
||||||
|
|
||||||
OnColorChanged?.Invoke(value);
|
OnColorChanged?.Invoke(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly XMBColor DEFAULT = new XMBColor("蓝", "#020754", "#0ab1dc");
|
private static readonly XMBColor DEFAULT = new XMBColor("蓝", "#020754", "#0ab1dc");
|
||||||
public List<XMBColor> Presets { get; private set; } = new List<XMBColor>()
|
public List<XMBColor> Presets { get; private set; } = new List<XMBColor>()
|
||||||
{
|
{
|
||||||
DEFAULT,
|
DEFAULT,
|
||||||
new XMBColor("白","#8a9fb2","#4e9eb6"),
|
new XMBColor("白","#8a9fb2","#4e9eb6"),
|
||||||
new XMBColor("黄","#987500","#d1a813"),
|
new XMBColor("黄","#987500","#d1a813"),
|
||||||
new XMBColor("绿","#3e962b","#7ac25e"),
|
new XMBColor("绿","#3e962b","#7ac25e"),
|
||||||
new XMBColor("粉","#e65a8b","#c7acc6"),
|
new XMBColor("粉","#e65a8b","#c7acc6"),
|
||||||
new XMBColor("墨绿","#00421a","#1c951f"),
|
new XMBColor("墨绿","#00421a","#1c951f"),
|
||||||
new XMBColor("紫","#633f93","#8763cc"),
|
new XMBColor("紫","#633f93","#8763cc"),
|
||||||
new XMBColor("天蓝","#038baa","#0ca2c2"),
|
new XMBColor("天蓝","#038baa","#0ca2c2"),
|
||||||
new XMBColor("红","#9c120e","#d73611"),
|
new XMBColor("红","#9c120e","#d73611"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public struct XMBColor
|
public struct XMBColor
|
||||||
{
|
{
|
||||||
public string Name;
|
public string Name;
|
||||||
public Color color1;
|
public Color color1;
|
||||||
public Color color2;
|
public Color color2;
|
||||||
|
|
||||||
public XMBColor(string name, string colorCodeStr1, string colorCodeStr2)
|
public XMBColor(string name, string colorCodeStr1, string colorCodeStr2)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
ColorUtility.TryParseHtmlString(colorCodeStr1, out color1);
|
ColorUtility.TryParseHtmlString(colorCodeStr1, out color1);
|
||||||
ColorUtility.TryParseHtmlString(colorCodeStr2, out color2);
|
ColorUtility.TryParseHtmlString(colorCodeStr2, out color2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static XMBColor Lerp(XMBColor start, XMBColor endColor, float t)
|
public static XMBColor Lerp(XMBColor start, XMBColor endColor, float t)
|
||||||
{
|
{
|
||||||
var result = new XMBColor();
|
var result = new XMBColor();
|
||||||
result.Name = endColor.Name;
|
result.Name = endColor.Name;
|
||||||
result.color1 = Color.Lerp(start.color1, endColor.color1, t);
|
result.color1 = Color.Lerp(start.color1, endColor.color1, t);
|
||||||
result.color2 = Color.Lerp(start.color2, endColor.color2, t);
|
result.color2 = Color.Lerp(start.color2, endColor.color2, t);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
int hash = 17;
|
int hash = 17;
|
||||||
hash = hash * 23 + (Name != null ? Name.GetHashCode() : 0);
|
hash = hash * 23 + (Name != null ? Name.GetHashCode() : 0);
|
||||||
hash = hash * 23 + color1.GetHashCode();
|
hash = hash * 23 + color1.GetHashCode();
|
||||||
hash = hash * 23 + color2.GetHashCode();
|
hash = hash * 23 + color2.GetHashCode();
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,103 +1,103 @@
|
|||||||
using AxibugEmuOnline.Client.ClientCore;
|
using AxibugEmuOnline.Client.ClientCore;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Networking;
|
using UnityEngine.Networking;
|
||||||
|
|
||||||
namespace AxibugEmuOnline.Client
|
namespace AxibugEmuOnline.Client
|
||||||
{
|
{
|
||||||
public class CacheManager
|
public class CacheManager
|
||||||
{
|
{
|
||||||
static readonly string CacheDirPath = $"{App.PersistentDataPath}/Caches";
|
static readonly string CacheDirPath = $"{App.PersistentDataPath}/Caches";
|
||||||
static readonly string TextureCacheDirPath = $"{CacheDirPath}/Texture";
|
static readonly string TextureCacheDirPath = $"{CacheDirPath}/Texture";
|
||||||
|
|
||||||
public void GetSpriteCache(string url, Action<Sprite, string> callback)
|
public void GetSpriteCache(string url, Action<Sprite, string> callback)
|
||||||
{
|
{
|
||||||
GetCacheData(url, TextureCacheDirPath, callback);
|
GetCacheData(url, TextureCacheDirPath, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> ÒƳýÎļþ»º´æ </summary>
|
/// <summary> ÒƳýÎļþ»º´æ </summary>
|
||||||
public void ClearCaches()
|
public void ClearCaches()
|
||||||
{
|
{
|
||||||
if (Directory.Exists(CacheDirPath))
|
if (Directory.Exists(CacheDirPath))
|
||||||
Directory.Delete(CacheDirPath, true);
|
Directory.Delete(CacheDirPath, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator DownloadFromURL(string url, string path, Action<byte[]> callback)
|
IEnumerator DownloadFromURL(string url, string path, Action<byte[]> callback)
|
||||||
{
|
{
|
||||||
var request = UnityWebRequest.Get($"{App.httpAPI.WebHost}/{url}");
|
var request = UnityWebRequest.Get($"{App.httpAPI.WebHost}/{url}");
|
||||||
yield return request.SendWebRequest();
|
yield return request.SendWebRequest();
|
||||||
|
|
||||||
if (request.result == UnityWebRequest.Result.Success)
|
if (request.result == UnityWebRequest.Result.Success)
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(path);
|
Directory.CreateDirectory(path);
|
||||||
File.WriteAllBytes($"{path}/{url.GetHashCode()}", request.downloadHandler.data);
|
File.WriteAllBytes($"{path}/{url.GetHashCode()}", request.downloadHandler.data);
|
||||||
callback.Invoke(request.downloadHandler.data);
|
callback.Invoke(request.downloadHandler.data);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
callback.Invoke(null);
|
callback.Invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dictionary<string, object> cachesInMemory = new Dictionary<string, object>();
|
private Dictionary<string, object> cachesInMemory = new Dictionary<string, object>();
|
||||||
void GetCacheData<T>(string url, string path, Action<T, string> callback) where T : class
|
void GetCacheData<T>(string url, string path, Action<T, string> callback) where T : class
|
||||||
{
|
{
|
||||||
if (cachesInMemory.TryGetValue(url, out var cacheObj) && cacheObj is T obj)
|
if (cachesInMemory.TryGetValue(url, out var cacheObj) && cacheObj is T obj)
|
||||||
{
|
{
|
||||||
callback.Invoke(obj, url);
|
callback.Invoke(obj, url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileName = $"{url.GetHashCode()}";
|
var fileName = $"{url.GetHashCode()}";
|
||||||
byte[] rawData = null;
|
byte[] rawData = null;
|
||||||
|
|
||||||
var filePath = $"{path}/{fileName}";
|
var filePath = $"{path}/{fileName}";
|
||||||
if (File.Exists(filePath))
|
if (File.Exists(filePath))
|
||||||
{
|
{
|
||||||
rawData = File.ReadAllBytes(filePath);
|
rawData = File.ReadAllBytes(filePath);
|
||||||
var @out = RawDataConvert<T>(rawData);
|
var @out = RawDataConvert<T>(rawData);
|
||||||
cachesInMemory[url] = @out;
|
cachesInMemory[url] = @out;
|
||||||
callback.Invoke(@out, url);
|
callback.Invoke(@out, url);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
App.StartCoroutine(DownloadFromURL(url, path, (data) =>
|
App.StartCoroutine(DownloadFromURL(url, path, (data) =>
|
||||||
{
|
{
|
||||||
var @out = RawDataConvert<T>(data);
|
var @out = RawDataConvert<T>(data);
|
||||||
cachesInMemory[url] = @out;
|
cachesInMemory[url] = @out;
|
||||||
callback.Invoke(@out, url);
|
callback.Invoke(@out, url);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Type t_texture2d = typeof(Texture2D);
|
Type t_texture2d = typeof(Texture2D);
|
||||||
Type t_sprite = typeof(Sprite);
|
Type t_sprite = typeof(Sprite);
|
||||||
Type t_byteArray = typeof(byte[]);
|
Type t_byteArray = typeof(byte[]);
|
||||||
Type t_object = typeof(object);
|
Type t_object = typeof(object);
|
||||||
|
|
||||||
T RawDataConvert<T>(byte[] data) where T : class
|
T RawDataConvert<T>(byte[] data) where T : class
|
||||||
{
|
{
|
||||||
var vt = typeof(T);
|
var vt = typeof(T);
|
||||||
|
|
||||||
if (vt == t_texture2d || vt == t_sprite)
|
if (vt == t_texture2d || vt == t_sprite)
|
||||||
{
|
{
|
||||||
Texture2D texture = new Texture2D(2, 2);
|
Texture2D texture = new Texture2D(2, 2);
|
||||||
texture.LoadImage(data);
|
texture.LoadImage(data);
|
||||||
|
|
||||||
if (vt == t_texture2d) return texture as T;
|
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 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)
|
else if (vt == t_byteArray)
|
||||||
{
|
{
|
||||||
return data as T;
|
return data as T;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return data as T;
|
return data as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NotImplementedException($"{vt.Name}");
|
throw new NotImplementedException($"{vt.Name}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,8 +1,8 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace AxibugEmuOnline.Client
|
namespace AxibugEmuOnline.Client
|
||||||
{
|
{
|
||||||
public class CoroutineRunner : MonoBehaviour
|
public class CoroutineRunner : MonoBehaviour
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,343 +1,343 @@
|
|||||||
using AxibugEmuOnline.Client.ClientCore;
|
using AxibugEmuOnline.Client.ClientCore;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Rendering.PostProcessing;
|
using UnityEngine.Rendering.PostProcessing;
|
||||||
using static AxibugEmuOnline.Client.FilterEffect;
|
using static AxibugEmuOnline.Client.FilterEffect;
|
||||||
|
|
||||||
namespace AxibugEmuOnline.Client
|
namespace AxibugEmuOnline.Client
|
||||||
{
|
{
|
||||||
public class FilterManager
|
public class FilterManager
|
||||||
{
|
{
|
||||||
private PostProcessProfile m_filterPorfile;
|
private PostProcessProfile m_filterPorfile;
|
||||||
private List<Filter> m_filters;
|
private List<Filter> m_filters;
|
||||||
private Dictionary<EnumPlatform, Filter> m_filterPlatforms = new Dictionary<EnumPlatform, Filter>();
|
private Dictionary<EnumPlatform, Filter> m_filterPlatforms = new Dictionary<EnumPlatform, Filter>();
|
||||||
private AlphaWraper m_previewFilterWraper;
|
private AlphaWraper m_previewFilterWraper;
|
||||||
FilterRomSetting m_filterRomSetting;
|
FilterRomSetting m_filterRomSetting;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 滤镜列表
|
/// 滤镜列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IReadOnlyList<Filter> Filters => m_filters;
|
public IReadOnlyList<Filter> Filters => m_filters;
|
||||||
|
|
||||||
public FilterManager(PostProcessVolume filterVolume, CanvasGroup filterPreview, CanvasGroup mainBg)
|
public FilterManager(PostProcessVolume filterVolume, CanvasGroup filterPreview, CanvasGroup mainBg)
|
||||||
{
|
{
|
||||||
m_filterPorfile = filterVolume.profile;
|
m_filterPorfile = filterVolume.profile;
|
||||||
m_filters = m_filterPorfile.settings.Where(setting => setting is FilterEffect).Select(setting => new Filter(setting as FilterEffect)).ToList();
|
m_filters = m_filterPorfile.settings.Where(setting => setting is FilterEffect).Select(setting => new Filter(setting as FilterEffect)).ToList();
|
||||||
var json = PlayerPrefs.GetString(nameof(FilterRomSetting));
|
var json = PlayerPrefs.GetString(nameof(FilterRomSetting));
|
||||||
m_filterRomSetting = JsonUtility.FromJson<FilterRomSetting>(json) ?? new FilterRomSetting();
|
m_filterRomSetting = JsonUtility.FromJson<FilterRomSetting>(json) ?? new FilterRomSetting();
|
||||||
|
|
||||||
m_previewFilterWraper = new AlphaWraper(mainBg, filterPreview, false);
|
m_previewFilterWraper = new AlphaWraper(mainBg, filterPreview, false);
|
||||||
ShutDownFilterPreview();
|
ShutDownFilterPreview();
|
||||||
ShutDownFilter();
|
ShutDownFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> 关闭滤镜预览 </summary>
|
/// <summary> 关闭滤镜预览 </summary>
|
||||||
public void ShutDownFilterPreview()
|
public void ShutDownFilterPreview()
|
||||||
{
|
{
|
||||||
m_previewFilterWraper.On = false;
|
m_previewFilterWraper.On = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> 开启滤镜预览 </summary>
|
/// <summary> 开启滤镜预览 </summary>
|
||||||
public void EnableFilterPreview()
|
public void EnableFilterPreview()
|
||||||
{
|
{
|
||||||
m_previewFilterWraper.On = true;
|
m_previewFilterWraper.On = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 打开滤镜
|
/// 打开滤镜
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="filter"></param>
|
/// <param name="filter"></param>
|
||||||
public void EnableFilter(Filter filter)
|
public void EnableFilter(Filter filter)
|
||||||
{
|
{
|
||||||
foreach (var selfFiler in Filters)
|
foreach (var selfFiler in Filters)
|
||||||
{
|
{
|
||||||
if (selfFiler != filter) selfFiler.m_setting.enabled.Override(false);
|
if (selfFiler != filter) selfFiler.m_setting.enabled.Override(false);
|
||||||
else selfFiler.m_setting.enabled.Override(true);
|
else selfFiler.m_setting.enabled.Override(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 关闭滤镜效果
|
/// 关闭滤镜效果
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void ShutDownFilter()
|
public void ShutDownFilter()
|
||||||
{
|
{
|
||||||
//关闭所有后处理效果
|
//关闭所有后处理效果
|
||||||
foreach (var setting in m_filterPorfile.settings)
|
foreach (var setting in m_filterPorfile.settings)
|
||||||
setting.enabled.Override(false);
|
setting.enabled.Override(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 为指定rom设置滤镜以及滤镜的预设
|
/// 为指定rom设置滤镜以及滤镜的预设
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="rom">rom对象</param>
|
/// <param name="rom">rom对象</param>
|
||||||
/// <param name="filter">滤镜</param>
|
/// <param name="filter">滤镜</param>
|
||||||
/// <param name="preset">滤镜预设</param>
|
/// <param name="preset">滤镜预设</param>
|
||||||
public void SetupFilter(RomFile rom, Filter filter, FilterPreset preset)
|
public void SetupFilter(RomFile rom, Filter filter, FilterPreset preset)
|
||||||
{
|
{
|
||||||
m_filterRomSetting.Setup(rom, filter, preset);
|
m_filterRomSetting.Setup(rom, filter, preset);
|
||||||
|
|
||||||
string json = m_filterRomSetting.ToJson();
|
string json = m_filterRomSetting.ToJson();
|
||||||
PlayerPrefs.SetString(nameof(FilterRomSetting), json);
|
PlayerPrefs.SetString(nameof(FilterRomSetting), json);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获得指定rom配置的滤镜设置
|
/// 获得指定rom配置的滤镜设置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="rom">rom对象</param>
|
/// <param name="rom">rom对象</param>
|
||||||
/// <returns>此元组任意内任意成员都有可能为空</returns>
|
/// <returns>此元组任意内任意成员都有可能为空</returns>
|
||||||
public (Filter filter, FilterPreset preset) GetFilterSetting(RomFile rom)
|
public (Filter filter, FilterPreset preset) GetFilterSetting(RomFile rom)
|
||||||
{
|
{
|
||||||
var value = m_filterRomSetting.Get(rom);
|
var value = m_filterRomSetting.Get(rom);
|
||||||
Filter filter = null;
|
Filter filter = null;
|
||||||
FilterPreset preset = null;
|
FilterPreset preset = null;
|
||||||
|
|
||||||
filter = Filters.FirstOrDefault(f => f.Name == value.filterName);
|
filter = Filters.FirstOrDefault(f => f.Name == value.filterName);
|
||||||
if (filter != null)
|
if (filter != null)
|
||||||
{
|
{
|
||||||
string presetName = value.presetName;
|
string presetName = value.presetName;
|
||||||
preset = filter.Presets.FirstOrDefault(p => p.Name == presetName);
|
preset = filter.Presets.FirstOrDefault(p => p.Name == presetName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (filter, preset);
|
return (filter, preset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Filter
|
public class Filter
|
||||||
{
|
{
|
||||||
public string Name => m_setting.Name;
|
public string Name => m_setting.Name;
|
||||||
public IReadOnlyCollection<EditableParamerter> Paramerters => m_setting.EditableParam;
|
public IReadOnlyCollection<EditableParamerter> Paramerters => m_setting.EditableParam;
|
||||||
/// <summary> 滤镜预设 </summary>
|
/// <summary> 滤镜预设 </summary>
|
||||||
public List<FilterPreset> Presets = new List<FilterPreset>();
|
public List<FilterPreset> Presets = new List<FilterPreset>();
|
||||||
/// <summary> 滤镜默认预设 </summary>
|
/// <summary> 滤镜默认预设 </summary>
|
||||||
public FilterPreset DefaultPreset = new FilterPreset("DEFAULT");
|
public FilterPreset DefaultPreset = new FilterPreset("DEFAULT");
|
||||||
|
|
||||||
internal FilterEffect m_setting;
|
internal FilterEffect m_setting;
|
||||||
|
|
||||||
public Filter(FilterEffect setting)
|
public Filter(FilterEffect setting)
|
||||||
{
|
{
|
||||||
m_setting = setting;
|
m_setting = setting;
|
||||||
|
|
||||||
loadPresets();
|
loadPresets();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadPresets()
|
private void loadPresets()
|
||||||
{
|
{
|
||||||
var json = PlayerPrefs.GetString($"Filter_{Name}_PresetList", string.Empty);
|
var json = PlayerPrefs.GetString($"Filter_{Name}_PresetList", string.Empty);
|
||||||
var loadedPresets = JsonUtility.FromJson<FilterPresetList>(json);
|
var loadedPresets = JsonUtility.FromJson<FilterPresetList>(json);
|
||||||
if (loadedPresets == null) return;
|
if (loadedPresets == null) return;
|
||||||
else Presets = loadedPresets.presets;
|
else Presets = loadedPresets.presets;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SavePresets()
|
public void SavePresets()
|
||||||
{
|
{
|
||||||
var json = JsonUtility.ToJson(new FilterPresetList(Presets));
|
var json = JsonUtility.ToJson(new FilterPresetList(Presets));
|
||||||
PlayerPrefs.SetString($"Filter_{Name}_PresetList", json);
|
PlayerPrefs.SetString($"Filter_{Name}_PresetList", json);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MsgBool CreatePreset(string presetName, out FilterPreset newPreset)
|
public MsgBool CreatePreset(string presetName, out FilterPreset newPreset)
|
||||||
{
|
{
|
||||||
newPreset = null;
|
newPreset = null;
|
||||||
if (string.IsNullOrWhiteSpace(presetName)) return "名称不能为空";
|
if (string.IsNullOrWhiteSpace(presetName)) return "名称不能为空";
|
||||||
if (Presets.Count(p => p.Name == presetName) != 0) return "名称重复";
|
if (Presets.Count(p => p.Name == presetName) != 0) return "名称重复";
|
||||||
|
|
||||||
newPreset = new FilterPreset(presetName);
|
newPreset = new FilterPreset(presetName);
|
||||||
Presets.Add(newPreset);
|
Presets.Add(newPreset);
|
||||||
|
|
||||||
SavePresets();
|
SavePresets();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemovePreset(FilterPreset preset)
|
public void RemovePreset(FilterPreset preset)
|
||||||
{
|
{
|
||||||
if (!Presets.Remove(preset)) return;
|
if (!Presets.Remove(preset)) return;
|
||||||
SavePresets();
|
SavePresets();
|
||||||
|
|
||||||
EventInvoker.RaiseFilterPresetRemoved(this, preset);
|
EventInvoker.RaiseFilterPresetRemoved(this, preset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResetPreset()
|
public void ResetPreset()
|
||||||
{
|
{
|
||||||
foreach (var param in Paramerters)
|
foreach (var param in Paramerters)
|
||||||
{
|
{
|
||||||
param.ResetToDefault();
|
param.ResetToDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ApplyPreset(FilterPreset preset)
|
public void ApplyPreset(FilterPreset preset)
|
||||||
{
|
{
|
||||||
foreach (var param in Paramerters)
|
foreach (var param in Paramerters)
|
||||||
{
|
{
|
||||||
var value = preset.GetParamValue(param.Name, param.ValueType);
|
var value = preset.GetParamValue(param.Name, param.ValueType);
|
||||||
if (value == null)
|
if (value == null)
|
||||||
param.ResetToDefault();
|
param.ResetToDefault();
|
||||||
else
|
else
|
||||||
param.Apply(value);
|
param.Apply(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
private class FilterPresetList
|
private class FilterPresetList
|
||||||
{
|
{
|
||||||
public List<FilterPreset> presets;
|
public List<FilterPreset> presets;
|
||||||
|
|
||||||
public FilterPresetList(List<FilterPreset> presets)
|
public FilterPresetList(List<FilterPreset> presets)
|
||||||
{
|
{
|
||||||
this.presets = presets;
|
this.presets = presets;
|
||||||
foreach (var preset in presets)
|
foreach (var preset in presets)
|
||||||
{
|
{
|
||||||
preset.ReadyForJson();
|
preset.ReadyForJson();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class FilterPreset
|
public class FilterPreset
|
||||||
{
|
{
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
public string Name;
|
public string Name;
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private List<string> m_paramName = new List<string>();
|
private List<string> m_paramName = new List<string>();
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private List<string> m_valueJson = new List<string>();
|
private List<string> m_valueJson = new List<string>();
|
||||||
|
|
||||||
private bool m_cacheReady = false;
|
private bool m_cacheReady = false;
|
||||||
private Dictionary<string, string> m_paramName2ValueJson;
|
private Dictionary<string, string> m_paramName2ValueJson;
|
||||||
public FilterPreset(string presetName)
|
public FilterPreset(string presetName)
|
||||||
{
|
{
|
||||||
Name = presetName;
|
Name = presetName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReadyForJson()
|
public void ReadyForJson()
|
||||||
{
|
{
|
||||||
prepareCache();
|
prepareCache();
|
||||||
|
|
||||||
m_paramName = m_paramName2ValueJson.Keys.ToList();
|
m_paramName = m_paramName2ValueJson.Keys.ToList();
|
||||||
m_valueJson = m_paramName2ValueJson.Values.ToList();
|
m_valueJson = m_paramName2ValueJson.Values.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetParamValueJson(string paramName)
|
public string GetParamValueJson(string paramName)
|
||||||
{
|
{
|
||||||
prepareCache();
|
prepareCache();
|
||||||
|
|
||||||
m_paramName2ValueJson.TryGetValue(paramName, out var value);
|
m_paramName2ValueJson.TryGetValue(paramName, out var value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object GetParamValue(string paramName, Type valueType)
|
public object GetParamValue(string paramName, Type valueType)
|
||||||
{
|
{
|
||||||
var rawStr = GetParamValueJson(paramName);
|
var rawStr = GetParamValueJson(paramName);
|
||||||
if (rawStr == null) return null;
|
if (rawStr == null) return null;
|
||||||
|
|
||||||
if (valueType == typeof(float))
|
if (valueType == typeof(float))
|
||||||
{
|
{
|
||||||
float.TryParse(rawStr, out var floatVal);
|
float.TryParse(rawStr, out var floatVal);
|
||||||
return floatVal;
|
return floatVal;
|
||||||
}
|
}
|
||||||
else if (valueType.IsEnum)
|
else if (valueType.IsEnum)
|
||||||
{
|
{
|
||||||
var names = Enum.GetNames(valueType);
|
var names = Enum.GetNames(valueType);
|
||||||
var values = Enum.GetValues(valueType);
|
var values = Enum.GetValues(valueType);
|
||||||
|
|
||||||
for (int i = 0; i < names.Length; i++)
|
for (int i = 0; i < names.Length; i++)
|
||||||
{
|
{
|
||||||
if (names[i].Equals(rawStr))
|
if (names[i].Equals(rawStr))
|
||||||
{
|
{
|
||||||
return values.GetValue(i);
|
return values.GetValue(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
App.log.Error($"尚未支持的滤镜参数类型{valueType}");
|
App.log.Error($"尚未支持的滤镜参数类型{valueType}");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetParamValue(string paramName, Type valueType, object value)
|
public void SetParamValue(string paramName, Type valueType, object value)
|
||||||
{
|
{
|
||||||
prepareCache();
|
prepareCache();
|
||||||
m_paramName2ValueJson[paramName] = value.ToString();
|
m_paramName2ValueJson[paramName] = value.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepareCache()
|
private void prepareCache()
|
||||||
{
|
{
|
||||||
if (m_cacheReady) return;
|
if (m_cacheReady) return;
|
||||||
|
|
||||||
m_paramName2ValueJson = new Dictionary<string, string>();
|
m_paramName2ValueJson = new Dictionary<string, string>();
|
||||||
for (int i = 0; i < m_paramName.Count; i++)
|
for (int i = 0; i < m_paramName.Count; i++)
|
||||||
{
|
{
|
||||||
m_paramName2ValueJson[m_paramName[i]] = m_valueJson[i];
|
m_paramName2ValueJson[m_paramName[i]] = m_valueJson[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cacheReady = true;
|
m_cacheReady = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class FilterRomSetting
|
public class FilterRomSetting
|
||||||
{
|
{
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private List<int> m_romID;
|
private List<int> m_romID;
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private List<Item> m_items;
|
private List<Item> m_items;
|
||||||
|
|
||||||
bool m_cacheReady = false;
|
bool m_cacheReady = false;
|
||||||
Dictionary<int, Item> m_cache;
|
Dictionary<int, Item> m_cache;
|
||||||
|
|
||||||
public void Setup(RomFile rom, Filter filter, FilterPreset preset)
|
public void Setup(RomFile rom, Filter filter, FilterPreset preset)
|
||||||
{
|
{
|
||||||
prepareCache();
|
prepareCache();
|
||||||
|
|
||||||
if (filter == null)
|
if (filter == null)
|
||||||
m_cache.Remove(rom.ID);
|
m_cache.Remove(rom.ID);
|
||||||
else
|
else
|
||||||
m_cache[rom.ID] = new Item { FilterName = filter.Name, PresetName = preset != null ? preset.Name : null };
|
m_cache[rom.ID] = new Item { FilterName = filter.Name, PresetName = preset != null ? preset.Name : null };
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ToJson()
|
public string ToJson()
|
||||||
{
|
{
|
||||||
prepareCache();
|
prepareCache();
|
||||||
m_romID = m_cache.Keys.ToList();
|
m_romID = m_cache.Keys.ToList();
|
||||||
m_items = m_cache.Values.ToList();
|
m_items = m_cache.Values.ToList();
|
||||||
|
|
||||||
return JsonUtility.ToJson(this);
|
return JsonUtility.ToJson(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public (string filterName, string presetName) Get(RomFile rom)
|
public (string filterName, string presetName) Get(RomFile rom)
|
||||||
{
|
{
|
||||||
prepareCache();
|
prepareCache();
|
||||||
|
|
||||||
m_cache.TryGetValue(rom.ID, out var item);
|
m_cache.TryGetValue(rom.ID, out var item);
|
||||||
return (item.FilterName, item.PresetName);
|
return (item.FilterName, item.PresetName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepareCache()
|
private void prepareCache()
|
||||||
{
|
{
|
||||||
if (m_cacheReady) return;
|
if (m_cacheReady) return;
|
||||||
|
|
||||||
if (m_items == null) m_items = new List<Item>();
|
if (m_items == null) m_items = new List<Item>();
|
||||||
if (m_romID == null) m_romID = new List<int>();
|
if (m_romID == null) m_romID = new List<int>();
|
||||||
m_cache = new Dictionary<int, Item>();
|
m_cache = new Dictionary<int, Item>();
|
||||||
for (int i = 0; i < m_romID.Count && i < m_items.Count; i++)
|
for (int i = 0; i < m_romID.Count && i < m_items.Count; i++)
|
||||||
{
|
{
|
||||||
m_cache[m_romID[i]] = m_items[i];
|
m_cache[m_romID[i]] = m_items[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cacheReady = true;
|
m_cacheReady = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
struct Item
|
struct Item
|
||||||
{
|
{
|
||||||
public string FilterName;
|
public string FilterName;
|
||||||
public string PresetName;
|
public string PresetName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,131 +1,131 @@
|
|||||||
using AxibugEmuOnline.Client.ClientCore;
|
using AxibugEmuOnline.Client.ClientCore;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Networking;
|
using UnityEngine.Networking;
|
||||||
|
|
||||||
namespace AxibugEmuOnline.Client
|
namespace AxibugEmuOnline.Client
|
||||||
{
|
{
|
||||||
public class HttpAPI
|
public class HttpAPI
|
||||||
{
|
{
|
||||||
public string WebHost = "http://emu.axibug.com";
|
public string WebHost = "http://emu.axibug.com";
|
||||||
public string WebSiteApi => WebHost + "/api";
|
public string WebSiteApi => WebHost + "/api";
|
||||||
|
|
||||||
public delegate void GetRomListAPI(Action<Resp_GameList> callback, int page, int pageSize = 10);
|
public delegate void GetRomListAPI(Action<Resp_GameList> callback, int page, int pageSize = 10);
|
||||||
public delegate void SearchRomListAPI(Action<Resp_GameList> callback, string searchKey, int page, int pageSize = 10);
|
public delegate void SearchRomListAPI(Action<Resp_GameList> callback, string searchKey, int page, int pageSize = 10);
|
||||||
|
|
||||||
public void GetNesRomList(Action<Resp_GameList> callback, int page, int pageSize = 10)
|
public void GetNesRomList(Action<Resp_GameList> callback, int page, int pageSize = 10)
|
||||||
{
|
{
|
||||||
App.StartCoroutine(GetNesRomListFlow(page, pageSize, callback));
|
App.StartCoroutine(GetNesRomListFlow(page, pageSize, callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SearchNesRomList(Action<Resp_GameList> callback, string searchKey, int page, int pageSize = 10)
|
public void SearchNesRomList(Action<Resp_GameList> callback, string searchKey, int page, int pageSize = 10)
|
||||||
{
|
{
|
||||||
App.StartCoroutine(SearchNesRomListFlow(searchKey, page, pageSize, callback));
|
App.StartCoroutine(SearchNesRomListFlow(searchKey, page, pageSize, callback));
|
||||||
}
|
}
|
||||||
private IEnumerator SearchNesRomListFlow(string searchKey, int page, int pageSize, Action<Resp_GameList> callback)
|
private IEnumerator SearchNesRomListFlow(string searchKey, int page, int pageSize, Action<Resp_GameList> callback)
|
||||||
{
|
{
|
||||||
UnityWebRequest request = UnityWebRequest.Get($"{WebSiteApi}/NesRomList?Page={page}&PageSize={pageSize}&SearchKey={searchKey}");
|
UnityWebRequest request = UnityWebRequest.Get($"{WebSiteApi}/NesRomList?Page={page}&PageSize={pageSize}&SearchKey={searchKey}");
|
||||||
yield return request.SendWebRequest();
|
yield return request.SendWebRequest();
|
||||||
|
|
||||||
if (request.result != UnityWebRequest.Result.Success)
|
if (request.result != UnityWebRequest.Result.Success)
|
||||||
{
|
{
|
||||||
callback.Invoke(null);
|
callback.Invoke(null);
|
||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp = JsonUtility.FromJson<Resp_GameList>(request.downloadHandler.text);
|
var resp = JsonUtility.FromJson<Resp_GameList>(request.downloadHandler.text);
|
||||||
callback.Invoke(resp);
|
callback.Invoke(resp);
|
||||||
}
|
}
|
||||||
private IEnumerator GetNesRomListFlow(int page, int pageSize, Action<Resp_GameList> callback)
|
private IEnumerator GetNesRomListFlow(int page, int pageSize, Action<Resp_GameList> callback)
|
||||||
{
|
{
|
||||||
UnityWebRequest request = UnityWebRequest.Get($"{WebSiteApi}/NesRomList?Page={page}&PageSize={pageSize}");
|
UnityWebRequest request = UnityWebRequest.Get($"{WebSiteApi}/NesRomList?Page={page}&PageSize={pageSize}");
|
||||||
yield return request.SendWebRequest();
|
yield return request.SendWebRequest();
|
||||||
|
|
||||||
if (request.result != UnityWebRequest.Result.Success)
|
if (request.result != UnityWebRequest.Result.Success)
|
||||||
{
|
{
|
||||||
callback.Invoke(null);
|
callback.Invoke(null);
|
||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp = JsonUtility.FromJson<Resp_GameList>(request.downloadHandler.text);
|
var resp = JsonUtility.FromJson<Resp_GameList>(request.downloadHandler.text);
|
||||||
callback.Invoke(resp);
|
callback.Invoke(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerator GetNesRomInfo(int RomID, Action<Resp_RomInfo> callback)
|
public IEnumerator GetNesRomInfo(int RomID, Action<Resp_RomInfo> callback)
|
||||||
{
|
{
|
||||||
UnityWebRequest request = UnityWebRequest.Get($"{WebSiteApi}/RomInfo?PType={PlatformType.Nes}&RomID={RomID}");
|
UnityWebRequest request = UnityWebRequest.Get($"{WebSiteApi}/RomInfo?PType={PlatformType.Nes}&RomID={RomID}");
|
||||||
yield return request.SendWebRequest();
|
yield return request.SendWebRequest();
|
||||||
|
|
||||||
if (request.result != UnityWebRequest.Result.Success)
|
if (request.result != UnityWebRequest.Result.Success)
|
||||||
{
|
{
|
||||||
callback.Invoke(null);
|
callback.Invoke(null);
|
||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp = JsonUtility.FromJson<Resp_RomInfo>(request.downloadHandler.text);
|
var resp = JsonUtility.FromJson<Resp_RomInfo>(request.downloadHandler.text);
|
||||||
callback.Invoke(resp);
|
callback.Invoke(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum PlatformType : byte
|
enum PlatformType : byte
|
||||||
{
|
{
|
||||||
All = 0,
|
All = 0,
|
||||||
Nes = 1,
|
Nes = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum GameType : byte
|
enum GameType : byte
|
||||||
{
|
{
|
||||||
NONE = 0,
|
NONE = 0,
|
||||||
ACT,
|
ACT,
|
||||||
ARPG,
|
ARPG,
|
||||||
AVG,
|
AVG,
|
||||||
ETC,
|
ETC,
|
||||||
FTG,
|
FTG,
|
||||||
PUZ,
|
PUZ,
|
||||||
RAC,
|
RAC,
|
||||||
RPG,
|
RPG,
|
||||||
SLG,
|
SLG,
|
||||||
SPG,
|
SPG,
|
||||||
SRPG,
|
SRPG,
|
||||||
STG,
|
STG,
|
||||||
TAB,
|
TAB,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 合卡
|
/// 合卡
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ALLINONE,
|
ALLINONE,
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class Resp_GameList
|
public class Resp_GameList
|
||||||
{
|
{
|
||||||
public int page;
|
public int page;
|
||||||
public int maxPage;
|
public int maxPage;
|
||||||
public int resultAllCount;
|
public int resultAllCount;
|
||||||
public List<Resp_RomInfo> gameList;
|
public List<Resp_RomInfo> gameList;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class Resp_RomInfo
|
public class Resp_RomInfo
|
||||||
{
|
{
|
||||||
public int orderid;
|
public int orderid;
|
||||||
public int id;
|
public int id;
|
||||||
public string romName;
|
public string romName;
|
||||||
public string gType;
|
public string gType;
|
||||||
public string desc;
|
public string desc;
|
||||||
public string url;
|
public string url;
|
||||||
public string imgUrl;
|
public string imgUrl;
|
||||||
public string hash;
|
public string hash;
|
||||||
public int stars;
|
public int stars;
|
||||||
}
|
}
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class Resp_CheckStandInfo
|
public class Resp_CheckStandInfo
|
||||||
{
|
{
|
||||||
public int needUpdateClient;
|
public int needUpdateClient;
|
||||||
public string serverIp;
|
public string serverIp;
|
||||||
public ushort serverPort;
|
public ushort serverPort;
|
||||||
public string clientVersion;
|
public string clientVersion;
|
||||||
public string downLoadUrl;
|
public string downLoadUrl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
namespace AxibugEmuOnline.Client
|
namespace AxibugEmuOnline.Client
|
||||||
{
|
{
|
||||||
public enum EnumPlatform
|
public enum EnumPlatform
|
||||||
{
|
{
|
||||||
NES
|
NES
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,166 +1,166 @@
|
|||||||
using AxibugEmuOnline.Client.ClientCore;
|
using AxibugEmuOnline.Client.ClientCore;
|
||||||
using ICSharpCode.SharpZipLib.Zip;
|
using ICSharpCode.SharpZipLib.Zip;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using UnityEngine.Networking;
|
using UnityEngine.Networking;
|
||||||
|
|
||||||
namespace AxibugEmuOnline.Client
|
namespace AxibugEmuOnline.Client
|
||||||
{
|
{
|
||||||
public class RomFile
|
public class RomFile
|
||||||
{
|
{
|
||||||
private HttpAPI.Resp_RomInfo webData;
|
private HttpAPI.Resp_RomInfo webData;
|
||||||
private bool hasLocalFile;
|
private bool hasLocalFile;
|
||||||
private EnumPlatform platform;
|
private EnumPlatform platform;
|
||||||
private UnityWebRequest downloadRequest;
|
private UnityWebRequest downloadRequest;
|
||||||
|
|
||||||
public bool IsUserRom { get; private set; }
|
public bool IsUserRom { get; private set; }
|
||||||
|
|
||||||
/// <summary> 指示该Rom文件的存放路径 </summary>
|
/// <summary> 指示该Rom文件的存放路径 </summary>
|
||||||
public string LocalFilePath =>
|
public string LocalFilePath =>
|
||||||
IsUserRom ?
|
IsUserRom ?
|
||||||
$"{App.PersistentDataPath}/UserRoms/{platform}/{FileName}" :
|
$"{App.PersistentDataPath}/UserRoms/{platform}/{FileName}" :
|
||||||
$"{App.PersistentDataPath}/RemoteRoms/{platform}/{FileName}";
|
$"{App.PersistentDataPath}/RemoteRoms/{platform}/{FileName}";
|
||||||
|
|
||||||
/// <summary> 指示该Rom文件是否已下载完毕 </summary>
|
/// <summary> 指示该Rom文件是否已下载完毕 </summary>
|
||||||
public bool RomReady => hasLocalFile;
|
public bool RomReady => hasLocalFile;
|
||||||
/// <summary> 指示是否正在下载Rom文件 </summary>
|
/// <summary> 指示是否正在下载Rom文件 </summary>
|
||||||
public bool IsDownloading => downloadRequest != null && downloadRequest.result == UnityWebRequest.Result.InProgress;
|
public bool IsDownloading => downloadRequest != null && downloadRequest.result == UnityWebRequest.Result.InProgress;
|
||||||
public float Progress => IsDownloading ? downloadRequest.downloadProgress : 0;
|
public float Progress => IsDownloading ? downloadRequest.downloadProgress : 0;
|
||||||
|
|
||||||
public EnumPlatform Platform => platform;
|
public EnumPlatform Platform => platform;
|
||||||
/// <summary> 指示该Rom信息是否已填充 </summary>
|
/// <summary> 指示该Rom信息是否已填充 </summary>
|
||||||
public bool InfoReady => webData != null;
|
public bool InfoReady => webData != null;
|
||||||
/// <summary> 唯一标识 </summary>
|
/// <summary> 唯一标识 </summary>
|
||||||
public int ID => webData != null ? webData.id : -1;
|
public int ID => webData != null ? webData.id : -1;
|
||||||
/// <summary> 别名 </summary>
|
/// <summary> 别名 </summary>
|
||||||
public string Alias => IsUserRom ? Path.GetFileNameWithoutExtension(FileName) : webData.romName;
|
public string Alias => IsUserRom ? Path.GetFileNameWithoutExtension(FileName) : webData.romName;
|
||||||
/// <summary> 描述 </summary>
|
/// <summary> 描述 </summary>
|
||||||
public string Descript => IsUserRom ? string.Empty : webData.desc;
|
public string Descript => IsUserRom ? string.Empty : webData.desc;
|
||||||
/// <summary> 游戏类型 </summary>
|
/// <summary> 游戏类型 </summary>
|
||||||
public string GameTypeDes => IsUserRom ? string.Empty : webData.gType;
|
public string GameTypeDes => IsUserRom ? string.Empty : webData.gType;
|
||||||
/// <summary> 小图URL </summary>
|
/// <summary> 小图URL </summary>
|
||||||
public string ImageURL => IsUserRom ? string.Empty : webData.imgUrl;
|
public string ImageURL => IsUserRom ? string.Empty : webData.imgUrl;
|
||||||
|
|
||||||
/// <summary> 文件名 </summary>
|
/// <summary> 文件名 </summary>
|
||||||
public string FileName { get; private set; }
|
public string FileName { get; private set; }
|
||||||
/// <summary> 在查询结果中的索引 </summary>
|
/// <summary> 在查询结果中的索引 </summary>
|
||||||
public int Index { get; private set; }
|
public int Index { get; private set; }
|
||||||
/// <summary> 在查询结果中的所在页 </summary>
|
/// <summary> 在查询结果中的所在页 </summary>
|
||||||
public int Page { get; private set; }
|
public int Page { get; private set; }
|
||||||
public string Hash => webData != null ? webData.hash : string.Empty;
|
public string Hash => webData != null ? webData.hash : string.Empty;
|
||||||
|
|
||||||
public event Action<RomFile> OnDownloadOver;
|
public event Action<RomFile> OnDownloadOver;
|
||||||
public event Action OnInfoFilled;
|
public event Action OnInfoFilled;
|
||||||
|
|
||||||
public RomFile(EnumPlatform platform, int index, int insidePage)
|
public RomFile(EnumPlatform platform, int index, int insidePage)
|
||||||
{
|
{
|
||||||
this.platform = platform;
|
this.platform = platform;
|
||||||
Index = index;
|
Index = index;
|
||||||
Page = insidePage;
|
Page = insidePage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BeginDownload()
|
public void BeginDownload()
|
||||||
{
|
{
|
||||||
if (RomReady) return;
|
if (RomReady) return;
|
||||||
if (IsDownloading) return;
|
if (IsDownloading) return;
|
||||||
|
|
||||||
App.StartCoroutine(DownloadRemoteRom((bytes) =>
|
App.StartCoroutine(DownloadRemoteRom((bytes) =>
|
||||||
{
|
{
|
||||||
if (bytes != null)
|
if (bytes != null)
|
||||||
{
|
{
|
||||||
var directPath = Path.GetDirectoryName(LocalFilePath);
|
var directPath = Path.GetDirectoryName(LocalFilePath);
|
||||||
Directory.CreateDirectory(directPath);
|
Directory.CreateDirectory(directPath);
|
||||||
|
|
||||||
File.WriteAllBytes(LocalFilePath, bytes);
|
File.WriteAllBytes(LocalFilePath, bytes);
|
||||||
hasLocalFile = true;
|
hasLocalFile = true;
|
||||||
}
|
}
|
||||||
OnDownloadOver?.Invoke(this);
|
OnDownloadOver?.Invoke(this);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] GetRomFileData()
|
public byte[] GetRomFileData()
|
||||||
{
|
{
|
||||||
if (!IsUserRom && webData == null) throw new Exception("Not Valid Rom");
|
if (!IsUserRom && webData == null) throw new Exception("Not Valid Rom");
|
||||||
if (!RomReady) throw new Exception("Rom File Not Downloaded");
|
if (!RomReady) throw new Exception("Rom File Not Downloaded");
|
||||||
|
|
||||||
var bytes = File.ReadAllBytes(LocalFilePath);
|
var bytes = File.ReadAllBytes(LocalFilePath);
|
||||||
if (Path.GetExtension(LocalFilePath).ToLower() == ".zip")
|
if (Path.GetExtension(LocalFilePath).ToLower() == ".zip")
|
||||||
{
|
{
|
||||||
var zip = new ZipInputStream(new MemoryStream(bytes));
|
var zip = new ZipInputStream(new MemoryStream(bytes));
|
||||||
while (zip.GetNextEntry() is ZipEntry entry)
|
while (zip.GetNextEntry() is ZipEntry entry)
|
||||||
{
|
{
|
||||||
if (!entry.Name.ToLower().EndsWith(".nes")) continue;
|
if (!entry.Name.ToLower().EndsWith(".nes")) continue;
|
||||||
|
|
||||||
var buffer = new byte[1024];
|
var buffer = new byte[1024];
|
||||||
MemoryStream output = new MemoryStream();
|
MemoryStream output = new MemoryStream();
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
var size = zip.Read(buffer, 0, buffer.Length);
|
var size = zip.Read(buffer, 0, buffer.Length);
|
||||||
if (size == 0) break;
|
if (size == 0) break;
|
||||||
else output.Write(buffer, 0, size);
|
else output.Write(buffer, 0, size);
|
||||||
}
|
}
|
||||||
output.Flush();
|
output.Flush();
|
||||||
return output.ToArray();
|
return output.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception("Not Valid Rom Data");
|
throw new Exception("Not Valid Rom Data");
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerator DownloadRemoteRom(Action<byte[]> callback)
|
private IEnumerator DownloadRemoteRom(Action<byte[]> callback)
|
||||||
{
|
{
|
||||||
downloadRequest = UnityWebRequest.Get($"{App.httpAPI.WebHost}/{webData.url}");
|
downloadRequest = UnityWebRequest.Get($"{App.httpAPI.WebHost}/{webData.url}");
|
||||||
yield return downloadRequest.SendWebRequest();
|
yield return downloadRequest.SendWebRequest();
|
||||||
|
|
||||||
var request = downloadRequest;
|
var request = downloadRequest;
|
||||||
downloadRequest = null;
|
downloadRequest = null;
|
||||||
|
|
||||||
if (request.result != UnityWebRequest.Result.Success)
|
if (request.result != UnityWebRequest.Result.Success)
|
||||||
{
|
{
|
||||||
callback(null);
|
callback(null);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
callback(request.downloadHandler.data);
|
callback(request.downloadHandler.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetWebData(HttpAPI.Resp_RomInfo resp_RomInfo)
|
public void SetWebData(HttpAPI.Resp_RomInfo resp_RomInfo)
|
||||||
{
|
{
|
||||||
webData = resp_RomInfo;
|
webData = resp_RomInfo;
|
||||||
FileName = Path.GetFileName(webData.url);
|
FileName = Path.GetFileName(webData.url);
|
||||||
FileName = System.Net.WebUtility.UrlDecode(FileName);
|
FileName = System.Net.WebUtility.UrlDecode(FileName);
|
||||||
|
|
||||||
if (File.Exists(LocalFilePath))
|
if (File.Exists(LocalFilePath))
|
||||||
{
|
{
|
||||||
var fileBytes = File.ReadAllBytes(LocalFilePath);
|
var fileBytes = File.ReadAllBytes(LocalFilePath);
|
||||||
var localHash = RomLib.CalcHash(fileBytes);
|
var localHash = RomLib.CalcHash(fileBytes);
|
||||||
|
|
||||||
hasLocalFile = localHash == webData.hash;
|
hasLocalFile = localHash == webData.hash;
|
||||||
if (!hasLocalFile)
|
if (!hasLocalFile)
|
||||||
File.Delete(LocalFilePath);
|
File.Delete(LocalFilePath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hasLocalFile = false;
|
hasLocalFile = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
OnInfoFilled?.Invoke();
|
OnInfoFilled?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
private RomFile() { }
|
private RomFile() { }
|
||||||
public static RomFile CreateExistRom(EnumPlatform platform, string fileName)
|
public static RomFile CreateExistRom(EnumPlatform platform, string fileName)
|
||||||
{
|
{
|
||||||
var res = new RomFile();
|
var res = new RomFile();
|
||||||
res.IsUserRom = true;
|
res.IsUserRom = true;
|
||||||
res.FileName = fileName;
|
res.FileName = fileName;
|
||||||
res.hasLocalFile = File.Exists(res.LocalFilePath);
|
res.hasLocalFile = File.Exists(res.LocalFilePath);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,153 +1,153 @@
|
|||||||
using AxibugEmuOnline.Client.ClientCore;
|
using AxibugEmuOnline.Client.ClientCore;
|
||||||
using AxibugEmuOnline.Client.Common;
|
using AxibugEmuOnline.Client.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using static AxibugEmuOnline.Client.HttpAPI;
|
using static AxibugEmuOnline.Client.HttpAPI;
|
||||||
|
|
||||||
namespace AxibugEmuOnline.Client
|
namespace AxibugEmuOnline.Client
|
||||||
{
|
{
|
||||||
public class RomLib
|
public class RomLib
|
||||||
{
|
{
|
||||||
/// <summary> Rom请求,一页的大小 </summary>
|
/// <summary> Rom请求,一页的大小 </summary>
|
||||||
private const int PAGE_SIZE = 10;
|
private const int PAGE_SIZE = 10;
|
||||||
|
|
||||||
/// <summary> 请求指令 </summary>
|
/// <summary> 请求指令 </summary>
|
||||||
private HashSet<int> FetchPageCmd = new HashSet<int>();
|
private HashSet<int> FetchPageCmd = new HashSet<int>();
|
||||||
private RomFile[] nesRomFetchList;
|
private RomFile[] nesRomFetchList;
|
||||||
private Dictionary<int, RomFile> nesRomFileIdMapper = new Dictionary<int, RomFile>();
|
private Dictionary<int, RomFile> nesRomFileIdMapper = new Dictionary<int, RomFile>();
|
||||||
private Dictionary<string, RomFile> nesRomFileNameMapper = new Dictionary<string, RomFile>();
|
private Dictionary<string, RomFile> nesRomFileNameMapper = new Dictionary<string, RomFile>();
|
||||||
private HttpAPI.GetRomListAPI m_romGetFunc;
|
private HttpAPI.GetRomListAPI m_romGetFunc;
|
||||||
private HttpAPI.SearchRomListAPI m_romSearchFunc;
|
private HttpAPI.SearchRomListAPI m_romSearchFunc;
|
||||||
private EnumPlatform m_platform;
|
private EnumPlatform m_platform;
|
||||||
|
|
||||||
public RomLib(EnumPlatform platform)
|
public RomLib(EnumPlatform platform)
|
||||||
{
|
{
|
||||||
m_platform = platform;
|
m_platform = platform;
|
||||||
switch (platform)
|
switch (platform)
|
||||||
{
|
{
|
||||||
case EnumPlatform.NES:
|
case EnumPlatform.NES:
|
||||||
m_romGetFunc = App.httpAPI.GetNesRomList;
|
m_romGetFunc = App.httpAPI.GetNesRomList;
|
||||||
m_romSearchFunc = App.httpAPI.SearchNesRomList;
|
m_romSearchFunc = App.httpAPI.SearchNesRomList;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public RomFile GetExistRom(string fileName)
|
public RomFile GetExistRom(string fileName)
|
||||||
{
|
{
|
||||||
var res = RomFile.CreateExistRom(m_platform, fileName);
|
var res = RomFile.CreateExistRom(m_platform, fileName);
|
||||||
|
|
||||||
nesRomFileNameMapper[res.FileName] = res;
|
nesRomFileNameMapper[res.FileName] = res;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RomFile GetRomFile(string romFileName)
|
public RomFile GetRomFile(string romFileName)
|
||||||
{
|
{
|
||||||
RomFile romFile;
|
RomFile romFile;
|
||||||
nesRomFileNameMapper.TryGetValue(romFileName, out romFile);
|
nesRomFileNameMapper.TryGetValue(romFileName, out romFile);
|
||||||
return romFile;
|
return romFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary> 清除所有下载的Rom文件 </summary>
|
/// <summary> 清除所有下载的Rom文件 </summary>
|
||||||
public void ClearRomFile()
|
public void ClearRomFile()
|
||||||
{
|
{
|
||||||
var path = $"{App.PersistentDataPath}/RemoteRoms/{m_platform}";
|
var path = $"{App.PersistentDataPath}/RemoteRoms/{m_platform}";
|
||||||
if (Directory.Exists(path)) Directory.Delete(path, true);
|
if (Directory.Exists(path)) Directory.Delete(path, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> 移除一个已下载的Rom </summary>
|
/// <summary> 移除一个已下载的Rom </summary>
|
||||||
public void RemoveOneRomFile(RomFile romFile)
|
public void RemoveOneRomFile(RomFile romFile)
|
||||||
{
|
{
|
||||||
if (romFile.RomReady)
|
if (romFile.RomReady)
|
||||||
File.Delete(romFile.LocalFilePath);
|
File.Delete(romFile.LocalFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获得所有Rom文件
|
/// 获得所有Rom文件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="callback"></param>
|
/// <param name="callback"></param>
|
||||||
public void FetchRomCount(Action<RomFile[]> callback, string searchKey = null)
|
public void FetchRomCount(Action<RomFile[]> callback, string searchKey = null)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(searchKey))
|
if (string.IsNullOrWhiteSpace(searchKey))
|
||||||
{
|
{
|
||||||
m_romGetFunc((romList) =>
|
m_romGetFunc((romList) =>
|
||||||
{
|
{
|
||||||
FetchPageCmd.Clear();
|
FetchPageCmd.Clear();
|
||||||
nesRomFileIdMapper.Clear();
|
nesRomFileIdMapper.Clear();
|
||||||
nesRomFileNameMapper.Clear();
|
nesRomFileNameMapper.Clear();
|
||||||
nesRomFetchList = new RomFile[romList.resultAllCount];
|
nesRomFetchList = new RomFile[romList.resultAllCount];
|
||||||
for (int i = 0; i < nesRomFetchList.Length; i++)
|
for (int i = 0; i < nesRomFetchList.Length; i++)
|
||||||
{
|
{
|
||||||
//以后考虑用对象池实例化RomFile
|
//以后考虑用对象池实例化RomFile
|
||||||
nesRomFetchList[i] = new RomFile(m_platform, i, i / PAGE_SIZE);
|
nesRomFetchList[i] = new RomFile(m_platform, i, i / PAGE_SIZE);
|
||||||
}
|
}
|
||||||
SaveRomInfoFromWeb(romList);
|
SaveRomInfoFromWeb(romList);
|
||||||
|
|
||||||
callback.Invoke(nesRomFetchList);
|
callback.Invoke(nesRomFetchList);
|
||||||
}, 0, PAGE_SIZE);
|
}, 0, PAGE_SIZE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_romSearchFunc((romList) =>
|
m_romSearchFunc((romList) =>
|
||||||
{
|
{
|
||||||
FetchPageCmd.Clear();
|
FetchPageCmd.Clear();
|
||||||
nesRomFileIdMapper.Clear();
|
nesRomFileIdMapper.Clear();
|
||||||
nesRomFileNameMapper.Clear();
|
nesRomFileNameMapper.Clear();
|
||||||
nesRomFetchList = new RomFile[romList.resultAllCount];
|
nesRomFetchList = new RomFile[romList.resultAllCount];
|
||||||
for (int i = 0; i < nesRomFetchList.Length; i++)
|
for (int i = 0; i < nesRomFetchList.Length; i++)
|
||||||
{
|
{
|
||||||
//以后考虑用对象池实例化RomFile
|
//以后考虑用对象池实例化RomFile
|
||||||
nesRomFetchList[i] = new RomFile(m_platform, i, i / PAGE_SIZE);
|
nesRomFetchList[i] = new RomFile(m_platform, i, i / PAGE_SIZE);
|
||||||
}
|
}
|
||||||
SaveRomInfoFromWeb(romList);
|
SaveRomInfoFromWeb(romList);
|
||||||
|
|
||||||
callback.Invoke(nesRomFetchList);
|
callback.Invoke(nesRomFetchList);
|
||||||
}, searchKey, 0, PAGE_SIZE);
|
}, searchKey, 0, PAGE_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BeginFetchRomInfo(RomFile romFile)
|
public void BeginFetchRomInfo(RomFile romFile)
|
||||||
{
|
{
|
||||||
if (romFile.InfoReady) return;
|
if (romFile.InfoReady) return;
|
||||||
|
|
||||||
FetchPageCmd.Add(romFile.Page);
|
FetchPageCmd.Add(romFile.Page);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ExecuteFetchRomInfo()
|
public void ExecuteFetchRomInfo()
|
||||||
{
|
{
|
||||||
if (FetchPageCmd.Count == 0) return;
|
if (FetchPageCmd.Count == 0) return;
|
||||||
|
|
||||||
foreach (var pageNo in FetchPageCmd)
|
foreach (var pageNo in FetchPageCmd)
|
||||||
{
|
{
|
||||||
m_romGetFunc(SaveRomInfoFromWeb, pageNo, PAGE_SIZE);
|
m_romGetFunc(SaveRomInfoFromWeb, pageNo, PAGE_SIZE);
|
||||||
}
|
}
|
||||||
FetchPageCmd.Clear();
|
FetchPageCmd.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SaveRomInfoFromWeb(Resp_GameList resp)
|
private void SaveRomInfoFromWeb(Resp_GameList resp)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < resp.gameList.Count; i++)
|
for (int i = 0; i < resp.gameList.Count; i++)
|
||||||
{
|
{
|
||||||
var webData = resp.gameList[i];
|
var webData = resp.gameList[i];
|
||||||
RomFile targetRomFile = nesRomFetchList[webData.orderid];
|
RomFile targetRomFile = nesRomFetchList[webData.orderid];
|
||||||
|
|
||||||
targetRomFile.SetWebData(webData);
|
targetRomFile.SetWebData(webData);
|
||||||
nesRomFileIdMapper[webData.id] = nesRomFetchList[webData.orderid];
|
nesRomFileIdMapper[webData.id] = nesRomFetchList[webData.orderid];
|
||||||
nesRomFileNameMapper[targetRomFile.FileName] = targetRomFile;
|
nesRomFileNameMapper[targetRomFile.FileName] = targetRomFile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string CalcHash(byte[] data)
|
public static string CalcHash(byte[] data)
|
||||||
{
|
{
|
||||||
return Helper.FileMD5Hash(data);
|
return Helper.FileMD5Hash(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddRomFile(RomFile rom)
|
public void AddRomFile(RomFile rom)
|
||||||
{
|
{
|
||||||
nesRomFileNameMapper[rom.FileName] = rom;
|
nesRomFileNameMapper[rom.FileName] = rom;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,16 +26,16 @@ namespace AxibugEmuOnline.Client
|
|||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdPing, OnCmdPing);
|
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdPing, OnCmdPing);
|
||||||
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdPong, OnCmdPong);
|
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdPong, OnCmdPong);
|
||||||
|
|
||||||
LoopAction_3s += Ping;
|
LoopAction_3s += Ping;
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
UnityEditor.EditorApplication.playModeStateChanged += (state) =>
|
UnityEditor.EditorApplication.playModeStateChanged += (state) =>
|
||||||
{
|
{
|
||||||
if (state == UnityEditor.PlayModeStateChange.ExitingPlayMode)
|
if (state == UnityEditor.PlayModeStateChange.ExitingPlayMode)
|
||||||
OnApplicationQuit();
|
OnApplicationQuit();
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
float LastLoopTime_1s;
|
float LastLoopTime_1s;
|
||||||
@ -44,14 +44,14 @@ namespace AxibugEmuOnline.Client
|
|||||||
{
|
{
|
||||||
NetMsg.Instance.DequeueNesMsg();
|
NetMsg.Instance.DequeueNesMsg();
|
||||||
|
|
||||||
LoopAction_tick?.Invoke();
|
LoopAction_tick?.Invoke();
|
||||||
|
|
||||||
if (Time.time - LastLoopTime_1s > 1)
|
if (Time.time - LastLoopTime_1s > 1)
|
||||||
{
|
{
|
||||||
LastLoopTime_1s = Time.time;
|
LastLoopTime_1s = Time.time;
|
||||||
LoopAction_1s?.Invoke();
|
LoopAction_1s?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Time.time - LastLoopTime_3s > 3)
|
if (Time.time - LastLoopTime_3s > 3)
|
||||||
{
|
{
|
||||||
LastLoopTime_3s = Time.time;
|
LastLoopTime_3s = Time.time;
|
||||||
@ -61,7 +61,7 @@ namespace AxibugEmuOnline.Client
|
|||||||
|
|
||||||
void OnApplicationQuit()
|
void OnApplicationQuit()
|
||||||
{
|
{
|
||||||
App.log.Debug("OnApplicationQuit");
|
App.log.Debug("OnApplicationQuit");
|
||||||
App.network.bAutoReConnect = false;
|
App.network.bAutoReConnect = false;
|
||||||
|
|
||||||
if (App.network.isConnected)
|
if (App.network.isConnected)
|
@ -1,45 +1,45 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// StringºÍBoolµÄ·ìºÏ¹Ö
|
/// StringºÍBoolµÄ·ìºÏ¹Ö
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public struct MsgBool
|
public struct MsgBool
|
||||||
{
|
{
|
||||||
public string ErrorMsg;
|
public string ErrorMsg;
|
||||||
public bool Value;
|
public bool Value;
|
||||||
|
|
||||||
public override readonly string ToString()
|
public override readonly string ToString()
|
||||||
{
|
{
|
||||||
if (Value)
|
if (Value)
|
||||||
{
|
{
|
||||||
return true.ToString();
|
return true.ToString();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return ErrorMsg;
|
return ErrorMsg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator MsgBool(string errorMsg)
|
public static implicit operator MsgBool(string errorMsg)
|
||||||
{
|
{
|
||||||
return new MsgBool { Value = false, ErrorMsg = errorMsg };
|
return new MsgBool { Value = false, ErrorMsg = errorMsg };
|
||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator MsgBool(bool value)
|
public static implicit operator MsgBool(bool value)
|
||||||
{
|
{
|
||||||
return new MsgBool { Value = value };
|
return new MsgBool { Value = value };
|
||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator bool(MsgBool msgBool)
|
public static implicit operator bool(MsgBool msgBool)
|
||||||
{
|
{
|
||||||
return msgBool.Value;
|
return msgBool.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator (bool, string)(MsgBool msgBool)
|
public static implicit operator (bool, string)(MsgBool msgBool)
|
||||||
{
|
{
|
||||||
return (msgBool.Value, msgBool.ErrorMsg);
|
return (msgBool.Value, msgBool.ErrorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator string(MsgBool msgBool)
|
public static implicit operator string(MsgBool msgBool)
|
||||||
{
|
{
|
||||||
return msgBool.ToString();
|
return msgBool.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,52 +1,52 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using VirtualNes.Core;
|
using VirtualNes.Core;
|
||||||
|
|
||||||
namespace AxibugEmuOnline.Client
|
namespace AxibugEmuOnline.Client
|
||||||
{
|
{
|
||||||
public class AudioProvider : MonoBehaviour
|
public class AudioProvider : MonoBehaviour
|
||||||
{
|
{
|
||||||
public NesEmulator NesEmu { get; set; }
|
public NesEmulator NesEmu { get; set; }
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private AudioSource m_as;
|
private AudioSource m_as;
|
||||||
|
|
||||||
private SoundBuffer _buffer = new SoundBuffer(4096);
|
private SoundBuffer _buffer = new SoundBuffer(4096);
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
var dummy = AudioClip.Create("dummy", 1, 1, AudioSettings.outputSampleRate, false);
|
var dummy = AudioClip.Create("dummy", 1, 1, AudioSettings.outputSampleRate, false);
|
||||||
dummy.SetData(new float[] { 1 }, 0);
|
dummy.SetData(new float[] { 1 }, 0);
|
||||||
m_as.clip = dummy; //just to let unity play the audiosource
|
m_as.clip = dummy; //just to let unity play the audiosource
|
||||||
m_as.loop = true;
|
m_as.loop = true;
|
||||||
m_as.spatialBlend = 1;
|
m_as.spatialBlend = 1;
|
||||||
m_as.Play();
|
m_as.Play();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnAudioFilterRead(float[] data, int channels)
|
void OnAudioFilterRead(float[] data, int channels)
|
||||||
{
|
{
|
||||||
int step = channels;
|
int step = channels;
|
||||||
|
|
||||||
if (NesEmu == null || NesEmu.NesCore == null) return;
|
if (NesEmu == null || NesEmu.NesCore == null) return;
|
||||||
if (NesEmu.IsPause) return;
|
if (NesEmu.IsPause) return;
|
||||||
|
|
||||||
ProcessSound(NesEmu.NesCore, (uint)(data.Length / channels));
|
ProcessSound(NesEmu.NesCore, (uint)(data.Length / channels));
|
||||||
|
|
||||||
for (int i = 0; i < data.Length; i += step)
|
for (int i = 0; i < data.Length; i += step)
|
||||||
{
|
{
|
||||||
float rawFloat = 0;
|
float rawFloat = 0;
|
||||||
byte rawData;
|
byte rawData;
|
||||||
if (_buffer.TryRead(out rawData))
|
if (_buffer.TryRead(out rawData))
|
||||||
rawFloat = rawData / 255f;
|
rawFloat = rawData / 255f;
|
||||||
|
|
||||||
data[i] = rawFloat;
|
data[i] = rawFloat;
|
||||||
for (int fill = 1; fill < step; fill++)
|
for (int fill = 1; fill < step; fill++)
|
||||||
data[i + fill] = rawFloat;
|
data[i + fill] = rawFloat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessSound(NES nes, uint feedCount)
|
void ProcessSound(NES nes, uint feedCount)
|
||||||
{
|
{
|
||||||
nes.apu.Process(_buffer, feedCount);
|
nes.apu.Process(_buffer, feedCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,18 +1,18 @@
|
|||||||
using AxibugEmuOnline.Client.ClientCore;
|
using AxibugEmuOnline.Client.ClientCore;
|
||||||
using VirtualNes.Core.Debug;
|
using VirtualNes.Core.Debug;
|
||||||
|
|
||||||
namespace AxibugEmuOnline.Client
|
namespace AxibugEmuOnline.Client
|
||||||
{
|
{
|
||||||
public class CoreDebuger : IDebugerImpl
|
public class CoreDebuger : IDebugerImpl
|
||||||
{
|
{
|
||||||
public void Log(string message)
|
public void Log(string message)
|
||||||
{
|
{
|
||||||
App.log.Info(message);
|
App.log.Info(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LogError(string message)
|
public void LogError(string message)
|
||||||
{
|
{
|
||||||
App.log.Error(message);
|
App.log.Error(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,171 +1,171 @@
|
|||||||
using AxibugEmuOnline.Client.ClientCore;
|
using AxibugEmuOnline.Client.ClientCore;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using VirtualNes.Core;
|
using VirtualNes.Core;
|
||||||
|
|
||||||
namespace AxibugEmuOnline.Client
|
namespace AxibugEmuOnline.Client
|
||||||
{
|
{
|
||||||
public class CoreSupporter : ISupporterImpl
|
public class CoreSupporter : ISupporterImpl
|
||||||
{
|
{
|
||||||
public Stream OpenRom(string fname)
|
public Stream OpenRom(string fname)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var romFile = App.nesRomLib.GetRomFile(fname);
|
var romFile = App.nesRomLib.GetRomFile(fname);
|
||||||
var bytes = romFile.GetRomFileData();
|
var bytes = romFile.GetRomFileData();
|
||||||
Debug.Log($"Open {romFile.Alias}");
|
Debug.Log($"Open {romFile.Alias}");
|
||||||
return new MemoryStream(bytes);
|
return new MemoryStream(bytes);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogError(ex);
|
Debug.LogError(ex);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetRomPathInfo(string fname, out string fullPath, out string directPath)
|
public void GetRomPathInfo(string fname, out string fullPath, out string directPath)
|
||||||
{
|
{
|
||||||
var romFile = App.nesRomLib.GetRomFile(fname);
|
var romFile = App.nesRomLib.GetRomFile(fname);
|
||||||
UnityEngine.Debug.Assert(romFile != null);
|
UnityEngine.Debug.Assert(romFile != null);
|
||||||
|
|
||||||
fullPath = romFile.LocalFilePath;
|
fullPath = romFile.LocalFilePath;
|
||||||
directPath = Path.GetDirectoryName(fullPath);
|
directPath = Path.GetDirectoryName(fullPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream OpenFile_DISKSYS()
|
public Stream OpenFile_DISKSYS()
|
||||||
{
|
{
|
||||||
return new MemoryStream(Resources.Load<TextAsset>("NES/Disksys.rom").bytes);
|
return new MemoryStream(Resources.Load<TextAsset>("NES/Disksys.rom").bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveSRAMToFile(byte[] sramContent, string romName)
|
public void SaveSRAMToFile(byte[] sramContent, string romName)
|
||||||
{
|
{
|
||||||
string sramDirectoryPath = $"{App.PersistentDataPath}/sav";
|
string sramDirectoryPath = $"{App.PersistentDataPath}/sav";
|
||||||
Directory.CreateDirectory(sramDirectoryPath);
|
Directory.CreateDirectory(sramDirectoryPath);
|
||||||
romName = Path.GetFileNameWithoutExtension(romName);
|
romName = Path.GetFileNameWithoutExtension(romName);
|
||||||
File.WriteAllBytes($"{sramDirectoryPath}/{romName}.sav", sramContent);
|
File.WriteAllBytes($"{sramDirectoryPath}/{romName}.sav", sramContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveDISKToFile(byte[] diskFileContent, string romName)
|
public void SaveDISKToFile(byte[] diskFileContent, string romName)
|
||||||
{
|
{
|
||||||
string diskFileDirectoryPath = $"{App.PersistentDataPath}/dsv";
|
string diskFileDirectoryPath = $"{App.PersistentDataPath}/dsv";
|
||||||
Directory.CreateDirectory(diskFileDirectoryPath);
|
Directory.CreateDirectory(diskFileDirectoryPath);
|
||||||
romName = Path.GetFileNameWithoutExtension(romName);
|
romName = Path.GetFileNameWithoutExtension(romName);
|
||||||
File.WriteAllBytes($"{diskFileDirectoryPath}/{romName}.dsv", diskFileContent);
|
File.WriteAllBytes($"{diskFileDirectoryPath}/{romName}.dsv", diskFileContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public EmulatorConfig Config { get; private set; } = new EmulatorConfig();
|
public EmulatorConfig Config { get; private set; } = new EmulatorConfig();
|
||||||
public NesControllerMapper ControllerMapper { get; private set; } = new NesControllerMapper();
|
public NesControllerMapper ControllerMapper { get; private set; } = new NesControllerMapper();
|
||||||
public void PrepareDirectory(string directPath)
|
public void PrepareDirectory(string directPath)
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory($"{App.PersistentDataPath}/{directPath}");
|
Directory.CreateDirectory($"{App.PersistentDataPath}/{directPath}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveFile(byte[] fileData, string directPath, string fileName)
|
public void SaveFile(byte[] fileData, string directPath, string fileName)
|
||||||
{
|
{
|
||||||
PrepareDirectory(directPath);
|
PrepareDirectory(directPath);
|
||||||
|
|
||||||
var fileFullpath = $"{App.PersistentDataPath}/{directPath}/{fileName}";
|
var fileFullpath = $"{App.PersistentDataPath}/{directPath}/{fileName}";
|
||||||
File.WriteAllBytes(fileFullpath, fileData);
|
File.WriteAllBytes(fileFullpath, fileData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream OpenFile(string directPath, string fileName)
|
public Stream OpenFile(string directPath, string fileName)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var data = File.ReadAllBytes($"{App.PersistentDataPath}/{directPath}/{fileName}");
|
var data = File.ReadAllBytes($"{App.PersistentDataPath}/{directPath}/{fileName}");
|
||||||
if (data == null) return null;
|
if (data == null) return null;
|
||||||
return new MemoryStream(data);
|
return new MemoryStream(data);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetMapperNo(ROM rom, out int mapperNo)
|
public bool TryGetMapperNo(ROM rom, out int mapperNo)
|
||||||
{
|
{
|
||||||
var db = Resources.Load<RomDB>("NES/ROMDB");
|
var db = Resources.Load<RomDB>("NES/ROMDB");
|
||||||
return db.GetMapperNo(rom.GetPROM_CRC(), out mapperNo);
|
return db.GetMapperNo(rom.GetPROM_CRC(), out mapperNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ControllerState m_sampledState;
|
private ControllerState m_sampledState;
|
||||||
public ControllerState GetControllerState()
|
public ControllerState GetControllerState()
|
||||||
{
|
{
|
||||||
return m_sampledState;
|
return m_sampledState;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint LastTestInput = 0;
|
uint LastTestInput = 0;
|
||||||
public void SampleInput(uint frameIndex)
|
public void SampleInput(uint frameIndex)
|
||||||
{
|
{
|
||||||
if (InGameUI.Instance.IsNetPlay)
|
if (InGameUI.Instance.IsNetPlay)
|
||||||
{
|
{
|
||||||
if (App.roomMgr.netReplay.TryGetNextFrame((int)frameIndex, out var replayData, out int frameDiff, out bool inputDiff))
|
if (App.roomMgr.netReplay.TryGetNextFrame((int)frameIndex, out var replayData, out int frameDiff, out bool inputDiff))
|
||||||
{
|
{
|
||||||
if (inputDiff)
|
if (inputDiff)
|
||||||
{
|
{
|
||||||
App.log.Debug($"{DateTime.Now.ToString("hh:mm:ss.fff")} TryGetNextFrame remoteFrame->{App.roomMgr.netReplay.mRemoteFrameIdx} diff->{frameDiff} " +
|
App.log.Debug($"{DateTime.Now.ToString("hh:mm:ss.fff")} TryGetNextFrame remoteFrame->{App.roomMgr.netReplay.mRemoteFrameIdx} diff->{frameDiff} " +
|
||||||
$"frame=>{replayData.FrameStartID} InPut=>{replayData.InPut}");
|
$"frame=>{replayData.FrameStartID} InPut=>{replayData.InPut}");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_sampledState = FromNet(replayData);
|
m_sampledState = FromNet(replayData);
|
||||||
}
|
}
|
||||||
else m_sampledState = default;
|
else m_sampledState = default;
|
||||||
|
|
||||||
var localState = ControllerMapper.CreateState();
|
var localState = ControllerMapper.CreateState();
|
||||||
var rawData = ToNet(localState);
|
var rawData = ToNet(localState);
|
||||||
if (LastTestInput != rawData)
|
if (LastTestInput != rawData)
|
||||||
{
|
{
|
||||||
LastTestInput = rawData;
|
LastTestInput = rawData;
|
||||||
App.log.Debug($"{DateTime.Now.ToString("hh:mm:ss.fff")} Input F:{App.roomMgr.netReplay.mCurrClientFrameIdx} | I:{rawData}");
|
App.log.Debug($"{DateTime.Now.ToString("hh:mm:ss.fff")} Input F:{App.roomMgr.netReplay.mCurrClientFrameIdx} | I:{rawData}");
|
||||||
}
|
}
|
||||||
App.roomMgr.SendRoomSingelPlayerInput(frameIndex, rawData);
|
App.roomMgr.SendRoomSingelPlayerInput(frameIndex, rawData);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_sampledState = ControllerMapper.CreateState();
|
m_sampledState = ControllerMapper.CreateState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ControllerState FromNet(AxiReplay.ReplayStep step)
|
public ControllerState FromNet(AxiReplay.ReplayStep step)
|
||||||
{
|
{
|
||||||
var temp = new ServerInputSnapShot();
|
var temp = new ServerInputSnapShot();
|
||||||
var result = new ControllerState();
|
var result = new ControllerState();
|
||||||
temp.all = step.InPut;
|
temp.all = step.InPut;
|
||||||
result.raw0 = temp.p1;
|
result.raw0 = temp.p1;
|
||||||
result.raw1 = temp.p2;
|
result.raw1 = temp.p2;
|
||||||
result.raw2 = temp.p3;
|
result.raw2 = temp.p3;
|
||||||
result.raw3 = temp.p4;
|
result.raw3 = temp.p4;
|
||||||
result.valid = true;
|
result.valid = true;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint ToNet(ControllerState state)
|
public uint ToNet(ControllerState state)
|
||||||
{
|
{
|
||||||
var temp = new ServerInputSnapShot();
|
var temp = new ServerInputSnapShot();
|
||||||
temp.p1 = (byte)state.raw0;
|
temp.p1 = (byte)state.raw0;
|
||||||
temp.p2 = (byte)state.raw1;
|
temp.p2 = (byte)state.raw1;
|
||||||
temp.p3 = (byte)state.raw2;
|
temp.p3 = (byte)state.raw2;
|
||||||
temp.p4 = (byte)state.raw3;
|
temp.p4 = (byte)state.raw3;
|
||||||
return (uint)temp.all;
|
return (uint)temp.all;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Explicit, Size = 8)]
|
[StructLayout(LayoutKind.Explicit, Size = 8)]
|
||||||
struct ServerInputSnapShot
|
struct ServerInputSnapShot
|
||||||
{
|
{
|
||||||
[FieldOffset(0)]
|
[FieldOffset(0)]
|
||||||
public UInt64 all;
|
public UInt64 all;
|
||||||
[FieldOffset(0)]
|
[FieldOffset(0)]
|
||||||
public byte p1;
|
public byte p1;
|
||||||
[FieldOffset(1)]
|
[FieldOffset(1)]
|
||||||
public byte p2;
|
public byte p2;
|
||||||
[FieldOffset(2)]
|
[FieldOffset(2)]
|
||||||
public byte p3;
|
public byte p3;
|
||||||
[FieldOffset(3)]
|
[FieldOffset(3)]
|
||||||
public byte p4;
|
public byte p4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user