Compare commits

...

2 Commits

31 changed files with 673 additions and 596 deletions

View File

@ -36,7 +36,7 @@ namespace AxibugEmuOnline.Client.ClientCore
private static CoroutineRunner coRunner; private static CoroutineRunner coRunner;
#endregion #endregion
#if UNITY_PSP2 #if UNITY_PSP2 && !UNITY_EDITOR //PSV真机
public static string PersistentDataPath => "ux0:data/AxibugEmu"; public static string PersistentDataPath => "ux0:data/AxibugEmu";
#else #else
public static string PersistentDataPath => Application.persistentDataPath; public static string PersistentDataPath => Application.persistentDataPath;
@ -45,7 +45,13 @@ namespace AxibugEmuOnline.Client.ClientCore
{ {
PlayerPrefs.DeleteAll(); PlayerPrefs.DeleteAll();
settings = new AppSettings(); if (UnityEngine.Application.platform == RuntimePlatform.PSP2)
{
//PSV 等平台需要手动创建目录
PSP2Init();
}
settings = new AppSettings();
log = new LogManager(); log = new LogManager();
LogManager.OnLog += OnNoSugarNetLog; LogManager.OnLog += OnNoSugarNetLog;
@ -68,11 +74,6 @@ namespace AxibugEmuOnline.Client.ClientCore
tickLoop = go.AddComponent<TickLoop>(); tickLoop = go.AddComponent<TickLoop>();
coRunner = go.AddComponent<CoroutineRunner>(); coRunner = go.AddComponent<CoroutineRunner>();
if (UnityEngine.Application.platform == RuntimePlatform.PSP2)
{
//PSV 等平台需要手动创建目录
PersistentDataPathDir();
}
var importNode = GameObject.Find("IMPORTENT"); var importNode = GameObject.Find("IMPORTENT");
if (importNode != null) GameObject.DontDestroyOnLoad(importNode); if (importNode != null) GameObject.DontDestroyOnLoad(importNode);
@ -81,12 +82,17 @@ namespace AxibugEmuOnline.Client.ClientCore
RePullNetInfo(); RePullNetInfo();
} }
private static void PersistentDataPathDir()
private static void PSP2Init()
{ {
//PSVita最好手动创建目录
if (!Directory.Exists(PersistentDataPath)) if (!Directory.Exists(PersistentDataPath))
{
Directory.CreateDirectory(PersistentDataPath); Directory.CreateDirectory(PersistentDataPath);
}
#if UNITY_PSP2
//释放解码 FMV的26M内存一般游戏用不上PSP才用那破玩意儿
UnityEngine.PSVita.PSVitaVideoPlayer.TransferMemToMonoHeap();
#endif
} }
private static IEnumerator AppTickFlow() private static IEnumerator AppTickFlow()

View File

@ -1,19 +1,12 @@
{ {
"name": "AxibugEmuOnline.Client", "name": "AxibugEmuOnline.Client",
"rootNamespace": "AxibugEmuOnline.Client",
"references": [ "references": [
"VirtualNes.Core",
"UIEffect", "UIEffect",
"AxiReplay", "AxiReplay",
"Unity.Postprocessing.Runtime" "Unity.Postprocessing.Runtime"
], ],
"optionalUnityReferences": [],
"includePlatforms": [], "includePlatforms": [],
"excludePlatforms": [], "excludePlatforms": [],
"allowUnsafeCode": true, "allowUnsafeCode": true
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
} }

View File

@ -248,7 +248,19 @@ Shader "PostEffect/FixingPixcelArtGrille"
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;}
#else
// VGA style shadow mask.
float3 Mask(float2 pos){
pos.xy=floor(pos.xy*float2(1.0,0.5));
pos.x+=pos.y*3.0;
float3 mask=float3(_maskDark,_maskDark,_maskDark);
pos.x=fract(pos.x/6.0);
if(pos.x<0.333)mask.r=_maskLight;
else if(pos.x<0.666)mask.g=_maskLight;
else mask.b=_maskLight;
return mask;}
#endif #endif

View File

@ -13,7 +13,7 @@ namespace AxibugEmuOnline.Client.Manager
/// </summary> /// </summary>
private IEmuCore m_emuCore; private IEmuCore m_emuCore;
private IControllerSetuper m_controllerSetuper; private VirtualNes.Core.IControllerSetuper m_controllerSetuper;
/// <summary> /// <summary>
/// unity的c#实现有bug,以接口类型保存的monobehaviour引用,!=和==运算符没有调用到monobehaviour重写过的运算符 /// unity的c#实现有bug,以接口类型保存的monobehaviour引用,!=和==运算符没有调用到monobehaviour重写过的运算符
@ -84,10 +84,15 @@ namespace AxibugEmuOnline.Client.Manager
else //在房间中则使用服务器下发的手柄槽位信息分配本地手柄 else //在房间中则使用服务器下发的手柄槽位信息分配本地手柄
{ {
long selfUID = App.user.userdata.UID; long selfUID = App.user.userdata.UID;
App.roomMgr.mineRoomMiniInfo.GetPlayerSlotIdxByUid(selfUID, 0, out var con0Slot); uint? con0Slot;
App.roomMgr.mineRoomMiniInfo.GetPlayerSlotIdxByUid(selfUID, 1, out var con1Slot); uint? con1Slot;
App.roomMgr.mineRoomMiniInfo.GetPlayerSlotIdxByUid(selfUID, 2, out var con2Slot); uint? con2Slot;
App.roomMgr.mineRoomMiniInfo.GetPlayerSlotIdxByUid(selfUID, 3, out var con3Slot); uint? con3Slot;
App.roomMgr.mineRoomMiniInfo.GetPlayerSlotIdxByUid(selfUID, 0, out con0Slot);
App.roomMgr.mineRoomMiniInfo.GetPlayerSlotIdxByUid(selfUID, 1, out con1Slot);
App.roomMgr.mineRoomMiniInfo.GetPlayerSlotIdxByUid(selfUID, 2, out con2Slot);
App.roomMgr.mineRoomMiniInfo.GetPlayerSlotIdxByUid(selfUID, 3, out con3Slot);
m_controllerSetuper.SetConnect(con0Slot, con1Slot, con2Slot, con3Slot); m_controllerSetuper.SetConnect(con0Slot, con1Slot, con2Slot, con3Slot);
} }

View File

@ -62,10 +62,13 @@ namespace AxibugEmuOnline.Client
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) object cacheObj;
if (cachesInMemory.TryGetValue(url, out cacheObj) && cacheObj is T)
{ {
callback.Invoke(obj, url); T obj = (T)cacheObj;
callback.Invoke(obj, url);
return; return;
} }

View File

@ -22,6 +22,8 @@ namespace AxibugEmuOnline.Client
public FilterManager(PostProcessVolume filterVolume, CanvasGroup filterPreview, CanvasGroup mainBg) public FilterManager(PostProcessVolume filterVolume, CanvasGroup filterPreview, CanvasGroup mainBg)
{ {
if (filterVolume == null)
return;
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));
@ -86,23 +88,40 @@ namespace AxibugEmuOnline.Client
/// </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 GetFilterSetting_result 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); filter = Filters.FirstOrDefault(f => f.Name == value.Item1);
if (filter != null)
{
string presetName = value.Item2;
preset = filter.Presets.FirstOrDefault(p => p.Name == presetName);
}
return new GetFilterSetting_result()
{
filter = filter,
preset = preset
};
} }
public class Filter public struct GetFilterSetting_result
{
public Filter filter;
public FilterPreset preset;
}
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;
@ -223,8 +242,8 @@ namespace AxibugEmuOnline.Client
public string GetParamValueJson(string paramName) public string GetParamValueJson(string paramName)
{ {
prepareCache(); prepareCache();
string value;
m_paramName2ValueJson.TryGetValue(paramName, out var value); m_paramName2ValueJson.TryGetValue(paramName, out value);
return value; return value;
} }
@ -234,8 +253,9 @@ namespace AxibugEmuOnline.Client
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 floatVal;
float.TryParse(rawStr, out floatVal);
return floatVal; return floatVal;
} }
else if (valueType.IsEnum) else if (valueType.IsEnum)
@ -309,12 +329,13 @@ namespace AxibugEmuOnline.Client
return JsonUtility.ToJson(this); return JsonUtility.ToJson(this);
} }
public (string filterName, string presetName) Get(RomFile rom) public ValueTuple<string,string> Get(RomFile rom)
{ {
prepareCache(); prepareCache();
m_cache.TryGetValue(rom.ID, out var item); Item item;
return (item.FilterName, item.PresetName); m_cache.TryGetValue(rom.ID, out item);
return new ValueTuple<string, string>(item.FilterName, item.PresetName);
} }
private void prepareCache() private void prepareCache()

View File

@ -5,6 +5,7 @@ using System.Collections;
using System.IO; using System.IO;
using UnityEngine; using UnityEngine;
using UnityEngine.Networking; using UnityEngine.Networking;
using static UnityEngine.EventSystems.EventTrigger;
namespace AxibugEmuOnline.Client namespace AxibugEmuOnline.Client
{ {
@ -95,9 +96,11 @@ namespace AxibugEmuOnline.Client
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) var entry = zip.GetNextEntry() as ZipEntry;
while (entry != null)
{ {
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();

View File

@ -154,14 +154,16 @@ namespace AxibugEmuOnline.Client.Manager
for (int i = 0; i < msg.UserList.Count; i++) for (int i = 0; i < msg.UserList.Count; i++)
{ {
UserMiniInfo mi = msg.UserList[i]; UserMiniInfo mi = msg.UserList[i];
UpdateOrAddUser(mi, out bool isNewUser); bool isNewUser;
UpdateOrAddUser(mi, out isNewUser);
} }
Eventer.Instance.PostEvent(EEvent.OnUserListAllUpdate); Eventer.Instance.PostEvent(EEvent.OnUserListAllUpdate);
} }
public void RecvCmdUserJoin(byte[] reqData) public void RecvCmdUserJoin(byte[] reqData)
{ {
Protobuf_UserJoin_RESP msg = ProtoBufHelper.DeSerizlize<Protobuf_UserJoin_RESP>(reqData); Protobuf_UserJoin_RESP msg = ProtoBufHelper.DeSerizlize<Protobuf_UserJoin_RESP>(reqData);
UpdateOrAddUser(msg.UserInfo, out bool isNewUser); bool isNewUser;
UpdateOrAddUser(msg.UserInfo, out isNewUser);
if (isNewUser) if (isNewUser)
{ {
Eventer.Instance.PostEvent(EEvent.OnUserLogin, msg.UserInfo.UID, msg.UserInfo.NickName); Eventer.Instance.PostEvent(EEvent.OnUserLogin, msg.UserInfo.UID, msg.UserInfo.NickName);

View File

@ -6,7 +6,7 @@ public struct MsgBool
public string ErrorMsg; public string ErrorMsg;
public bool Value; public bool Value;
public override readonly string ToString() public override string ToString()
{ {
if (Value) if (Value)
{ {
@ -33,10 +33,10 @@ public struct 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)
{ {

View File

@ -1,4 +1,5 @@
using AxibugEmuOnline.Client.ClientCore; using AxibugEmuOnline.Client.ClientCore;
using AxiReplay;
using System; using System;
using System.IO; using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -101,8 +102,9 @@ namespace AxibugEmuOnline.Client
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)) int targetFrame; ReplayStep replayData; int frameDiff; bool inputDiff;
if (App.roomMgr.netReplay.TryGetNextFrame((int)frameIndex, out replayData, out frameDiff, out inputDiff))
{ {
if (inputDiff) if (inputDiff)
{ {
@ -112,7 +114,7 @@ namespace AxibugEmuOnline.Client
m_sampledState = FromNet(replayData); m_sampledState = FromNet(replayData);
} }
else m_sampledState = default; else m_sampledState = default(ControllerState);
var localState = ControllerMapper.CreateState(); var localState = ControllerMapper.CreateState();
var rawData = ToNet(localState); var rawData = ToNet(localState);

View File

@ -5,10 +5,10 @@ namespace AxibugEmuOnline.Client
{ {
public class NesControllerMapper : IControllerSetuper public class NesControllerMapper : IControllerSetuper
{ {
public Controller Controller0 { get; } = new(0); public Controller Controller0 { get; } = new Controller(0);
public Controller Controller1 { get; } = new(1); public Controller Controller1 { get; } = new Controller(1);
public Controller Controller2 { get; } = new(2); public Controller Controller2 { get; } = new Controller(2);
public Controller Controller3 { get; } = new(3); public Controller Controller3 { get; } = new Controller(3);
private readonly EnumButtonType[] m_states = new EnumButtonType[4]; private readonly EnumButtonType[] m_states = new EnumButtonType[4];
@ -138,7 +138,7 @@ namespace AxibugEmuOnline.Client
} }
} }
public readonly struct KeyListener public struct KeyListener
{ {
private readonly KeyCode m_key; private readonly KeyCode m_key;
@ -152,7 +152,8 @@ namespace AxibugEmuOnline.Client
{ {
m_key = KeyCode.None; m_key = KeyCode.None;
if (int.TryParse(confStr, out int result)) int result;
if (int.TryParse(confStr, out result))
m_key = (KeyCode)result; m_key = (KeyCode)result;
} }
@ -220,7 +221,7 @@ namespace AxibugEmuOnline.Client
break; break;
} }
return default; return default(KeyListener);
} }
} }

View File

@ -2,24 +2,19 @@
%TAG !u! tag:unity3d.com,2011: %TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000 --- !u!21 &2100000
Material: Material:
serializedVersion: 8 serializedVersion: 6
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0} m_PrefabInternal: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: NesEmulator_Screen m_Name: NesEmulator_Screen
m_Shader: {fileID: 4800000, guid: b351396ff606116478d7f4412abe4e2e, type: 3} m_Shader: {fileID: 4800000, guid: b351396ff606116478d7f4412abe4e2e, type: 3}
m_Parent: {fileID: 0} m_ShaderKeywords:
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4 m_LightmapFlags: 4
m_EnableInstancingVariants: 0 m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0 m_DoubleSidedGI: 0
m_CustomRenderQueue: -1 m_CustomRenderQueue: -1
stringTagMap: {} stringTagMap: {}
disabledShaderPasses: [] disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties: m_SavedProperties:
serializedVersion: 3 serializedVersion: 3
m_TexEnvs: m_TexEnvs:
@ -63,7 +58,6 @@ Material:
m_Texture: {fileID: 0} m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1} m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0} m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats: m_Floats:
- _BumpScale: 1 - _BumpScale: 1
- _ColorMask: 15 - _ColorMask: 15
@ -91,5 +85,3 @@ Material:
m_Colors: m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1} - _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1} - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1

View File

@ -13,7 +13,7 @@ namespace AxibugEmuOnline.Client.Network
private Dictionary<int, List<Delegate>> netEventDic = new Dictionary<int, List<Delegate>>(128); private Dictionary<int, List<Delegate>> netEventDic = new Dictionary<int, List<Delegate>>(128);
private Queue<(int, int, byte[])> queueNetMsg = new Queue<(int, int, byte[])>(); private Queue<ValueTuple<int, int, byte[]>> queueNetMsg = new Queue<ValueTuple<int, int, byte[]>>();
private NetMsg() { } private NetMsg() { }
@ -66,7 +66,7 @@ namespace AxibugEmuOnline.Client.Network
{ {
lock (lockQueueObj) lock (lockQueueObj)
{ {
queueNetMsg.Enqueue((cmd, ERRCODE, arg)); queueNetMsg.Enqueue(new ValueTuple<int,int,byte[]>(cmd, ERRCODE, arg));
} }
} }
@ -76,7 +76,8 @@ namespace AxibugEmuOnline.Client.Network
{ {
while (queueNetMsg.Count > 0) while (queueNetMsg.Count > 0)
{ {
(int, int, byte[]) msgData = queueNetMsg.Dequeue();
var msgData = queueNetMsg.Dequeue();
PostNetMsgEvent(msgData.Item1, msgData.Item2, msgData.Item3); PostNetMsgEvent(msgData.Item1, msgData.Item2, msgData.Item3);
} }
} }

View File

@ -39,7 +39,7 @@ namespace AxibugEmuOnline.Client
public void SetDependencyProperty(object data) public void SetDependencyProperty(object data)
{ {
SetSelectState(data is ThirdMenuRoot tr && tr.SelectIndex == Index); SetSelectState(data is ThirdMenuRoot && ((ThirdMenuRoot)data).SelectIndex == Index);
} }
public void Release() public void Release()

View File

@ -7,191 +7,192 @@ using UnityEngine;
using static AxibugEmuOnline.Client.FilterManager; using static AxibugEmuOnline.Client.FilterManager;
namespace AxibugEmuOnline.Client namespace AxibugEmuOnline.Client
{ {
/// <summary> /// <summary>
/// 背景颜色设置UI /// 背景颜色设置UI
/// </summary> /// </summary>
public class UI_FilterItem : MenuItem, IVirtualItem public class UI_FilterItem : MenuItem, IVirtualItem
{ {
public int Index { get; set; } public int Index { get; set; }
public Filter Datacontext { get; private set; } public Filter Datacontext { get; private set; }
public void SetData(object data)
{
Datacontext = data as Filter;
UpdateView();
}
private void UpdateView()
{
if (Datacontext == null)
SetBaseInfo("无", null, null);
else
SetBaseInfo(Datacontext.Name, $"参数数量:{Datacontext.Paramerters.Count}", null);
}
public void SetDependencyProperty(object data)
{
SetSelectState(data is ThirdMenuRoot tr && tr.SelectIndex == Index);
if (m_select)
{
App.filter.EnableFilterPreview();
if (App.filter != null)
App.filter.EnableFilter(Datacontext);
else
App.filter.ShutDownFilter();
}
}
public void Release() { }
public override bool OnEnterItem()
{
if (Datacontext != null && Datacontext.Paramerters.Count > 0)
{
var opts = new List<OptionMenu>();
opts.Add(new Opt_CreatePreset(Datacontext));
opts.AddRange(Datacontext.Presets.Select(p => new Opt_Presets(Datacontext, p)));
OverlayManager.PopSideBar(opts, onClose: () => public void SetData(object data)
{ {
App.filter.EnableFilterPreview(); Datacontext = data as Filter;
Datacontext.ResetPreset();
App.filter.EnableFilter(Datacontext); UpdateView();
}); }
}
return false; private void UpdateView()
} {
if (Datacontext == null)
SetBaseInfo("无", null, null);
public class Opt_CreatePreset : ExecuteMenu else
{ SetBaseInfo(Datacontext.Name, $"参数数量:{Datacontext.Paramerters.Count}", null);
private Filter m_filter; }
public Opt_CreatePreset(Filter filter) : base("创建滤镜预设", Resources.LoadAll<Sprite>("Icons/XMB-Icons/misc")[0]) public void SetDependencyProperty(object data)
{ {
m_filter = filter; SetSelectState(data is ThirdMenuRoot && ((ThirdMenuRoot)data).SelectIndex == Index);
}
if (m_select)
public override void OnFocus() {
{ App.filter.EnableFilterPreview();
m_filter.ResetPreset(); if (App.filter != null)
App.filter.EnableFilter(m_filter); App.filter.EnableFilter(Datacontext);
} else
App.filter.ShutDownFilter();
public override void OnExcute(OptionUI optionUI, ref bool cancelHide) }
{ }
cancelHide = true;
public void Release() { }
OverlayManager.Input((presetName) =>
{ public override bool OnEnterItem()
var result = m_filter.CreatePreset(presetName, out var newPreset); {
if (!result) OverlayManager.PopTip(result); if (Datacontext != null && Datacontext.Paramerters.Count > 0)
else optionUI.AddOptionMenuWhenPoping(new Opt_Presets(m_filter, newPreset)); {
}, "为预设设置一个名称", string.Empty); var opts = new List<OptionMenu>();
} opts.Add(new Opt_CreatePreset(Datacontext));
} opts.AddRange(Datacontext.Presets.Select(p => new Opt_Presets(Datacontext, p)));
public class Opt_Presets : ExpandMenu
{ OverlayManager.PopSideBar(opts, onClose: () =>
private Filter m_filter; {
private FilterPreset m_preset; App.filter.EnableFilterPreview();
private OptionUI_MenuItem m_ui; Datacontext.ResetPreset();
private List<OptionMenu> m_menu; App.filter.EnableFilter(Datacontext);
});
public Opt_Presets(Filter filter, FilterPreset preset) : base(preset.Name, null) }
{ return false;
m_filter = filter; }
m_preset = preset;
m_menu = new List<OptionMenu>(); public class Opt_CreatePreset : ExecuteMenu
m_menu.Add(new Opt_Delete(m_filter, m_preset)); {
foreach (var p in m_filter.Paramerters) private Filter m_filter;
{
m_menu.Add(new Opt_ParamEditor(m_filter, p, m_preset)); public Opt_CreatePreset(Filter filter) : base("创建滤镜预设", Resources.LoadAll<Sprite>("Icons/XMB-Icons/misc")[0])
} {
} m_filter = filter;
}
public override void OnShow(OptionUI_MenuItem ui)
{ public override void OnFocus()
EventInvoker.OnFilterPresetRemoved += EventInvoker_OnFilterPresetRemoved; {
m_ui = ui; m_filter.ResetPreset();
base.OnShow(ui); App.filter.EnableFilter(m_filter);
} }
public override void OnHide() public override void OnExcute(OptionUI optionUI, ref bool cancelHide)
{ {
EventInvoker.OnFilterPresetRemoved -= EventInvoker_OnFilterPresetRemoved; cancelHide = true;
}
OverlayManager.Input((presetName) =>
private void EventInvoker_OnFilterPresetRemoved(Filter filter, FilterPreset removedPreset) {
{ FilterPreset newPreset;
if (filter != m_filter || m_preset != removedPreset) return; var result = m_filter.CreatePreset(presetName, out newPreset);
m_ui.OptionUI.RemoveItem(m_ui); if (!result) OverlayManager.PopTip(result);
} else optionUI.AddOptionMenuWhenPoping(new Opt_Presets(m_filter, newPreset));
}, "为预设设置一个名称", string.Empty);
public override void OnFocus() }
{ }
m_filter.ApplyPreset(m_preset); public class Opt_Presets : ExpandMenu
App.filter.EnableFilter(m_filter); {
} private Filter m_filter;
private FilterPreset m_preset;
protected override List<OptionMenu> GetOptionMenus() private OptionUI_MenuItem m_ui;
{ private List<OptionMenu> m_menu;
return m_menu;
} public Opt_Presets(Filter filter, FilterPreset preset) : base(preset.Name, null)
{
public class Opt_ParamEditor : ValueSetMenu m_filter = filter;
{ m_preset = preset;
private Filter m_filter;
private FilterEffect.EditableParamerter m_param; m_menu = new List<OptionMenu>();
private FilterPreset m_preset; m_menu.Add(new Opt_Delete(m_filter, m_preset));
foreach (var p in m_filter.Paramerters)
public override bool Visible => m_param.ValueType.IsEnum || m_param.ValueType == typeof(float); {
m_menu.Add(new Opt_ParamEditor(m_filter, p, m_preset));
public Opt_ParamEditor(Filter filter, FilterEffect.EditableParamerter editParam, FilterPreset preset) }
: base(editParam.Name) }
{
m_filter = filter; public override void OnShow(OptionUI_MenuItem ui)
m_param = editParam; {
m_preset = preset; EventInvoker.OnFilterPresetRemoved += EventInvoker_OnFilterPresetRemoved;
} m_ui = ui;
base.OnShow(ui);
public override Type ValueType => m_param.ValueType; }
public override object ValueRaw => m_preset.GetParamValue(m_param.Name, ValueType) ?? m_param.Value; public override void OnHide()
{
public override void OnValueChanged(object newValue) EventInvoker.OnFilterPresetRemoved -= EventInvoker_OnFilterPresetRemoved;
{ }
m_preset.SetParamValue(m_param.Name, ValueType, newValue);
m_filter.SavePresets(); private void EventInvoker_OnFilterPresetRemoved(Filter filter, FilterPreset removedPreset)
m_param.Apply(newValue); {
} if (filter != m_filter || m_preset != removedPreset) return;
m_ui.OptionUI.RemoveItem(m_ui);
public override object Min => m_param.MinValue; }
public override object Max => m_param.MaxValue; public override void OnFocus()
} {
m_filter.ApplyPreset(m_preset);
public class Opt_Delete : ExecuteMenu App.filter.EnableFilter(m_filter);
{ }
private Filter m_filter;
private FilterPreset m_preset; protected override List<OptionMenu> GetOptionMenus()
{
public Opt_Delete(Filter filter, FilterPreset preset) : base("删除预设", null) return m_menu;
{ }
m_filter = filter;
m_preset = preset; public class Opt_ParamEditor : ValueSetMenu
} {
private Filter m_filter;
public override void OnExcute(OptionUI optionUI, ref bool cancelHide) private FilterEffect.EditableParamerter m_param;
{ private FilterPreset m_preset;
m_filter.RemovePreset(m_preset);
} public override bool Visible => m_param.ValueType.IsEnum || m_param.ValueType == typeof(float);
}
public Opt_ParamEditor(Filter filter, FilterEffect.EditableParamerter editParam, FilterPreset preset)
: base(editParam.Name)
} {
} m_filter = filter;
m_param = editParam;
m_preset = preset;
}
public override Type ValueType => m_param.ValueType;
public override object ValueRaw => m_preset.GetParamValue(m_param.Name, ValueType) ?? m_param.Value;
public override void OnValueChanged(object newValue)
{
m_preset.SetParamValue(m_param.Name, ValueType, newValue);
m_filter.SavePresets();
m_param.Apply(newValue);
}
public override object Min => m_param.MinValue;
public override object Max => m_param.MaxValue;
}
public class Opt_Delete : ExecuteMenu
{
private Filter m_filter;
private FilterPreset m_preset;
public Opt_Delete(Filter filter, FilterPreset preset) : base("删除预设", null)
{
m_filter = filter;
m_preset = preset;
}
public override void OnExcute(OptionUI optionUI, ref bool cancelHide)
{
m_filter.RemovePreset(m_preset);
}
}
}
}
} }

View File

@ -37,12 +37,12 @@ namespace AxibugEmuOnline.Client
m_romlib.BeginFetchRomInfo(m_romfile); m_romlib.BeginFetchRomInfo(m_romfile);
} }
SetSelectState(data is ThirdMenuRoot tr && tr.SelectIndex == Index); SetSelectState(data is ThirdMenuRoot && ((ThirdMenuRoot)data).SelectIndex == Index);
} }
public void SetDependencyProperty(object data) public void SetDependencyProperty(object data)
{ {
SetSelectState(data is ThirdMenuRoot tr && tr.SelectIndex == Index); SetSelectState(data is ThirdMenuRoot && ((ThirdMenuRoot)data).SelectIndex == Index);
} }
public void Release() public void Release()

View File

@ -11,7 +11,7 @@ namespace AxibugEmuOnline.Client
private object m_state; private object m_state;
private StepPerformer m_stepPerformer; private StepPerformer m_stepPerformer;
private readonly List<OptionMenu> menus = new(); private readonly List<OptionMenu> menus = new List<OptionMenu>();
public static InGameUI Instance { get; private set; } public static InGameUI Instance { get; private set; }
public RomFile RomFile { get; private set; } public RomFile RomFile { get; private set; }

View File

@ -1,14 +1,11 @@
using AxibugEmuOnline.Client.ClientCore; using AxibugEmuOnline.Client.ClientCore;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using UnityEditor.Presets;
using UnityEngine;
using VirtualNes.Core;
using static AxibugEmuOnline.Client.FilterManager; using static AxibugEmuOnline.Client.FilterManager;
namespace AxibugEmuOnline.Client namespace AxibugEmuOnline.Client
{ {
public class InGameUI_FilterSetting : ExpandMenu public class InGameUI_FilterSetting : ExpandMenu
{ {
private InGameUI m_gameUI; private InGameUI m_gameUI;

View File

@ -39,8 +39,10 @@ public static class GameObjectPool
public static void Release(GameObject instance) public static void Release(GameObject instance)
{ {
s_instanceToSrc.TryGetValue(instance, out var src); GameObject src;
if (src != null && s_poolMap.TryGetValue(src, out var pool)) Queue<GameObject> pool;
s_instanceToSrc.TryGetValue(instance, out src);
if (src != null && s_poolMap.TryGetValue(src, out pool))
{ {
pool.Enqueue(instance); pool.Enqueue(instance);
//instance.SetActive(false); //instance.SetActive(false);

View File

@ -480,9 +480,10 @@ public class ItemPresent : GridLayoutGroup, IVirtualLayout
if (_dataList != null) if (_dataList != null)
_dataList.Clear(); _dataList.Clear();
} }
else if (dataList is IEnumerable ienumrable) else if (dataList is IEnumerable)
{ {
List<object> temp = new List<object>(); var ienumrable = (IEnumerable)dataList;
List<object> temp = new List<object>();
foreach (var item in ienumrable) foreach (var item in ienumrable)
{ {
temp.Add(item); temp.Add(item);

View File

@ -6,240 +6,245 @@ using UnityEngine.UI;
public interface IVirtualLayout public interface IVirtualLayout
{ {
Dictionary<GameObject, ScripteInterface> CacheItemScripts { get; } Dictionary<GameObject, ScripteInterface> CacheItemScripts { get; }
public List<object> DataList { get; } List<object> DataList { get; }
public object DependencyProperty { get; } object DependencyProperty { get; }
public RectTransform RectTransform { get; } RectTransform RectTransform { get; }
public RectTransform GetTemplate(object data); RectTransform GetTemplate(object data);
public Vector2 GetItemAnchorePos(int index); Vector2 GetItemAnchorePos(int index);
public RectTransform GetItemUIIfExist(int index); RectTransform GetItemUIIfExist(int index);
public void UpdateProxyVisualState(); void UpdateProxyVisualState();
public void UpdateDependencyProperty(object dp); void UpdateDependencyProperty(object dp);
public void SetData(object dataList); void SetData(object dataList);
public void MoveToScrollViewCenter(ScrollRect scrollRect, int dataIndex); void MoveToScrollViewCenter(ScrollRect scrollRect, int dataIndex);
} }
public class ItemProxy public class ItemProxy
{ {
public bool IsDestroyed; public bool IsDestroyed;
public bool Visible = true; public bool Visible = true;
public int Index; public int Index;
public bool IsInViewRect; public bool IsInViewRect;
public Vector2 Pivot => _template.pivot; public Vector2 Pivot => _template.pivot;
public Vector2 AnchoredPosition; public Vector2 AnchoredPosition;
public float Width; public float Width;
public float Height; public float Height;
private IVirtualLayout _parent; private IVirtualLayout _parent;
private RectTransform _template => _parent.GetTemplate(_parent.DataList[Index]); private RectTransform _template => _parent.GetTemplate(_parent.DataList[Index]);
private RectTransform _runtimeInstance; private RectTransform _runtimeInstance;
private LayoutGroup _layoutElement; private LayoutGroup _layoutElement;
public RectTransform RuntimeItemUI => _runtimeInstance; public RectTransform RuntimeItemUI => _runtimeInstance;
public bool firstShow { get; private set; } = true; public bool firstShow { get; private set; } = true;
public float PreferredWidth public float PreferredWidth
{ {
get get
{ {
if (_layoutElement == null) return 0; if (_layoutElement == null) return 0;
return _layoutElement.preferredWidth; return _layoutElement.preferredWidth;
} }
} }
public float PreferredHeight public float PreferredHeight
{ {
get get
{ {
if (_layoutElement == null) return 0; if (_layoutElement == null) return 0;
return _layoutElement.preferredHeight; return _layoutElement.preferredHeight;
} }
} }
public ScripteInterface GetLuaObj() public ScripteInterface GetLuaObj()
{ {
if (_runtimeInstance == null) return null; if (_runtimeInstance == null) return null;
_parent.CacheItemScripts.TryGetValue(_runtimeInstance.gameObject, out ScripteInterface lfi); ScripteInterface lfi;
return lfi; _parent.CacheItemScripts.TryGetValue(_runtimeInstance.gameObject, out lfi);
}
public ItemProxy(IVirtualLayout parent) return lfi;
{ }
_parent = parent;
}
public void Dispose() public ItemProxy(IVirtualLayout parent)
{ {
if (_runtimeInstance != null) _parent = parent;
{ }
if (Application.isPlaying)
{
GameObjectPool.Release(_runtimeInstance.gameObject);
}
else
GameObject.DestroyImmediate(_runtimeInstance.gameObject);
}
}
public bool NeedShow public void Dispose()
{ {
get if (_runtimeInstance != null)
{ {
if (IsInViewRect && _runtimeInstance == null) return true; if (Application.isPlaying)
else {
{ GameObjectPool.Release(_runtimeInstance.gameObject);
if (_runtimeInstance != null && IsInViewRect && _runtimeInstance.anchoredPosition != AnchoredPosition) }
return true; else
else GameObject.DestroyImmediate(_runtimeInstance.gameObject);
return false; }
} }
}
} public bool NeedShow
public bool NeedHide => !IsInViewRect && _runtimeInstance != null; {
get
{
if (IsInViewRect && _runtimeInstance == null) return true;
else
{
if (_runtimeInstance != null && IsInViewRect && _runtimeInstance.anchoredPosition != AnchoredPosition)
return true;
else
return false;
}
}
public void UpdateView(bool force = false) }
{ public bool NeedHide => !IsInViewRect && _runtimeInstance != null;
if (IsInViewRect)
{
if (_runtimeInstance == null)
{
_runtimeInstance = GetInstance();
_layoutElement = _runtimeInstance.GetComponent<LayoutGroup>();
UpdateViewData();
}
else if (force)
{
UpdateViewData();
}
UpdateLayout(); public void UpdateView(bool force = false)
} {
else if (IsInViewRect)
{ {
ReleaseInstance(); if (_runtimeInstance == null)
} {
} _runtimeInstance = GetInstance();
_layoutElement = _runtimeInstance.GetComponent<LayoutGroup>();
UpdateViewData();
}
else if (force)
{
UpdateViewData();
}
public void UpdateLayout() UpdateLayout();
{ }
if (_runtimeInstance != null) else
{ {
_runtimeInstance.gameObject.SetActive(true); ReleaseInstance();
_runtimeInstance.anchorMax = Vector2.up; }
_runtimeInstance.anchorMin = Vector2.up; }
_runtimeInstance.anchoredPosition = AnchoredPosition;
_runtimeInstance.sizeDelta = new Vector2(Width, Height);
}
if (_layoutElement != null)
{
_layoutElement.CalculateLayoutInputHorizontal();
_layoutElement.CalculateLayoutInputVertical();
_layoutElement.SetLayoutHorizontal();
_layoutElement.SetLayoutVertical();
}
} public void UpdateLayout()
{
if (_runtimeInstance != null)
{
_runtimeInstance.gameObject.SetActive(true);
_runtimeInstance.anchorMax = Vector2.up;
_runtimeInstance.anchorMin = Vector2.up;
_runtimeInstance.anchoredPosition = AnchoredPosition;
_runtimeInstance.sizeDelta = new Vector2(Width, Height);
}
if (_layoutElement != null)
{
_layoutElement.CalculateLayoutInputHorizontal();
_layoutElement.CalculateLayoutInputVertical();
_layoutElement.SetLayoutHorizontal();
_layoutElement.SetLayoutVertical();
}
private void UpdateViewData() }
{
if (Application.isPlaying)
{
if (!_parent.CacheItemScripts.ContainsKey(_runtimeInstance.gameObject))
{
var vItem = _runtimeInstance.gameObject.GetComponent<IVirtualItem>();
ScripteInterface newSI = new ScripteInterface(vItem);
_parent.CacheItemScripts[_runtimeInstance.gameObject] = newSI;
}
_parent.CacheItemScripts.TryGetValue(_runtimeInstance.gameObject, out ScripteInterface si); private void UpdateViewData()
si.SetDataList(_parent.DataList[Index], Index); {
if (_parent.DependencyProperty != null) if (Application.isPlaying)
si.SetDependencyProperty(_parent.DependencyProperty); {
} if (!_parent.CacheItemScripts.ContainsKey(_runtimeInstance.gameObject))
} {
var vItem = _runtimeInstance.gameObject.GetComponent<IVirtualItem>();
ScripteInterface newSI = new ScripteInterface(vItem);
_parent.CacheItemScripts[_runtimeInstance.gameObject] = newSI;
}
public void UpdateDP() ScripteInterface si;
{
if (_runtimeInstance == null) return;
_parent.CacheItemScripts.TryGetValue(_runtimeInstance.gameObject, out ScripteInterface luaInterface); _parent.CacheItemScripts.TryGetValue(_runtimeInstance.gameObject, out si);
if (luaInterface == null) return; si.SetDataList(_parent.DataList[Index], Index);
if (_parent.DependencyProperty != null)
si.SetDependencyProperty(_parent.DependencyProperty);
}
}
if (_parent.DependencyProperty != null) public void UpdateDP()
luaInterface.SetDependencyProperty(_parent.DependencyProperty); {
} if (_runtimeInstance == null) return;
ScripteInterface luaInterface;
_parent.CacheItemScripts.TryGetValue(_runtimeInstance.gameObject, out luaInterface);
if (luaInterface == null) return;
private RectTransform GetInstance() if (_parent.DependencyProperty != null)
{ luaInterface.SetDependencyProperty(_parent.DependencyProperty);
var res = GameObjectPool.GetInstance(_template.gameObject, _parent.RectTransform).GetComponent<RectTransform>(); }
return res;
}
private void ReleaseInstance() private RectTransform GetInstance()
{ {
if (_runtimeInstance == null) return; var res = GameObjectPool.GetInstance(_template.gameObject, _parent.RectTransform).GetComponent<RectTransform>();
return res;
}
_layoutElement = null; private void ReleaseInstance()
{
if (_runtimeInstance == null) return;
if (Application.isPlaying) _layoutElement = null;
{
_parent.CacheItemScripts.TryGetValue(_runtimeInstance.gameObject, out ScripteInterface si); if (Application.isPlaying)
if (si != null) si.Release(); {
GameObjectPool.Release(_runtimeInstance.gameObject); ScripteInterface si;
_runtimeInstance = null; _parent.CacheItemScripts.TryGetValue(_runtimeInstance.gameObject, out si);
} if (si != null) si.Release();
else GameObjectPool.Release(_runtimeInstance.gameObject);
{ _runtimeInstance = null;
GameObject.DestroyImmediate(_runtimeInstance.gameObject); }
_runtimeInstance = null; else
} {
} GameObject.DestroyImmediate(_runtimeInstance.gameObject);
_runtimeInstance = null;
}
}
} }
public class ScripteInterface public class ScripteInterface
{ {
private IVirtualItem _itemInstance; private IVirtualItem _itemInstance;
public IVirtualItem ItemInstance => _itemInstance; public IVirtualItem ItemInstance => _itemInstance;
public ScripteInterface(IVirtualItem lc) public ScripteInterface(IVirtualItem lc)
{ {
_itemInstance = lc; _itemInstance = lc;
} }
public void SetDataList(object dataItem, int index) public void SetDataList(object dataItem, int index)
{ {
if (_itemInstance == null) return; if (_itemInstance == null) return;
_itemInstance.Index = index; _itemInstance.Index = index;
_itemInstance.SetData(dataItem); _itemInstance.SetData(dataItem);
} }
public void Release() public void Release()
{ {
if (_itemInstance == null) return; if (_itemInstance == null) return;
_itemInstance.Release(); _itemInstance.Release();
} }
public void SetDependencyProperty(object dependencyProperty) public void SetDependencyProperty(object dependencyProperty)
{ {
if (_itemInstance == null) return; if (_itemInstance == null) return;
_itemInstance.SetDependencyProperty(dependencyProperty); _itemInstance.SetDependencyProperty(dependencyProperty);
} }
} }
public interface IVirtualItem public interface IVirtualItem
{ {
GameObject gameObject { get; } GameObject gameObject { get; }
int Index { get; set; } int Index { get; set; }
void SetData(object data); void SetData(object data);
void SetDependencyProperty(object data); void SetDependencyProperty(object data);
void Release(); void Release();
} }

View File

@ -269,16 +269,18 @@ namespace AxibugEmuOnline.Client
private void CreateRuntimeMenuItem(OptionMenu menuData) private void CreateRuntimeMenuItem(OptionMenu menuData)
{ {
if (menuData is ExecuteMenu executeMenu) if (menuData is ExecuteMenu)
{ {
var menuUI = Instantiate(TEMPLATE_EXECUTEITEM.gameObject, TEMPLATE_EXECUTEITEM.transform.parent).GetComponent<OptionUI_ExecuteItem>(); ExecuteMenu executeMenu = (ExecuteMenu)menuData;
var menuUI = Instantiate(TEMPLATE_EXECUTEITEM.gameObject, TEMPLATE_EXECUTEITEM.transform.parent).GetComponent<OptionUI_ExecuteItem>();
menuUI.gameObject.SetActive(true); menuUI.gameObject.SetActive(true);
menuUI.SetData(this, executeMenu); menuUI.SetData(this, executeMenu);
m_runtimeMenuItems.Add(menuUI); m_runtimeMenuItems.Add(menuUI);
} }
else if (menuData is ValueSetMenu valueSetMenu) else if (menuData is ValueSetMenu)
{ {
var menuUI = Instantiate(TEMPLATE_VALUEEDITITEM.gameObject, TEMPLATE_VALUEEDITITEM.transform.parent).GetComponent<OptionUI_ValueEditItem>(); var valueSetMenu = (ValueSetMenu)menuData;
var menuUI = Instantiate(TEMPLATE_VALUEEDITITEM.gameObject, TEMPLATE_VALUEEDITITEM.transform.parent).GetComponent<OptionUI_ValueEditItem>();
menuUI.gameObject.SetActive(true); menuUI.gameObject.SetActive(true);
menuUI.SetData(this, valueSetMenu); menuUI.SetData(this, valueSetMenu);
m_runtimeMenuItems.Add(menuUI); m_runtimeMenuItems.Add(menuUI);

View File

@ -17,9 +17,10 @@ namespace AxibugEmuOnline.Client
com_floatEdit.gameObject.SetActive(false); com_floatEdit.gameObject.SetActive(false);
com_enumEdit.gameObject.SetActive(false); com_enumEdit.gameObject.SetActive(false);
if (menuData is ValueSetMenu valueMenu) if (menuData is ValueSetMenu)
{ {
if (valueMenu.ValueType == typeof(float)) var valueMenu = (ValueSetMenu)menuData;
if (valueMenu.ValueType == typeof(float))
{ {
m_currentCom = com_floatEdit; m_currentCom = com_floatEdit;
} }

View File

@ -18,11 +18,11 @@ namespace AxibugEmuOnline.Client
protected override void OnShow(object param) protected override void OnShow(object param)
{ {
(Action<string> callback, string placeHolder, string defaultText) t = ((Action<string> callback, string placeHolder, string defaultText))param; ValueTuple<Action<string>, string, string> t = (ValueTuple<Action<string>, string, string>)param;
OnCommit = t.callback; OnCommit = t.Item1;
(m_input.placeholder as Text).text = t.placeHolder; (m_input.placeholder as Text).text = t.Item2;
m_input.text = t.defaultText; m_input.text = t.Item3;
} }
protected override void Update() protected override void Update()

View File

@ -22,7 +22,7 @@ namespace AxibugEmuOnline.Client
public static InputUI Input(Action<string> callback, string placeHolder, string defaultText) public static InputUI Input(Action<string> callback, string placeHolder, string defaultText)
{ {
s_ins.m_InputUI.Show((callback, placeHolder, defaultText)); s_ins.m_InputUI.Show(new ValueTuple<Action<string>, string, string>(callback, placeHolder, defaultText));
return s_ins.m_InputUI; return s_ins.m_InputUI;
} }

View File

@ -9,132 +9,136 @@ using Debug = System.Diagnostics.Debug;
namespace AxibugEmuOnline.Client namespace AxibugEmuOnline.Client
{ {
public class RoomItem : MenuItem, IVirtualItem public class RoomItem : MenuItem, IVirtualItem
{ {
[SerializeField] Image m_roomPreview; [SerializeField] Image m_roomPreview;
[SerializeField] Slider m_downloadProgress; [SerializeField] Slider m_downloadProgress;
[SerializeField] GameObject m_downloadingFlag; [SerializeField] GameObject m_downloadingFlag;
[SerializeField] GameObject m_romReadyFlag; [SerializeField] GameObject m_romReadyFlag;
private RomFile m_romFile; private RomFile m_romFile;
public int Index { get; set; } public int Index { get; set; }
public int RoomID { get; private set; } public int RoomID { get; private set; }
protected override void Awake() protected override void Awake()
{ {
base.Awake(); base.Awake();
Eventer.Instance.RegisterEvent<int>(EEvent.OnRoomListSingleUpdate, OnRoomSignelUpdate); Eventer.Instance.RegisterEvent<int>(EEvent.OnRoomListSingleUpdate, OnRoomSignelUpdate);
} }
private void OnRoomSignelUpdate(int roomID) private void OnRoomSignelUpdate(int roomID)
{ {
if (this.RoomID != roomID) return; if (this.RoomID != roomID) return;
if (App.roomMgr.GetRoomListMiniInfo(roomID, out var roomInfo)) Protobuf_Room_MiniInfo roomInfo;
UpdateUI(roomInfo); if (App.roomMgr.GetRoomListMiniInfo(roomID, out roomInfo))
} UpdateUI(roomInfo);
}
public void SetData(object data) public void SetData(object data)
{ {
Debug.Assert(data is Protobuf_Room_MiniInfo); Debug.Assert(data is Protobuf_Room_MiniInfo);
var roomInfo = (Protobuf_Room_MiniInfo)data; var roomInfo = (Protobuf_Room_MiniInfo)data;
RoomID = roomInfo.RoomID; RoomID = roomInfo.RoomID;
UpdateUI(roomInfo); UpdateUI(roomInfo);
} }
public override bool OnEnterItem() public override bool OnEnterItem()
{ {
if (m_romFile == null) return false; if (m_romFile == null) return false;
if (!m_romFile.RomReady) if (!m_romFile.RomReady)
{ {
m_romFile.BeginDownload(); m_romFile.BeginDownload();
return false; return false;
} }
else else
{ {
if (!App.roomMgr.GetRoomListMiniInfo(RoomID, out Protobuf_Room_MiniInfo MiniInfo)) Protobuf_Room_MiniInfo MiniInfo;
{ if (!App.roomMgr.GetRoomListMiniInfo(RoomID, out MiniInfo))
OverlayManager.PopTip("房间不存在"); {
return false; OverlayManager.PopTip("房间不存在");
} return false;
}
int[] freeSlots;
if (!MiniInfo.GetFreeSlot(out freeSlots))
{
OverlayManager.PopTip("无空闲位置");
return false;
}
if (!MiniInfo.GetFreeSlot(out var freeSlots)) App.roomMgr.SendJoinRoom(RoomID);
{ return true;
OverlayManager.PopTip("无空闲位置"); }
return false; }
}
App.roomMgr.SendJoinRoom(RoomID); private void UpdateUI(Protobuf_Room_MiniInfo roomInfo)
return true; {
} var hostNick = roomInfo.GetHostNickName();
} int cur; int max;
private void UpdateUI(Protobuf_Room_MiniInfo roomInfo) roomInfo.GetRoomPlayers(out cur, out max);
{ SetBaseInfo("--", $"<b>{hostNick}</b>的房间", $"{cur}/{max}");
var hostNick = roomInfo.GetHostNickName(); SetIcon(null);
roomInfo.GetRoomPlayers(out var cur, out var max);
SetBaseInfo("--", $"<b>{hostNick}</b>的房间", $"{cur}/{max}");
SetIcon(null);
roomInfo.FetchRomFileInRoomInfo(EnumPlatform.NES, (room, romFile) => roomInfo.FetchRomFileInRoomInfo(EnumPlatform.NES, (room, romFile) =>
{ {
if (room.RoomID != RoomID) return; if (room.RoomID != RoomID) return;
m_romFile = romFile; m_romFile = romFile;
Txt.text = romFile.Alias; Txt.text = romFile.Alias;
UpdateRomInfoView(); UpdateRomInfoView();
App.CacheMgr.GetSpriteCache(romFile.ImageURL, OnGetRomImage); App.CacheMgr.GetSpriteCache(romFile.ImageURL, OnGetRomImage);
}); });
} }
protected override void Update() protected override void Update()
{ {
UpdateRomInfoView(); UpdateRomInfoView();
base.Update(); base.Update();
} }
private void UpdateRomInfoView() private void UpdateRomInfoView()
{ {
float? downloadingProgress = null; float? downloadingProgress = null;
bool romReady = false; bool romReady = false;
if (m_romFile != null) if (m_romFile != null)
{ {
if (m_romFile.IsDownloading) if (m_romFile.IsDownloading)
downloadingProgress = m_romFile.Progress; downloadingProgress = m_romFile.Progress;
if (m_romFile.RomReady) if (m_romFile.RomReady)
romReady = true; romReady = true;
} }
m_downloadingFlag.SetActiveEx(downloadingProgress.HasValue); m_downloadingFlag.SetActiveEx(downloadingProgress.HasValue);
if (downloadingProgress.HasValue) if (downloadingProgress.HasValue)
m_downloadProgress.value = downloadingProgress.Value; m_downloadProgress.value = downloadingProgress.Value;
m_romReadyFlag.SetActiveEx(romReady); m_romReadyFlag.SetActiveEx(romReady);
} }
private void OnGetRomImage(Sprite sprite, string url) private void OnGetRomImage(Sprite sprite, string url)
{ {
if (m_romFile == null) return; if (m_romFile == null) return;
if (m_romFile.ImageURL != url) return; if (m_romFile.ImageURL != url) return;
SetIcon(sprite); SetIcon(sprite);
} }
public void SetDependencyProperty(object data) public void SetDependencyProperty(object data)
{ {
SetSelectState(data is ThirdMenuRoot tr && tr.SelectIndex == Index); SetSelectState((data is ThirdMenuRoot && ((ThirdMenuRoot)data).SelectIndex == Index));
} }
public void Release() public void Release()
{ {
Reset(); Reset();
} }
} }
} }

View File

@ -44,7 +44,7 @@ namespace AxibugEmuOnline.Client
m_trackTween.Kill(); m_trackTween.Kill();
m_trackTween = null; m_trackTween = null;
} }
m_trackTween = DOTween.To(() => m_rect.position, (value) => m_rect.position = value, itemUIRect.position, 0.125f); m_trackTween = DOTween.To(() => m_rect.position, (_value) => m_rect.position = _value, itemUIRect.position, 0.125f);
m_trackTween.onComplete = () => m_trackTween = null; m_trackTween.onComplete = () => m_trackTween = null;
} }
} }

View File

@ -184,6 +184,10 @@ namespace AxibugEmuOnline.Client
private MenuItem Clone(MenuItem template, Transform parent) private MenuItem Clone(MenuItem template, Transform parent)
{ {
#if UNITY_EDITOR #if UNITY_EDITOR
//========================套娃宏========================
#if UNITY_2019_1_OR_NEWER //新版Unity因UNITY2018.2用不了这玩意儿,编辑器也罢
if (Application.isPlaying) if (Application.isPlaying)
{ {
var item = GameObject.Instantiate(template.gameObject, parent).GetComponent<MenuItem>(); var item = GameObject.Instantiate(template.gameObject, parent).GetComponent<MenuItem>();
@ -197,8 +201,17 @@ namespace AxibugEmuOnline.Client
return clone.GetComponent<MenuItem>(); return clone.GetComponent<MenuItem>();
} }
#else #else
return GameObject.Instantiate(SubMenuItemTemplate.gameObject, parent).GetComponent<MenuItem>(); var item = GameObject.Instantiate(template.gameObject, parent).GetComponent<MenuItem>();
item.transform.localPosition = Vector3.zero;
return item;
#endif #endif
} //========================套娃宏 End========================
}
#else
return GameObject.Instantiate(SubMenuItemTemplate.gameObject, parent).GetComponent<MenuItem>();
#endif
}
}
} }

View File

@ -9,7 +9,8 @@ namespace AxibugEmuOnline.Client
private static Dictionary<Graphic, Material> _caches = new Dictionary<Graphic, Material>(); private static Dictionary<Graphic, Material> _caches = new Dictionary<Graphic, Material>();
public static Material GetMaterial(this Graphic graphic) public static Material GetMaterial(this Graphic graphic)
{ {
if (_caches.TryGetValue(graphic, out var material)) Material material;
if (_caches.TryGetValue(graphic, out material))
{ {
return material; return material;
} }

View File

@ -34,7 +34,10 @@ public class XMBInfoBar : MonoBehaviour
RefreshFps(); RefreshFps();
} }
(uint lastFrame, float lastTime) m_lastFrameInfo; /// <summary>
/// (uint lastFrame, float lastTime)
/// </summary>
ValueTuple<uint,float> m_lastFrameInfo;
private void RefreshFps() private void RefreshFps()
{ {
if (App.emu.Core.IsNull()) if (App.emu.Core.IsNull())
@ -42,14 +45,18 @@ public class XMBInfoBar : MonoBehaviour
else else
{ {
FPS.gameObject.SetActiveEx(true); FPS.gameObject.SetActiveEx(true);
var gap = App.emu.Core.Frame - m_lastFrameInfo.lastFrame; //var gap = App.emu.Core.Frame - m_lastFrameInfo.lastFrame;
var time = Time.realtimeSinceStartup - m_lastFrameInfo.lastTime; //var time = Time.realtimeSinceStartup - m_lastFrameInfo.lastTime;
var fps = gap / time; var gap = App.emu.Core.Frame - m_lastFrameInfo.Item1;
var time = Time.realtimeSinceStartup - m_lastFrameInfo.Item2;
var fps = gap / time;
FPS.text = $"FPS:{fps:.#}"; FPS.text = $"FPS:{fps:.#}";
m_lastFrameInfo.lastFrame = App.emu.Core.Frame; //m_lastFrameInfo.lastFrame = App.emu.Core.Frame;
m_lastFrameInfo.lastTime = Time.realtimeSinceStartup; //m_lastFrameInfo.lastTime = Time.realtimeSinceStartup;
} m_lastFrameInfo.Item1 = App.emu.Core.Frame;
m_lastFrameInfo.Item2 = Time.realtimeSinceStartup;
}
} }
private void RefreshDelay() private void RefreshDelay()

View File

@ -36,7 +36,9 @@ namespace AxibugEmuOnline.Client
private static Dictionary<int, RomFile> s_RomFileCahcesInRoomInfo = new Dictionary<int, RomFile>(); private static Dictionary<int, RomFile> s_RomFileCahcesInRoomInfo = new Dictionary<int, RomFile>();
public static void FetchRomFileInRoomInfo(this Protobuf_Room_MiniInfo roomInfo, EnumPlatform platform, Action<Protobuf_Room_MiniInfo, RomFile> callback) public static void FetchRomFileInRoomInfo(this Protobuf_Room_MiniInfo roomInfo, EnumPlatform platform, Action<Protobuf_Room_MiniInfo, RomFile> callback)
{ {
if (s_RomFileCahcesInRoomInfo.TryGetValue(roomInfo.GameRomID, out RomFile romFile)) RomFile romFile;
if (s_RomFileCahcesInRoomInfo.TryGetValue(roomInfo.GameRomID, out romFile))
{ {
callback.Invoke(roomInfo, romFile); callback.Invoke(roomInfo, romFile);
return; return;
@ -46,11 +48,11 @@ namespace AxibugEmuOnline.Client
case EnumPlatform.NES: case EnumPlatform.NES:
App.StartCoroutine(App.httpAPI.GetNesRomInfo(roomInfo.GameRomID, (romWebData) => App.StartCoroutine(App.httpAPI.GetNesRomInfo(roomInfo.GameRomID, (romWebData) =>
{ {
RomFile romFile = new RomFile(EnumPlatform.NES, 0, 0); RomFile _romFile = new RomFile(EnumPlatform.NES, 0, 0);
romFile.SetWebData(romWebData); _romFile.SetWebData(romWebData);
s_RomFileCahcesInRoomInfo[roomInfo.GameRomID] = romFile; s_RomFileCahcesInRoomInfo[roomInfo.GameRomID] = _romFile;
callback.Invoke(roomInfo, romFile); callback.Invoke(roomInfo, _romFile);
})); }));
break; break;
} }