Compare commits

..

No commits in common. "e5e7beb52c3860a2cf932ee3d74e72290ec08b84" and "3e919523301fedf54df747ed853351e457eafd98" have entirely different histories.

44 changed files with 972 additions and 1118 deletions

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
@ -249,7 +249,7 @@ namespace VirtualNes.Core
LoadDISK(); LoadDISK();
{ {
// Padクラス内だと初期化タイミングが遅いのでここで // Pad・ッ・鬣ケトレ、タ、ネウ<EFBFBD>レサッ・ソ・、・゚・<EFBFBD>ー、ャ゚W、、、ホ、ヌ、ウ、ウ、ヌ
uint crc = rom.GetPROM_CRC(); uint crc = rom.GetPROM_CRC();
if ( if (
crc == 0xe792de94 // Best Play - Pro Yakyuu (New) (J) crc == 0xe792de94 // Best Play - Pro Yakyuu (New) (J)
@ -275,7 +275,7 @@ namespace VirtualNes.Core
LoadTurboFile(); LoadTurboFile();
// VS-Unisystemのデフォルト設定 // VS-Unisystem、ホ・ヌ・ユ・ゥ・<EFBFBD>ネヤOカィ
if (rom.IsVSUNISYSTEM()) if (rom.IsVSUNISYSTEM())
{ {
uint crc = rom.GetPROM_CRC(); uint crc = rom.GetPROM_CRC();
@ -286,13 +286,13 @@ namespace VirtualNes.Core
Reset(); Reset();
// ゲーム固有のデフォルトオプションを設定(設定戻す時に使う為) // ・イゥ`・犹フモミ、ホ・ヌ・ユ・ゥ・<EFBDA9>ネ・ェ・ラ・キ・逾<EFBDA5><E980BE>Oカィ(ヤOカィ諾、ケ瓶、ヒハケ、ヲ樣)
GameOption.defRenderMethod = (int)GetRenderMethod(); GameOption.defRenderMethod = (int)GetRenderMethod();
GameOption.defIRQtype = GetIrqType(); GameOption.defIRQtype = GetIrqType();
GameOption.defFrameIRQ = GetFrameIRQmode(); GameOption.defFrameIRQ = GetFrameIRQmode();
GameOption.defVideoMode = GetVideoMode(); GameOption.defVideoMode = GetVideoMode();
// 設定をロードして設定する(エントリが無ければデフォルトが入る) // ヤOカィ、<EFBFBD>愰`・ノ、キ、ニヤOカィ、ケ、<EFBDB9>(・ィ・<EFBDA8>ネ・熙ャ殪、ア、<EFBDB1>ミ・ヌ・ユ・ゥ・<EFBDA9>ネ、ャネ<EFBDAC><EFBE88>)
if (rom.GetMapperNo() != 20) if (rom.GetMapperNo() != 20)
{ {
GameOption.Load(rom.GetPROM_CRC()); GameOption.Load(rom.GetPROM_CRC());
@ -331,12 +331,12 @@ namespace VirtualNes.Core
{ {
if (fp == null) if (fp == null)
{ {
// xxx ファイルを開けません // xxx ・ユ・。・、・<EFBFBD><EFBFBD>_、ア、゙、サ、<EFBFBD>
throw new Exception($"Can Not Open File [TurboFile.vtf]"); throw new Exception($"Can Not Open File [TurboFile.vtf]");
} }
long size = fp.Length; long size = fp.Length;
// ファイルサイズ取得 // ・ユ・。・、・<EFBFBD>オ・、・コネ。オテ
if (size > 32 * 1024) if (size > 32 * 1024)
{ {
size = 32 * 1024; size = 32 * 1024;
@ -354,7 +354,7 @@ namespace VirtualNes.Core
private void LoadDISK() private void LoadDISK()
{ {
//todo : 磁碟机读取支持 //todo : エナオ忞巐チネ。ヨァウヨ
} }
private void LoadSRAM() private void LoadSRAM()
@ -400,7 +400,7 @@ namespace VirtualNes.Core
{ {
int i; int i;
// 儊儌儕僋儕傾 // メモリクリア
MemoryUtility.ZEROMEMORY(MMU.RAM, MMU.RAM.Length); MemoryUtility.ZEROMEMORY(MMU.RAM, MMU.RAM.Length);
MemoryUtility.ZEROMEMORY(MMU.WRAM, MMU.WRAM.Length); MemoryUtility.ZEROMEMORY(MMU.WRAM, MMU.WRAM.Length);
MemoryUtility.ZEROMEMORY(MMU.DRAM, MMU.DRAM.Length); MemoryUtility.ZEROMEMORY(MMU.DRAM, MMU.DRAM.Length);
@ -420,11 +420,11 @@ namespace VirtualNes.Core
MMU.PROM = MMU.VROM = null; MMU.PROM = MMU.VROM = null;
// 0 彍嶼杊巭懳嶔 // 0 除算防止対策
MMU.PROM_8K_SIZE = MMU.PROM_16K_SIZE = MMU.PROM_32K_SIZE = 1; MMU.PROM_8K_SIZE = MMU.PROM_16K_SIZE = MMU.PROM_32K_SIZE = 1;
MMU.VROM_1K_SIZE = MMU.VROM_2K_SIZE = MMU.VROM_4K_SIZE = MMU.VROM_8K_SIZE = 1; MMU.VROM_1K_SIZE = MMU.VROM_2K_SIZE = MMU.VROM_4K_SIZE = MMU.VROM_8K_SIZE = 1;
// 僨僼僅儖僩僶儞僋愝掕 // デフォルトバンク設定
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
{ {
MMU.CPU_MEM_BANK[i] = null; MMU.CPU_MEM_BANK[i] = null;
@ -432,11 +432,11 @@ namespace VirtualNes.Core
MMU.CPU_MEM_PAGE[i] = 0; MMU.CPU_MEM_PAGE[i] = 0;
} }
// 撪憻RAM/WRAM // 内臓RAM/WRAM
MMU.SetPROM_Bank(0, MMU.RAM, MMU.BANKTYPE_RAM); MMU.SetPROM_Bank(0, MMU.RAM, MMU.BANKTYPE_RAM);
MMU.SetPROM_Bank(3, MMU.WRAM, MMU.BANKTYPE_RAM); MMU.SetPROM_Bank(3, MMU.WRAM, MMU.BANKTYPE_RAM);
// 僟儈乕 // ダミー
MMU.SetPROM_Bank(1, MMU.XRAM, MMU.BANKTYPE_ROM); MMU.SetPROM_Bank(1, MMU.XRAM, MMU.BANKTYPE_ROM);
MMU.SetPROM_Bank(2, MMU.XRAM, MMU.BANKTYPE_ROM); MMU.SetPROM_Bank(2, MMU.XRAM, MMU.BANKTYPE_ROM);
@ -522,7 +522,7 @@ namespace VirtualNes.Core
} }
} }
} }
ppu.ScanlineNext(); // 偙傟偺埵抲偱儔僗僞乕宯偼夋柺偑堘偆 ppu.ScanlineNext(); // これの位置でラスター系は画面が違う
if (RenderMethod == EnumRenderMethod.PRE_ALL_RENDER) if (RenderMethod == EnumRenderMethod.PRE_ALL_RENDER)
EmulationCPU(nescfg.ScanlineCycles); EmulationCPU(nescfg.ScanlineCycles);
@ -583,7 +583,7 @@ namespace VirtualNes.Core
{ {
pad.VSync(); pad.VSync();
// VBLANK婜娫 // VBLANK期間
if (scanline == nescfg.TotalScanlines - 1) if (scanline == nescfg.TotalScanlines - 1)
{ {
ppu.VBlankEnd(); ppu.VBlankEnd();
@ -642,7 +642,7 @@ namespace VirtualNes.Core
if (scanline == 0) if (scanline == 0)
{ {
// 僟儈乕僗僉儍儞儔僀儞 // ダミースキャンライン
// H-Draw (4fetches*32) // H-Draw (4fetches*32)
EmulationCPU(FETCH_CYCLES * 128); EmulationCPU(FETCH_CYCLES * 128);
ppu.FrameStart(); ppu.FrameStart();
@ -655,7 +655,7 @@ namespace VirtualNes.Core
} }
else if (scanline < 240) else if (scanline < 240)
{ {
// 僗僋儕乕儞昤夋(Scanline 1乣239) // スクリーン描画(Scanline 1239)
if (bDraw) if (bDraw)
{ {
ppu.Scanline(scanline, Supporter.Config.graphics.bAllSprite, Supporter.Config.graphics.bLeftClip); ppu.Scanline(scanline, Supporter.Config.graphics.bAllSprite, Supporter.Config.graphics.bLeftClip);
@ -707,7 +707,7 @@ namespace VirtualNes.Core
} }
else if (scanline == 240) else if (scanline == 240)
{ {
// 僟儈乕僗僉儍儞儔僀儞 (Scanline 240) // ダミースキャンライン (Scanline 240)
mapper.VSync(); mapper.VSync();
EmulationCPU(nescfg.HDrawCycles); EmulationCPU(nescfg.HDrawCycles);
@ -720,7 +720,7 @@ namespace VirtualNes.Core
{ {
pad.VSync(); pad.VSync();
// VBLANK婜娫 // VBLANK期間
if (scanline == nescfg.TotalScanlines - 1) if (scanline == nescfg.TotalScanlines - 1)
{ {
ppu.VBlankEnd(); ppu.VBlankEnd();
@ -864,7 +864,7 @@ namespace VirtualNes.Core
MMU.VROM_4K_SIZE = rom.GetVROM_SIZE() * 2; MMU.VROM_4K_SIZE = rom.GetVROM_SIZE() * 2;
MMU.VROM_8K_SIZE = rom.GetVROM_SIZE(); MMU.VROM_8K_SIZE = rom.GetVROM_SIZE();
// 僨僼僅儖僩僶儞僋 // デフォルトバンク
if (MMU.VROM_8K_SIZE != 0) if (MMU.VROM_8K_SIZE != 0)
{ {
MMU.SetVROM_8K_Bank(0); MMU.SetVROM_8K_Bank(0);
@ -874,7 +874,7 @@ namespace VirtualNes.Core
MMU.SetCRAM_8K_Bank(0); MMU.SetCRAM_8K_Bank(0);
} }
// 儈儔乕 // ミラー
if (rom.Is4SCREEN()) if (rom.Is4SCREEN())
{ {
MMU.SetVRAM_Mirror(MMU.VRAM_MIRROR4); MMU.SetVRAM_Mirror(MMU.VRAM_MIRROR4);
@ -976,13 +976,13 @@ namespace VirtualNes.Core
reg.S = 0xFF; reg.S = 0xFF;
reg.P = CPU.Z_FLAG | CPU.R_FLAG | CPU.I_FLAG; reg.P = CPU.Z_FLAG | CPU.R_FLAG | CPU.I_FLAG;
// 埨慡懳嶔傪寭偹偰偁偊偰儖乕僾偵(1昩暘) // 安全対策を兼ねてあえてループに(1秒分)
for (int i = 0; i < nescfg.TotalScanlines * 60; i++) for (int i = 0; i < nescfg.TotalScanlines * 60; i++)
{ {
EmulationCPU(nescfg.ScanlineCycles); EmulationCPU(nescfg.ScanlineCycles);
cpu.GetContext(ref reg); cpu.GetContext(ref reg);
// 柍尷儖乕僾偵擖偭偨偙偲傪妋擣偟偨傜敳偗傞 // 無限ループに入ったことを確認したら抜ける
if (reg.PC == 0x4700) if (reg.PC == 0x4700)
{ {
break; break;
@ -993,7 +993,7 @@ namespace VirtualNes.Core
} }
cpu.GetContext(ref reg); cpu.GetContext(ref reg);
// 柍尷儖乕僾偵擖偭偰偄偨傜嵞愝掕偡傞 // 無限ループに入っていたら再設定する
if (reg.PC == 0x4700) if (reg.PC == 0x4700)
{ {
reg.PC = 0x4720; // Play Address reg.PC = 0x4720; // Play Address
@ -1009,7 +1009,7 @@ namespace VirtualNes.Core
else else
{ {
cpu.GetContext(ref reg); cpu.GetContext(ref reg);
reg.PC = 0x4700; // 柍尷儖乕僾 reg.PC = 0x4700; // 無限ループ
reg.S = 0xFF; reg.S = 0xFF;
EmulationCPU(nescfg.ScanlineCycles * nescfg.TotalScanlines); EmulationCPU(nescfg.ScanlineCycles * nescfg.TotalScanlines);
@ -1186,7 +1186,7 @@ namespace VirtualNes.Core
if (m_BarcodeCycles > 1000) if (m_BarcodeCycles > 1000)
{ {
m_BarcodeCycles = 0; m_BarcodeCycles = 0;
// 掆巭丠 // 停止?
if (m_BarcodeData[m_BarcodePtr] != 0xFF) if (m_BarcodeData[m_BarcodePtr] != 0xFF)
{ {
m_BarcodeOut = m_BarcodeData[m_BarcodePtr++]; m_BarcodeOut = m_BarcodeData[m_BarcodePtr++];
@ -1227,7 +1227,7 @@ namespace VirtualNes.Core
return; return;
m_TapeCycles += (nescfg.CpuClock / 32000.0); m_TapeCycles += (nescfg.CpuClock / 32000.0);
// m_TapeCycles += (nescfg.CpuClock / 22050.0); // 抶偡偓偰僟儊偭傐偄 // m_TapeCycles += (nescfg.CpuClock / 22050.0); // 遅すぎてダメっぽい
if (m_bTapePlay) if (m_bTapePlay)
{ {
@ -1293,7 +1293,7 @@ namespace VirtualNes.Core
return MMU.CPU_MEM_BANK[addr >> 13][addr & 0x1FFF]; return MMU.CPU_MEM_BANK[addr >> 13][addr & 0x1FFF];
} }
return 0x00; // Warning梊杊 return 0x00; // Warning予防
} }
private byte ReadReg(ushort addr) private byte ReadReg(ushort addr)
@ -1504,7 +1504,7 @@ namespace VirtualNes.Core
pad.Write(addr, data); pad.Write(addr, data);
apu.Write(addr, data); apu.Write(addr, data);
break; break;
// VirtuaNES屌桳億乕僩 // VirtuaNES固有ポート
case 0x18: case 0x18:
apu.Write(addr, data); apu.Write(addr, data);
break; break;
@ -1596,7 +1596,7 @@ namespace VirtualNes.Core
ref state.reg.cpureg.FrameIRQ_type, ref state.reg.cpureg.FrameIRQ_type,
ref state.reg.cpureg.FrameIRQ, ref state.reg.cpureg.FrameIRQ,
ref state.reg.cpureg.FrameIRQ_occur); ref state.reg.cpureg.FrameIRQ_occur);
state.reg.cpureg.FrameIRQ_cycles = cycles; // 参照がINTな為 state.reg.cpureg.FrameIRQ_cycles = cycles; // イホユユ、ャINT、ハ樣」ィ、ゥ
state.reg.cpureg.DMA_cycles = cpu.GetDmaCycles(); state.reg.cpureg.DMA_cycles = cpu.GetDmaCycles();
state.reg.cpureg.emul_cycles = emul_cycles; state.reg.cpureg.emul_cycles = emul_cycles;
@ -1625,7 +1625,7 @@ namespace VirtualNes.Core
MemoryUtility.memcpy(state.ram.SPPAL, MMU.SPPAL, state.ram.SPPAL.Length); MemoryUtility.memcpy(state.ram.SPPAL, MMU.SPPAL, state.ram.SPPAL.Length);
MemoryUtility.memcpy(state.ram.SPRAM, MMU.SPRAM, state.ram.SPRAM.Length); MemoryUtility.memcpy(state.ram.SPRAM, MMU.SPRAM, state.ram.SPRAM.Length);
// S-RAM STATE(使用/未使用に関わらず存在すればセーブする) // S-RAM STATE(ハケモテ/ホエハケモテ、ヒ騅、<E9A885>鬢コエ贇レ、ケ、<EFBDB9>ミ・サゥ`・ヨ、ケ、<EFBDB9>)
if (rom.IsSAVERAM()) if (rom.IsSAVERAM())
{ {
size = (uint)SAVERAM_SIZE; size = (uint)SAVERAM_SIZE;
@ -1649,9 +1649,9 @@ namespace VirtualNes.Core
uint size = 0; uint size = 0;
// SAVE CPU MEMORY BANK DATA // SAVE CPU MEMORY BANK DATA
// BANK0,1,2はバンクセーブに関係なし // BANK0,1,2、マ・ミ・<EFBFBD>ッ・サゥ`・ヨ、ヒ騅4、ハ、キ
// VirtuaNES0.30から // VirtuaNES0.30、ォ、<EFBFBD>
// バンクはSRAM使用に関わらずセーブ // ・ミ・<EFBFBD>ッ」ウ、マSRAMハケモテ、ヒ騅、<EFBFBD>鬢コ・サゥ`・ヨ
for (int i = 3; i < 8; i++) for (int i = 3; i < 8; i++)
{ {
state.mmu.CPU_MEM_TYPE[i] = MMU.CPU_MEM_TYPE[i]; state.mmu.CPU_MEM_TYPE[i] = MMU.CPU_MEM_TYPE[i];
@ -1696,7 +1696,7 @@ namespace VirtualNes.Core
} }
} }
// WRITE VRAM MEMORY(常に4K分すべて書き込む) // WRITE VRAM MEMORY(ウ」、ヒ4Kキヨ、ケ、ル、ニ抱、ュ゙z、<EFBFBD>)
state.VRAM = new byte[4 * 1024]; state.VRAM = new byte[4 * 1024];
Array.Copy(MMU.VRAM, state.VRAM, state.VRAM.Length); Array.Copy(MMU.VRAM, state.VRAM, state.VRAM.Length);
@ -1764,7 +1764,7 @@ namespace VirtualNes.Core
int DiskSize = 16 + 65500 * rom.GetDiskNo(); int DiskSize = 16 + 65500 * rom.GetDiskNo();
// 相違数をカウント // マ珀`ハ<><EFBFBD>ォ・ヲ・<EFBDA6>
for (int i = 16; i < DiskSize; i++) for (int i = 16; i < DiskSize; i++)
{ {
if (lpWrite[i] != 0) if (lpWrite[i] != 0)
@ -1874,9 +1874,9 @@ namespace VirtualNes.Core
//BANK STATE //BANK STATE
{ {
// SAVE CPU MEMORY BANK DATA // SAVE CPU MEMORY BANK DATA
// BANK0,1,2はバンクセーブに関係なし // BANK0,1,2、マ・ミ・<EFBFBD>ッ・サゥ`・ヨ、ヒ騅4、ハ、キ
// VirtuaNES0.30から // VirtuaNES0.30、ォ、<EFBFBD>
// バンクはSRAM使用に関わらずセーブ // ・ミ・<EFBFBD>ッ」ウ、マSRAMハケモテ、ヒ騅、<EFBFBD>鬢コ・サゥ`・ヨ
for (byte i = 3; i < 8; i++) for (byte i = 3; i < 8; i++)
{ {
MMU.CPU_MEM_TYPE[i] = state.mmu.CPU_MEM_TYPE[i]; MMU.CPU_MEM_TYPE[i] = state.mmu.CPU_MEM_TYPE[i];

View File

@ -2,7 +2,7 @@
{ {
public struct BLOCKHDR : IStateBufferObject public struct BLOCKHDR : IStateBufferObject
{ {
public bool Valid => !string.IsNullOrEmpty(ID); public bool Valid => !string.IsNullOrEmpty(ID);
/// <summary> 总是8个字节 </summary> /// <summary> 总是8个字节 </summary>
public string ID; public string ID;
public ushort Reserved; public ushort Reserved;
@ -11,12 +11,12 @@
public uint GetSize() public uint GetSize()
{ {
return (uint)(8 + sizeof(ushort) + sizeof(ushort) + sizeof(uint)); return (uint)(8 + sizeof(ushort) + sizeof(ushort) + sizeof(uint));
} }
public void SaveState(StateBuffer buffer) public void SaveState(StateBuffer buffer)
{ {
if (Valid) if (Valid)
{ {

View File

@ -8,12 +8,12 @@
public uint pad4bit; public uint pad4bit;
public byte strobe; public byte strobe;
public uint GetSize() public uint GetSize()
{ {
return sizeof(uint) * 4 + sizeof(byte); return sizeof(uint) * 4 + sizeof(byte);
} }
public void SaveState(StateBuffer buffer) public void SaveState(StateBuffer buffer)
{ {
buffer.Write(pad1bit); buffer.Write(pad1bit);
buffer.Write(pad2bit); buffer.Write(pad2bit);

View File

@ -4,12 +4,12 @@
{ {
public uint data; public uint data;
public uint GetSize() public uint GetSize()
{ {
return sizeof(uint); return sizeof(uint);
} }
public void SaveState(StateBuffer buffer) public void SaveState(StateBuffer buffer)
{ {
buffer.Write(data); buffer.Write(data);
} }

View File

@ -14,12 +14,12 @@
public uint GetSize() public uint GetSize()
{ {
return (uint)(ID.Length + sizeof(ushort) + sizeof(uint) + sizeof(ushort) + sizeof(ushort)); return (uint)(ID.Length + sizeof(ushort) + sizeof(uint) + sizeof(ushort) + sizeof(ushort));
} }
public void SaveState(StateBuffer buffer) public void SaveState(StateBuffer buffer)
{ {
buffer.Write(ID); buffer.Write(ID);
buffer.Write(BlockVersion); buffer.Write(BlockVersion);

View File

@ -9,12 +9,12 @@
return new MMCSTAT() { mmcdata = new byte[256] }; return new MMCSTAT() { mmcdata = new byte[256] };
} }
public uint GetSize() public uint GetSize()
{ {
return 256; return 256;
} }
public void SaveState(StateBuffer buffer) public void SaveState(StateBuffer buffer)
{ {
buffer.Write(mmcdata); buffer.Write(mmcdata);
} }

View File

@ -22,12 +22,12 @@ namespace VirtualNes.Core
return res; return res;
} }
public uint GetSize() public uint GetSize()
{ {
return (uint)(RAM.Length + BGPAL.Length + SPPAL.Length + SPRAM.Length); return (uint)(RAM.Length + BGPAL.Length + SPPAL.Length + SPRAM.Length);
} }
public void SaveState(StateBuffer buffer) public void SaveState(StateBuffer buffer)
{ {
buffer.Write(RAM); buffer.Write(RAM);
buffer.Write(BGPAL); buffer.Write(BGPAL);

View File

@ -7,12 +7,12 @@
public uint GetSize() public uint GetSize()
{ {
return cpureg.GetSize() + ppureg.GetSize(); return cpureg.GetSize() + ppureg.GetSize();
} }
public void SaveState(StateBuffer buffer) public void SaveState(StateBuffer buffer)
{ {
cpureg.SaveState(buffer); cpureg.SaveState(buffer);
ppureg.SaveState(buffer); ppureg.SaveState(buffer);
@ -45,12 +45,12 @@
public long emul_cycles; public long emul_cycles;
public long base_cycles; public long base_cycles;
public uint GetSize() public uint GetSize()
{ {
return 32; return 32;
} }
public void SaveState(StateBuffer buffer) public void SaveState(StateBuffer buffer)
{ {
buffer.Write(PC); buffer.Write(PC);
buffer.Write(A); buffer.Write(A);
@ -102,12 +102,12 @@
public ushort loopy_v; public ushort loopy_v;
public ushort loopy_x; public ushort loopy_x;
public uint GetSize() public uint GetSize()
{ {
return 12; return 12;
} }
public void SaveState(StateBuffer buffer) public void SaveState(StateBuffer buffer)
{ {
buffer.Write(reg0); buffer.Write(reg0);
buffer.Write(reg1); buffer.Write(reg1);

View File

@ -9,12 +9,12 @@
return new SNDSTAT() { snddata = new byte[0x800] }; return new SNDSTAT() { snddata = new byte[0x800] };
} }
public uint GetSize() public uint GetSize()
{ {
return (uint)snddata.Length; return (uint)snddata.Length;
} }
public void SaveState(StateBuffer buffer) public void SaveState(StateBuffer buffer)
{ {
buffer.Write(snddata); buffer.Write(snddata);
} }

View File

@ -36,7 +36,7 @@ namespace VirtualNes.Core
public BLOCKHDR exctrBLOCK; public BLOCKHDR exctrBLOCK;
public EXCTRSTAT exctr; public EXCTRSTAT exctr;
public byte[] ToBytes() public byte[] ToBytes()
{ {
StateBuffer buffer = new StateBuffer(); StateBuffer buffer = new StateBuffer();

View File

@ -2,7 +2,7 @@
namespace VirtualNes.Core namespace VirtualNes.Core
{ {
public struct ControllerState : IEquatable<ControllerState> public struct ControllerState
{ {
public uint raw0; public uint raw0;
public uint raw1; public uint raw1;
@ -11,74 +11,20 @@ namespace VirtualNes.Core
public bool valid; public bool valid;
public ControllerState(EnumButtonType[] states) public ControllerState(
EnumButtonType player0_buttons,
EnumButtonType player1_buttons,
EnumButtonType player2_buttons,
EnumButtonType player3_buttons)
{ {
raw0 = (uint)states[0]; raw0 = (uint)player0_buttons;
raw1 = (uint)states[1]; raw1 = (uint)player1_buttons;
raw2 = (uint)states[2]; raw2 = (uint)player2_buttons;
raw3 = (uint)states[3]; raw3 = (uint)player3_buttons;
valid = true; valid = true;
} }
public bool HasButton(int player, EnumButtonType button)
{
uint raw;
switch (player) public static bool operator ==(ControllerState left, ControllerState right)
{
case 0: raw = raw0; break;
case 1: raw = raw1; break;
case 2: raw = raw2; break;
case 3: raw = raw3; break;
default:
raw = 0;
break;
}
return (raw & (uint)button) == (uint)button;
}
public override string ToString()
{
return $"{raw0}|{raw1}|{raw2}|{raw3}";
}
#region Impl_Equals
public bool Equals(ControllerState other)
{
return raw0 == other.raw0 && raw1 == other.raw1 && raw2 == other.raw2 && raw3 == other.raw3 && valid == other.valid;
}
public override bool Equals(object obj)
{
return obj is ControllerState other && Equals(other);
}
public override int GetHashCode()
{
//return HashCode.Combine(raw0, raw1, raw2, raw3, valid);
return ComputeHashCode(raw0, raw1, raw2, raw3, valid);
}
public static int ComputeHashCode(uint raw0, uint raw1, uint raw2, uint raw3, bool valid)
{
unchecked // 允许溢出,使得哈希码计算更加合理
{
int hash = 17; // 选择一个非零的初始值
// 将每个 uint 类型的值转换为 int 并合并到哈希码中
hash = hash * 31 + (int)raw0;
hash = hash * 31 + (int)raw1;
hash = hash * 31 + (int)raw2;
hash = hash * 31 + (int)raw3;
// 将 bool 类型的值转换为 int 并合并到哈希码中
hash = hash * 31 + (valid ? 1 : 0);
return hash;
}
}
public static bool operator ==(ControllerState left, ControllerState right)
{ {
return return
left.raw0 == right.raw0 && left.raw0 == right.raw0 &&
@ -91,7 +37,24 @@ namespace VirtualNes.Core
{ {
return !(left == right); return !(left == right);
} }
#endregion
public override string ToString()
{
return $"{raw0}|{raw1}|{raw2}|{raw3}";
}
public bool HasButton(int player, EnumButtonType button)
{
uint raw = 0;
switch (player)
{
case 0: raw = raw0; break;
case 1: raw = raw1; break;
case 2: raw = raw2; break;
case 3: raw = raw3; break;
}
return (raw & (uint)button) == (uint)button;
}
} }
[Flags] [Flags]

View File

@ -5,7 +5,6 @@ namespace VirtualNes.Core
public static class Supporter public static class Supporter
{ {
private static ISupporterImpl s_support; private static ISupporterImpl s_support;
public static void Setup(ISupporterImpl supporter) public static void Setup(ISupporterImpl supporter)
{ {
s_support = supporter; s_support = supporter;
@ -45,7 +44,6 @@ namespace VirtualNes.Core
{ {
s_support.SaveFile(fileData, directPath, fileName); s_support.SaveFile(fileData, directPath, fileName);
} }
public static Stream OpenFile(string directPath, string fileName) public static Stream OpenFile(string directPath, string fileName)
{ {
return s_support.OpenFile(directPath, fileName); return s_support.OpenFile(directPath, fileName);
@ -66,11 +64,6 @@ namespace VirtualNes.Core
s_support.SampleInput(frameCount); s_support.SampleInput(frameCount);
} }
public static IControllerSetuper GetControllerSetuper()
{
return s_support.GetControllerSetuper();
}
public static EmulatorConfig Config => s_support.Config; public static EmulatorConfig Config => s_support.Config;
} }
@ -89,21 +82,5 @@ namespace VirtualNes.Core
bool TryGetMapperNo(ROM rom, out int mapperNo); bool TryGetMapperNo(ROM rom, out int mapperNo);
ControllerState GetControllerState(); ControllerState GetControllerState();
void SampleInput(uint frameCount); void SampleInput(uint frameCount);
IControllerSetuper GetControllerSetuper();
} }
}
/// <summary>
/// 负责管理本地控制器与具体游戏之间的槽位分配
/// </summary>
public interface IControllerSetuper
{
/// <summary>
/// 设置本地手柄与游戏手柄槽位的映射
/// </summary>
void SetConnect(
uint? con0ToSlot = null,
uint? con1ToSlot = null,
uint? con2ToSlot = null,
uint? con3ToSlot = null);
}
}

View File

@ -8,85 +8,85 @@ using UnityEngine;
public class AxiProjectTools : EditorWindow public class AxiProjectTools : EditorWindow
{ {
static string cachecfgPath = "Assets/AxiComToolCache.asset"; static string cachecfgPath = "Assets/AxiComToolCache.asset";
static string toolSenceName = "AxiProjectTools"; static string toolSenceName = "AxiProjectTools";
static string outCsDir = Application.dataPath + "/AxiCom/"; static string outCsDir = Application.dataPath + "/AxiCom/";
static Dictionary<string, AxiPrefabCache_Com2GUID> ComType2GUID = new Dictionary<string, AxiPrefabCache_Com2GUID>(); static Dictionary<string, AxiPrefabCache_Com2GUID> ComType2GUID = new Dictionary<string, AxiPrefabCache_Com2GUID>();
static void GoTAxiProjectToolsSence() static void GoTAxiProjectToolsSence()
{ {
string[] sceneGuids = AssetDatabase.FindAssets("t:scene"); string[] sceneGuids = AssetDatabase.FindAssets("t:scene");
foreach (string guid in sceneGuids) foreach (string guid in sceneGuids)
{ {
string path = AssetDatabase.GUIDToAssetPath(guid); string path = AssetDatabase.GUIDToAssetPath(guid);
if (path.Contains(toolSenceName)) if (path.Contains(toolSenceName))
{ {
EditorSceneManager.OpenScene(path); EditorSceneManager.OpenScene(path);
return; return;
} }
} }
} }
[MenuItem("Axibug移植工具/[1]UGUI组件")] [MenuItem("Axibug移植工具/[1]UGUI组件")]
public static void Part1() public static void Part1()
{ {
GoTAxiProjectToolsSence(); GoTAxiProjectToolsSence();
ComType2GUID.Clear(); ComType2GUID.Clear();
string[] sceneGuids = AssetDatabase.FindAssets("t:scene"); string[] sceneGuids = AssetDatabase.FindAssets("t:scene");
foreach (string guid in sceneGuids) foreach (string guid in sceneGuids)
{ {
string path = AssetDatabase.GUIDToAssetPath(guid); string path = AssetDatabase.GUIDToAssetPath(guid);
if (path.Contains(toolSenceName)) if (path.Contains(toolSenceName))
continue; continue;
EditorSceneManager.OpenScene(path); EditorSceneManager.OpenScene(path);
// 创建一个列表来存储根节点 // 创建一个列表来存储根节点
List<GameObject> rootNodes = new List<GameObject>(); List<GameObject> rootNodes = new List<GameObject>();
// 遍历场景中的所有对象 // 遍历场景中的所有对象
GameObject[] allObjects = FindObjectsOfType<GameObject>(); GameObject[] allObjects = FindObjectsOfType<GameObject>();
foreach (GameObject obj in allObjects) foreach (GameObject obj in allObjects)
{ {
// 检查对象是否有父对象 // 检查对象是否有父对象
if (obj.transform.parent == null) if (obj.transform.parent == null)
{ {
// 如果没有父对象,则它是一个根节点 // 如果没有父对象,则它是一个根节点
rootNodes.Add(obj); rootNodes.Add(obj);
} }
} }
foreach (var node in rootNodes) foreach (var node in rootNodes)
LoopPrefabNode(path, node, 0); LoopPrefabNode(path, node, 0);
} }
string[] prefabGuids = AssetDatabase.FindAssets("t:Prefab"); string[] prefabGuids = AssetDatabase.FindAssets("t:Prefab");
foreach (string guid in prefabGuids) foreach (string guid in prefabGuids)
{ {
string path = AssetDatabase.GUIDToAssetPath(guid); string path = AssetDatabase.GUIDToAssetPath(guid);
GetPrefab(path); GetPrefab(path);
} }
AxiPrefabCache cache = ScriptableObject.CreateInstance<AxiPrefabCache>(); AxiPrefabCache cache = ScriptableObject.CreateInstance<AxiPrefabCache>();
foreach (var data in ComType2GUID) foreach (var data in ComType2GUID)
cache.caches.Add(data.Value); cache.caches.Add(data.Value);
AssetDatabase.CreateAsset(cache, cachecfgPath); AssetDatabase.CreateAsset(cache, cachecfgPath);
AssetDatabase.SaveAssets(); AssetDatabase.SaveAssets();
AssetDatabase.Refresh(); AssetDatabase.Refresh();
GoTAxiProjectToolsSence(); GoTAxiProjectToolsSence();
Debug.Log("<Color=#FFF333>处理完毕 [1]采集所有预制体和场景下的UGUI组件</color>"); Debug.Log("<Color=#FFF333>处理完毕 [1]采集所有预制体和场景下的UGUI组件</color>");
} }
static void GetPrefab(string path)
{
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
LoopPrefabNode(path, prefab.gameObject, 0);
}
static void LoopPrefabNode(string rootPath, GameObject trans, int depth)
{
string nodename = $"{rootPath}>{trans.name}";
static void GetPrefab(string path)
{
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
LoopPrefabNode(path, prefab.gameObject, 0);
}
static void LoopPrefabNode(string rootPath, GameObject trans, int depth)
{
string nodename = $"{rootPath}>{trans.name}";
#if UNITY_5_4_OR_NEWER && !UNITY_2018_4_OR_NEWER
GameObject prefabRoot = trans.gameObject; GameObject prefabRoot = trans.gameObject;
int comCount = prefabRoot.GetComponentCount(); int comCount = prefabRoot.GetComponentCount();
for (int i = 0; i < comCount; i++) for (int i = 0; i < comCount; i++)
@ -130,253 +130,250 @@ public class AxiProjectTools : EditorWindow
//±éÀú //±éÀú
foreach (Transform child in trans.transform) foreach (Transform child in trans.transform)
LoopPrefabNode(nodename, child.gameObject, depth + 1); LoopPrefabNode(nodename, child.gameObject, depth + 1);
#else }
Debug.Log("低版本不要执行本函数");
#endif
}
[MenuItem("Axibug移植工具/[2]")] [MenuItem("Axibug移植工具/[2]")]
public static void Part2() public static void Part2()
{ {
if (UnityEngine.Windows.Directory.Exists(outCsDir)) if (UnityEngine.Windows.Directory.Exists(outCsDir))
UnityEngine.Windows.Directory.Delete(outCsDir); UnityEngine.Windows.Directory.Delete(outCsDir);
Directory.CreateDirectory(outCsDir); Directory.CreateDirectory(outCsDir);
AxiPrefabCache cache = AssetDatabase.LoadAssetAtPath<AxiPrefabCache>(cachecfgPath); AxiPrefabCache cache = AssetDatabase.LoadAssetAtPath<AxiPrefabCache>(cachecfgPath);
foreach (var data in cache.caches) foreach (var data in cache.caches)
{ {
string toName = "Axi" + data.SrcName; string toName = "Axi" + data.SrcName;
string toPath = outCsDir + toName + ".cs"; string toPath = outCsDir + toName + ".cs";
string codeStr = "namespace AxibugCom { public class " + toName + " : " + data.SrcFullName + " {} }"; string codeStr = "namespace AxibugCom { public class " + toName + " : " + data.SrcFullName + " {} }";
try try
{ {
System.IO.File.WriteAllText(toPath, codeStr); System.IO.File.WriteAllText(toPath, codeStr);
data.ToName = toName; data.ToName = toName;
data.ToPATH = toPath; data.ToPATH = toPath;
} }
catch (Exception ex) catch (Exception ex)
{ {
Debug.LogError("写入失败" + ex.ToString()); Debug.LogError("写入失败" + ex.ToString());
} }
} }
Debug.Log("写入完毕"); Debug.Log("写入完毕");
AssetDatabase.SaveAssets(); AssetDatabase.SaveAssets();
AssetDatabase.Refresh(); AssetDatabase.Refresh();
Debug.Log("<Color=#FFF333>处理完毕 [2]生成中间脚本代码</color>"); Debug.Log("<Color=#FFF333>处理完毕 [2]生成中间脚本代码</color>");
} }
[MenuItem("Axibug移植工具/[3]")] [MenuItem("Axibug移植工具/[3]")]
public static void Part3() public static void Part3()
{ {
AxiPrefabCache cache = AssetDatabase.LoadAssetAtPath<AxiPrefabCache>(cachecfgPath); AxiPrefabCache cache = AssetDatabase.LoadAssetAtPath<AxiPrefabCache>(cachecfgPath);
List<MonoScript> allMonoScripts = FindAllAssetsOfType<MonoScript>(); List<MonoScript> allMonoScripts = FindAllAssetsOfType<MonoScript>();
foreach (var data in cache.caches) foreach (var data in cache.caches)
{ {
MonoScript monoScript = allMonoScripts.FirstOrDefault(w => w.name == data.ToName); MonoScript monoScript = allMonoScripts.FirstOrDefault(w => w.name == data.ToName);
if (monoScript == null) if (monoScript == null)
{ {
Debug.LogError("没找到" + data.ToName); Debug.LogError("没找到" + data.ToName);
continue; continue;
} }
string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(monoScript)); string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(monoScript));
data.ToGUID = guid; data.ToGUID = guid;
data.monoScript = monoScript; data.monoScript = monoScript;
} }
Debug.Log("写入完毕"); Debug.Log("写入完毕");
AssetDatabase.SaveAssets(); AssetDatabase.SaveAssets();
AssetDatabase.Refresh(); AssetDatabase.Refresh();
Debug.Log("<Color=#FFF333>处理完毕 [3]收集生成的脚本</color>"); Debug.Log("<Color=#FFF333>处理完毕 [3]收集生成的脚本</color>");
} }
static List<T> FindAllAssetsOfType<T>() where T : UnityEngine.Object static List<T> FindAllAssetsOfType<T>() where T : UnityEngine.Object
{ {
List<T> assets = new List<T>(); List<T> assets = new List<T>();
string[] allGuids = AssetDatabase.FindAssets(""); string[] allGuids = AssetDatabase.FindAssets("");
foreach (string guid in allGuids) foreach (string guid in allGuids)
{ {
string path = AssetDatabase.GUIDToAssetPath(guid); string path = AssetDatabase.GUIDToAssetPath(guid);
if (path.EndsWith(".cs") || path.EndsWith(".js") || path.EndsWith(".boo")) // Unity支持多种脚本语言但现代Unity主要使用C# if (path.EndsWith(".cs") || path.EndsWith(".js") || path.EndsWith(".boo")) // Unity支持多种脚本语言但现代Unity主要使用C#
{ {
T asset = AssetDatabase.LoadAssetAtPath<T>(path); T asset = AssetDatabase.LoadAssetAtPath<T>(path);
if (asset != null) if (asset != null)
{ {
assets.Add(asset); assets.Add(asset);
} }
} }
} }
return assets; return assets;
} }
[MenuItem("Axibug移植工具/[4]")] [MenuItem("Axibug移植工具/[4]")]
public static void Part4() public static void Part4()
{ {
AxiPrefabCache cache = AssetDatabase.LoadAssetAtPath<AxiPrefabCache>(cachecfgPath); AxiPrefabCache cache = AssetDatabase.LoadAssetAtPath<AxiPrefabCache>(cachecfgPath);
Dictionary<string, string> tempReplaceDict = new Dictionary<string, string>(); Dictionary<string, string> tempReplaceDict = new Dictionary<string, string>();
foreach (var data in cache.caches) foreach (var data in cache.caches)
{ {
tempReplaceDict[data.GUID] = data.ToGUID; tempReplaceDict[data.GUID] = data.ToGUID;
} }
ProcessAllPrefabs("*.prefab", tempReplaceDict); ProcessAllPrefabs("*.prefab", tempReplaceDict);
ProcessAllPrefabs("*.unity", tempReplaceDict); ProcessAllPrefabs("*.unity", tempReplaceDict);
ProcessAllPrefabs("*.anim", tempReplaceDict); ProcessAllPrefabs("*.anim", tempReplaceDict);
AssetDatabase.SaveAssets(); AssetDatabase.SaveAssets();
AssetDatabase.Refresh(); AssetDatabase.Refresh();
Debug.Log("<Color=#FFF333>处理完毕 [4]替换所有预制体和场景中的组件</color>"); Debug.Log("<Color=#FFF333>处理完毕 [4]替换所有预制体和场景中的组件</color>");
} }
static void ProcessAllPrefabs(string form, Dictionary<string, string> tempReplaceDict, bool reverse = false) static void ProcessAllPrefabs(string form, Dictionary<string, string> tempReplaceDict, bool reverse = false)
{ {
List<GameObject> prefabs = new List<GameObject>(); List<GameObject> prefabs = new List<GameObject>();
var resourcesPath = Application.dataPath; var resourcesPath = Application.dataPath;
var absolutePaths = Directory.GetFiles(resourcesPath, form, SearchOption.AllDirectories); var absolutePaths = Directory.GetFiles(resourcesPath, form, SearchOption.AllDirectories);
for (int i = 0; i < absolutePaths.Length; i++) for (int i = 0; i < absolutePaths.Length; i++)
{ {
Debug.Log("prefab name: " + absolutePaths[i]); Debug.Log("prefab name: " + absolutePaths[i]);
foreach (var VARIABLE in tempReplaceDict) foreach (var VARIABLE in tempReplaceDict)
{ {
string oldValue = reverse ? VARIABLE.Value : VARIABLE.Key; string oldValue = reverse ? VARIABLE.Value : VARIABLE.Key;
string newValue = reverse ? VARIABLE.Key : VARIABLE.Value; string newValue = reverse ? VARIABLE.Key : VARIABLE.Value;
ReplaceValue(absolutePaths[i], oldValue, newValue); ReplaceValue(absolutePaths[i], oldValue, newValue);
} }
EditorUtility.DisplayProgressBar("处理预制体……", "处理预制体中……", (float)i / absolutePaths.Length); EditorUtility.DisplayProgressBar("处理预制体……", "处理预制体中……", (float)i / absolutePaths.Length);
} }
EditorUtility.ClearProgressBar(); EditorUtility.ClearProgressBar();
} }
/// <summary> /// <summary>
/// 替换值 /// 替换值
/// </summary> /// </summary>
/// <param name="strFilePath">文件路径</param> /// <param name="strFilePath">文件路径</param>
static void ReplaceValue(string strFilePath, string oldLine, string newLine) static void ReplaceValue(string strFilePath, string oldLine, string newLine)
{ {
if (File.Exists(strFilePath)) if (File.Exists(strFilePath))
{ {
string[] lines = File.ReadAllLines(strFilePath); string[] lines = File.ReadAllLines(strFilePath);
for (int i = 0; i < lines.Length; i++) for (int i = 0; i < lines.Length; i++)
{ {
lines[i] = lines[i].Replace(oldLine, newLine); lines[i] = lines[i].Replace(oldLine, newLine);
} }
File.WriteAllLines(strFilePath, lines); File.WriteAllLines(strFilePath, lines);
} }
} }
[MenuItem("Axibug移植工具/[5]UnPack所有预制体")] [MenuItem("Axibug移植工具/[5]UnPack所有预制体")]
public static void UnpackPrefabs() public static void UnpackPrefabs()
{ {
string[] allAssetPaths = AssetDatabase.GetAllAssetPaths(); string[] allAssetPaths = AssetDatabase.GetAllAssetPaths();
int prefabCount = 0; int prefabCount = 0;
foreach (string path in allAssetPaths) foreach (string path in allAssetPaths)
{ {
if (Path.GetExtension(path).Equals(".prefab")) if (Path.GetExtension(path).Equals(".prefab"))
{ {
Debug.Log($"Unpacking {path}"); Debug.Log($"Unpacking {path}");
UnpackPrefab(path); UnpackPrefab(path);
prefabCount++; prefabCount++;
} }
} }
Debug.Log($"Unpacked {prefabCount} prefabs."); Debug.Log($"Unpacked {prefabCount} prefabs.");
Debug.Log("<Color=#FFF333>处理完毕 [5]UnPack所有预制体</color>"); Debug.Log("<Color=#FFF333>处理完毕 [5]UnPack所有预制体</color>");
} }
static void UnpackPrefab(string prefabPath) static void UnpackPrefab(string prefabPath)
{ {
GameObject prefabInstance = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath); GameObject prefabInstance = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
if (prefabInstance == null) if (prefabInstance == null)
{ {
Debug.LogError($"Failed to load prefab at path: {prefabPath}"); Debug.LogError($"Failed to load prefab at path: {prefabPath}");
return; return;
} }
var obj = GameObject.Instantiate(prefabInstance, null); var obj = GameObject.Instantiate(prefabInstance, null);
TraverseHierarchy(obj); TraverseHierarchy(obj);
PrefabUtility.SaveAsPrefabAsset(obj, prefabPath); PrefabUtility.SaveAsPrefabAsset(obj, prefabPath);
GameObject.DestroyImmediate(obj); GameObject.DestroyImmediate(obj);
} }
static void TraverseHierarchy(GameObject obj) static void TraverseHierarchy(GameObject obj)
{ {
// 检查该对象是否是预制体的实例 // 检查该对象是否是预制体的实例
if (PrefabUtility.IsPartOfPrefabInstance(obj)) if (PrefabUtility.IsPartOfPrefabInstance(obj))
{ {
// 将预制体实例转换为普通游戏对象 // 将预制体实例转换为普通游戏对象
PrefabUtility.UnpackPrefabInstance(obj, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction); PrefabUtility.UnpackPrefabInstance(obj, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction);
Debug.Log("Prefab instance converted to game object: " + obj.name); Debug.Log("Prefab instance converted to game object: " + obj.name);
} }
// 递归遍历子对象 // 递归遍历子对象
for (int i = 0; i < obj.transform.childCount; i++) for (int i = 0; i < obj.transform.childCount; i++)
{ {
TraverseHierarchy(obj.transform.GetChild(i).gameObject); TraverseHierarchy(obj.transform.GetChild(i).gameObject);
} }
} }
[MenuItem("Axibug移植工具/[6]Sprite")] [MenuItem("Axibug移植工具/[6]Sprite")]
public static void FixMultipleMaterialSprites() public static void FixMultipleMaterialSprites()
{ {
string[] guids = AssetDatabase.FindAssets("t:sprite"); string[] guids = AssetDatabase.FindAssets("t:sprite");
List<Sprite> spritesToFix = new List<Sprite>(); List<Sprite> spritesToFix = new List<Sprite>();
foreach (string guid in guids) foreach (string guid in guids)
{ {
string path = AssetDatabase.GUIDToAssetPath(guid); string path = AssetDatabase.GUIDToAssetPath(guid);
Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>(path); Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>(path);
// 检查是否有多个材质 // 检查是否有多个材质
if (IsUsingMultipleMaterials(sprite)) if (IsUsingMultipleMaterials(sprite))
{ {
spritesToFix.Add(sprite); spritesToFix.Add(sprite);
Debug.Log("Found sprite with multiple materials: " + path); Debug.Log("Found sprite with multiple materials: " + path);
} }
} }
// 修复每个找到的Sprite // 修复每个找到的Sprite
foreach (var sprite in spritesToFix) foreach (var sprite in spritesToFix)
{ {
FixSprite(sprite); FixSprite(sprite);
} }
AssetDatabase.SaveAssets(); AssetDatabase.SaveAssets();
AssetDatabase.Refresh(); AssetDatabase.Refresh();
Debug.Log("<Color=#FFF333>处理完毕 [6]修复Sprite</color>"); Debug.Log("<Color=#FFF333>处理完毕 [6]修复Sprite</color>");
} }
private static bool IsUsingMultipleMaterials(Sprite sprite) private static bool IsUsingMultipleMaterials(Sprite sprite)
{ {
if (sprite == null) return false; if (sprite == null) return false;
// 获取精灵的材质 // 获取精灵的材质
var textureImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(sprite)) as TextureImporter; var textureImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(sprite)) as TextureImporter;
return textureImporter != null && textureImporter.spriteImportMode == SpriteImportMode.Multiple; return textureImporter != null && textureImporter.spriteImportMode == SpriteImportMode.Multiple;
} }
private static void FixSprite(Sprite sprite) private static void FixSprite(Sprite sprite)
{ {
// 获取Sprite的路径 // 获取Sprite的路径
string path = AssetDatabase.GetAssetPath(sprite); string path = AssetDatabase.GetAssetPath(sprite);
var textureImporter = AssetImporter.GetAtPath(path) as TextureImporter; var textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;
if (textureImporter != null) if (textureImporter != null)
{ {
// 保存当前切割信息 // 保存当前切割信息
SpriteMetaData[] originalMetaData = textureImporter.spritesheet; SpriteMetaData[] originalMetaData = textureImporter.spritesheet;
// 临时禁用Sprite导入 // 临时禁用Sprite导入
textureImporter.spriteImportMode = SpriteImportMode.None; textureImporter.spriteImportMode = SpriteImportMode.None;
textureImporter.SaveAndReimport(); textureImporter.SaveAndReimport();
// 重新启用Sprite导入并保持原样切割参数 // 重新启用Sprite导入并保持原样切割参数
textureImporter.spriteImportMode = SpriteImportMode.Multiple; textureImporter.spriteImportMode = SpriteImportMode.Multiple;
textureImporter.spritesheet = originalMetaData; // 恢复原来的切割信息 textureImporter.spritesheet = originalMetaData; // 恢复原来的切割信息
// 重新导入以应用更改 // 重新导入以应用更改
textureImporter.SaveAndReimport(); textureImporter.SaveAndReimport();
} }
} }
} }

View File

@ -36,7 +36,7 @@ namespace AxibugEmuOnline.Client.ClientCore
private static CoroutineRunner coRunner; private static CoroutineRunner coRunner;
#endregion #endregion
#if UNITY_PSP2 && !UNITY_EDITOR //PSV真机 #if UNITY_PSP2
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,13 +45,7 @@ namespace AxibugEmuOnline.Client.ClientCore
{ {
PlayerPrefs.DeleteAll(); PlayerPrefs.DeleteAll();
if (UnityEngine.Application.platform == RuntimePlatform.PSP2) settings = new AppSettings();
{
//PSV 等平台需要手动创建目录
PSP2Init();
}
settings = new AppSettings();
log = new LogManager(); log = new LogManager();
LogManager.OnLog += OnNoSugarNetLog; LogManager.OnLog += OnNoSugarNetLog;
@ -74,6 +68,11 @@ 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);
@ -82,17 +81,12 @@ 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,12 +1,19 @@
{ {
"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,19 +248,7 @@ 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 VirtualNes.Core.IControllerSetuper m_controllerSetuper; private IControllerSetuper m_controllerSetuper;
/// <summary> /// <summary>
/// unity的c#实现有bug,以接口类型保存的monobehaviour引用,!=和==运算符没有调用到monobehaviour重写过的运算符 /// unity的c#实现有bug,以接口类型保存的monobehaviour引用,!=和==运算符没有调用到monobehaviour重写过的运算符
@ -84,15 +84,10 @@ namespace AxibugEmuOnline.Client.Manager
else //在房间中则使用服务器下发的手柄槽位信息分配本地手柄 else //在房间中则使用服务器下发的手柄槽位信息分配本地手柄
{ {
long selfUID = App.user.userdata.UID; long selfUID = App.user.userdata.UID;
uint? con0Slot; App.roomMgr.mineRoomMiniInfo.GetPlayerSlotIdxByUid(selfUID, 0, out var con0Slot);
uint? con1Slot; App.roomMgr.mineRoomMiniInfo.GetPlayerSlotIdxByUid(selfUID, 1, out var con1Slot);
uint? con2Slot; App.roomMgr.mineRoomMiniInfo.GetPlayerSlotIdxByUid(selfUID, 2, out var con2Slot);
uint? con3Slot; App.roomMgr.mineRoomMiniInfo.GetPlayerSlotIdxByUid(selfUID, 3, out var 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,13 +62,10 @@ 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
{ {
object cacheObj; if (cachesInMemory.TryGetValue(url, out var cacheObj) && cacheObj is T obj)
if (cachesInMemory.TryGetValue(url, out cacheObj) && cacheObj is T)
{ {
T obj = (T)cacheObj; callback.Invoke(obj, url);
callback.Invoke(obj, url);
return; return;
} }

View File

@ -22,8 +22,6 @@ 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));
@ -88,40 +86,23 @@ namespace AxibugEmuOnline.Client
/// </summary> /// </summary>
/// <param name="rom">rom对象</param> /// <param name="rom">rom对象</param>
/// <returns>此元组任意内任意成员都有可能为空</returns> /// <returns>此元组任意内任意成员都有可能为空</returns>
public GetFilterSetting_result 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;
// preset = filter.Presets.FirstOrDefault(p => p.Name == presetName);
//}
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, string presetName = value.presetName;
preset = preset preset = filter.Presets.FirstOrDefault(p => p.Name == presetName);
}; }
return (filter, preset);
} }
public struct GetFilterSetting_result public class Filter
{
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;
@ -242,8 +223,8 @@ namespace AxibugEmuOnline.Client
public string GetParamValueJson(string paramName) public string GetParamValueJson(string paramName)
{ {
prepareCache(); prepareCache();
string value;
m_paramName2ValueJson.TryGetValue(paramName, out value); m_paramName2ValueJson.TryGetValue(paramName, out var value);
return value; return value;
} }
@ -253,9 +234,8 @@ namespace AxibugEmuOnline.Client
if (rawStr == null) return null; if (rawStr == null) return null;
if (valueType == typeof(float)) if (valueType == typeof(float))
{ {
float floatVal; float.TryParse(rawStr, out var floatVal);
float.TryParse(rawStr, out floatVal);
return floatVal; return floatVal;
} }
else if (valueType.IsEnum) else if (valueType.IsEnum)
@ -329,13 +309,12 @@ namespace AxibugEmuOnline.Client
return JsonUtility.ToJson(this); return JsonUtility.ToJson(this);
} }
public ValueTuple<string,string> Get(RomFile rom) public (string filterName, string presetName) Get(RomFile rom)
{ {
prepareCache(); prepareCache();
Item item; m_cache.TryGetValue(rom.ID, out var item);
m_cache.TryGetValue(rom.ID, out item); return (item.FilterName, item.PresetName);
return new ValueTuple<string, string>(item.FilterName, item.PresetName);
} }
private void prepareCache() private void prepareCache()

View File

@ -5,7 +5,6 @@ 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
{ {
@ -96,11 +95,9 @@ 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));
var entry = zip.GetNextEntry() as ZipEntry; while (zip.GetNextEntry() is ZipEntry entry)
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,16 +154,14 @@ 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];
bool isNewUser; UpdateOrAddUser(mi, out 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);
bool isNewUser; UpdateOrAddUser(msg.UserInfo, out 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,10 +6,7 @@ public struct MsgBool
public string ErrorMsg; public string ErrorMsg;
public bool Value; public bool Value;
//low C# readonly public override readonly string ToString()
//public override readonly string ToString()
public override string ToString()
{ {
if (Value) if (Value)
{ {
@ -36,13 +33,12 @@ public struct MsgBool
return msgBool.Value; return msgBool.Value;
} }
//low C# 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();
} }

View File

@ -1,5 +1,4 @@
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;
@ -102,9 +101,8 @@ namespace AxibugEmuOnline.Client
public void SampleInput(uint frameIndex) public void SampleInput(uint frameIndex)
{ {
if (InGameUI.Instance.IsNetPlay) if (InGameUI.Instance.IsNetPlay)
{ {
int targetFrame; ReplayStep replayData; int frameDiff; bool inputDiff; if (App.roomMgr.netReplay.TryGetNextFrame((int)frameIndex, out var replayData, out int frameDiff, out bool inputDiff))
if (App.roomMgr.netReplay.TryGetNextFrame((int)frameIndex, out replayData, out frameDiff, out inputDiff))
{ {
if (inputDiff) if (inputDiff)
{ {
@ -114,7 +112,7 @@ namespace AxibugEmuOnline.Client
m_sampledState = FromNet(replayData); m_sampledState = FromNet(replayData);
} }
else m_sampledState = default(ControllerState); else m_sampledState = default;
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 Controller(0); public Controller Controller0 { get; } = new(0);
public Controller Controller1 { get; } = new Controller(1); public Controller Controller1 { get; } = new(1);
public Controller Controller2 { get; } = new Controller(2); public Controller Controller2 { get; } = new(2);
public Controller Controller3 { get; } = new Controller(3); public Controller Controller3 { get; } = new(3);
private readonly EnumButtonType[] m_states = new EnumButtonType[4]; private readonly EnumButtonType[] m_states = new EnumButtonType[4];
@ -137,10 +137,8 @@ namespace AxibugEmuOnline.Client
m_keyListener = Controller.GetKey(m_hostController.ControllerIndex, m_buttonType); m_keyListener = Controller.GetKey(m_hostController.ControllerIndex, m_buttonType);
} }
} }
//low C# readonly
//public readonly struct KeyListener
public struct KeyListener public readonly struct KeyListener
{ {
private readonly KeyCode m_key; private readonly KeyCode m_key;
@ -154,8 +152,7 @@ namespace AxibugEmuOnline.Client
{ {
m_key = KeyCode.None; m_key = KeyCode.None;
int result; if (int.TryParse(confStr, out int result))
if (int.TryParse(confStr, out result))
m_key = (KeyCode)result; m_key = (KeyCode)result;
} }
@ -223,7 +220,7 @@ namespace AxibugEmuOnline.Client
break; break;
} }
return default(KeyListener); return default;
} }
} }

View File

@ -2,19 +2,24 @@
%TAG !u! tag:unity3d.com,2011: %TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000 --- !u!21 &2100000
Material: Material:
serializedVersion: 6 serializedVersion: 8
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInternal: {fileID: 0} m_PrefabInstance: {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_ShaderKeywords: m_Parent: {fileID: 0}
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:
@ -58,6 +63,7 @@ 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
@ -85,3 +91,5 @@ 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<ValueTuple<int, int, byte[]>> queueNetMsg = new Queue<ValueTuple<int, int, byte[]>>(); private Queue<(int, int, byte[])> queueNetMsg = new Queue<(int, int, byte[])>();
private NetMsg() { } private NetMsg() { }
@ -66,7 +66,7 @@ namespace AxibugEmuOnline.Client.Network
{ {
lock (lockQueueObj) lock (lockQueueObj)
{ {
queueNetMsg.Enqueue(new ValueTuple<int,int,byte[]>(cmd, ERRCODE, arg)); queueNetMsg.Enqueue((cmd, ERRCODE, arg));
} }
} }
@ -76,8 +76,7 @@ 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 && ((ThirdMenuRoot)data).SelectIndex == Index); SetSelectState(data is ThirdMenuRoot tr && tr.SelectIndex == Index);
} }
public void Release() public void Release()

View File

@ -7,192 +7,191 @@ 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)));
public void SetData(object data) OverlayManager.PopSideBar(opts, onClose: () =>
{ {
Datacontext = data as Filter; App.filter.EnableFilterPreview();
Datacontext.ResetPreset();
UpdateView(); App.filter.EnableFilter(Datacontext);
} });
}
private void UpdateView() return false;
{ }
if (Datacontext == null)
SetBaseInfo("无", null, null);
else public class Opt_CreatePreset : ExecuteMenu
SetBaseInfo(Datacontext.Name, $"参数数量:{Datacontext.Paramerters.Count}", null); {
} private Filter m_filter;
public void SetDependencyProperty(object data) public Opt_CreatePreset(Filter filter) : base("创建滤镜预设", Resources.LoadAll<Sprite>("Icons/XMB-Icons/misc")[0])
{ {
SetSelectState(data is ThirdMenuRoot && ((ThirdMenuRoot)data).SelectIndex == Index); m_filter = filter;
}
if (m_select)
{ public override void OnFocus()
App.filter.EnableFilterPreview(); {
if (App.filter != null) m_filter.ResetPreset();
App.filter.EnableFilter(Datacontext); App.filter.EnableFilter(m_filter);
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 (Datacontext != null && Datacontext.Paramerters.Count > 0) if (!result) OverlayManager.PopTip(result);
{ else optionUI.AddOptionMenuWhenPoping(new Opt_Presets(m_filter, newPreset));
var opts = new List<OptionMenu>(); }, "为预设设置一个名称", string.Empty);
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;
App.filter.EnableFilterPreview(); private FilterPreset m_preset;
Datacontext.ResetPreset(); private OptionUI_MenuItem m_ui;
App.filter.EnableFilter(Datacontext); private List<OptionMenu> m_menu;
});
} public Opt_Presets(Filter filter, FilterPreset preset) : base(preset.Name, null)
return false; {
} m_filter = filter;
m_preset = preset;
public class Opt_CreatePreset : ExecuteMenu m_menu = new List<OptionMenu>();
{ m_menu.Add(new Opt_Delete(m_filter, m_preset));
private Filter m_filter; foreach (var p in m_filter.Paramerters)
{
public Opt_CreatePreset(Filter filter) : base("创建滤镜预设", Resources.LoadAll<Sprite>("Icons/XMB-Icons/misc")[0]) m_menu.Add(new Opt_ParamEditor(m_filter, p, m_preset));
{ }
m_filter = filter; }
}
public override void OnShow(OptionUI_MenuItem ui)
public override void OnFocus() {
{ EventInvoker.OnFilterPresetRemoved += EventInvoker_OnFilterPresetRemoved;
m_filter.ResetPreset(); m_ui = ui;
App.filter.EnableFilter(m_filter); base.OnShow(ui);
} }
public override void OnExcute(OptionUI optionUI, ref bool cancelHide) public override void OnHide()
{ {
cancelHide = true; EventInvoker.OnFilterPresetRemoved -= EventInvoker_OnFilterPresetRemoved;
}
OverlayManager.Input((presetName) =>
{ private void EventInvoker_OnFilterPresetRemoved(Filter filter, FilterPreset removedPreset)
FilterPreset newPreset; {
var result = m_filter.CreatePreset(presetName, out newPreset); if (filter != m_filter || m_preset != removedPreset) return;
if (!result) OverlayManager.PopTip(result); m_ui.OptionUI.RemoveItem(m_ui);
else optionUI.AddOptionMenuWhenPoping(new Opt_Presets(m_filter, newPreset)); }
}, "为预设设置一个名称", string.Empty);
} public override void OnFocus()
} {
public class Opt_Presets : ExpandMenu m_filter.ApplyPreset(m_preset);
{ App.filter.EnableFilter(m_filter);
private Filter m_filter; }
private FilterPreset m_preset;
private OptionUI_MenuItem m_ui; protected override List<OptionMenu> GetOptionMenus()
private List<OptionMenu> m_menu; {
return m_menu;
public Opt_Presets(Filter filter, FilterPreset preset) : base(preset.Name, null) }
{
m_filter = filter; public class Opt_ParamEditor : ValueSetMenu
m_preset = preset; {
private Filter m_filter;
m_menu = new List<OptionMenu>(); private FilterEffect.EditableParamerter m_param;
m_menu.Add(new Opt_Delete(m_filter, m_preset)); private FilterPreset 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)
{
public override void OnShow(OptionUI_MenuItem ui) m_filter = filter;
{ m_param = editParam;
EventInvoker.OnFilterPresetRemoved += EventInvoker_OnFilterPresetRemoved; m_preset = preset;
m_ui = ui; }
base.OnShow(ui);
} public override Type ValueType => m_param.ValueType;
public override void OnHide() public override object ValueRaw => m_preset.GetParamValue(m_param.Name, ValueType) ?? m_param.Value;
{
EventInvoker.OnFilterPresetRemoved -= EventInvoker_OnFilterPresetRemoved; public override void OnValueChanged(object newValue)
} {
m_preset.SetParamValue(m_param.Name, ValueType, newValue);
private void EventInvoker_OnFilterPresetRemoved(Filter filter, FilterPreset removedPreset) m_filter.SavePresets();
{ 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 void OnFocus() public override object Max => m_param.MaxValue;
{ }
m_filter.ApplyPreset(m_preset);
App.filter.EnableFilter(m_filter); public class Opt_Delete : ExecuteMenu
} {
private Filter m_filter;
protected override List<OptionMenu> GetOptionMenus() private FilterPreset m_preset;
{
return m_menu; public Opt_Delete(Filter filter, FilterPreset preset) : base("删除预设", null)
} {
m_filter = filter;
public class Opt_ParamEditor : ValueSetMenu m_preset = preset;
{ }
private Filter m_filter;
private FilterEffect.EditableParamerter m_param; public override void OnExcute(OptionUI optionUI, ref bool cancelHide)
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 && ((ThirdMenuRoot)data).SelectIndex == Index); SetSelectState(data is ThirdMenuRoot tr && tr.SelectIndex == Index);
} }
public void SetDependencyProperty(object data) public void SetDependencyProperty(object data)
{ {
SetSelectState(data is ThirdMenuRoot && ((ThirdMenuRoot)data).SelectIndex == Index); SetSelectState(data is ThirdMenuRoot tr && tr.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 List<OptionMenu>(); private readonly List<OptionMenu> menus = new();
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,11 +1,14 @@
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,10 +39,8 @@ public static class GameObjectPool
public static void Release(GameObject instance) public static void Release(GameObject instance)
{ {
GameObject src; s_instanceToSrc.TryGetValue(instance, out var src);
Queue<GameObject> pool; if (src != null && s_poolMap.TryGetValue(src, out var 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,10 +480,9 @@ public class ItemPresent : GridLayoutGroup, IVirtualLayout
if (_dataList != null) if (_dataList != null)
_dataList.Clear(); _dataList.Clear();
} }
else if (dataList is IEnumerable) else if (dataList is IEnumerable ienumrable)
{ {
var ienumrable = (IEnumerable)dataList; List<object> temp = new List<object>();
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,245 +6,240 @@ using UnityEngine.UI;
public interface IVirtualLayout public interface IVirtualLayout
{ {
Dictionary<GameObject, ScripteInterface> CacheItemScripts { get; } Dictionary<GameObject, ScripteInterface> CacheItemScripts { get; }
List<object> DataList { get; } public List<object> DataList { get; }
object DependencyProperty { get; } public object DependencyProperty { get; }
RectTransform RectTransform { get; } public RectTransform RectTransform { get; }
RectTransform GetTemplate(object data); public RectTransform GetTemplate(object data);
Vector2 GetItemAnchorePos(int index); public Vector2 GetItemAnchorePos(int index);
RectTransform GetItemUIIfExist(int index); public RectTransform GetItemUIIfExist(int index);
void UpdateProxyVisualState(); public void UpdateProxyVisualState();
void UpdateDependencyProperty(object dp); public void UpdateDependencyProperty(object dp);
void SetData(object dataList); public void SetData(object dataList);
void MoveToScrollViewCenter(ScrollRect scrollRect, int dataIndex); public 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;
ScripteInterface lfi; _parent.CacheItemScripts.TryGetValue(_runtimeInstance.gameObject, out ScripteInterface lfi);
_parent.CacheItemScripts.TryGetValue(_runtimeInstance.gameObject, out lfi); return lfi;
}
return lfi; public ItemProxy(IVirtualLayout parent)
} {
_parent = parent;
}
public ItemProxy(IVirtualLayout parent) public void Dispose()
{ {
_parent = parent; if (_runtimeInstance != null)
} {
if (Application.isPlaying)
{
GameObjectPool.Release(_runtimeInstance.gameObject);
}
else
GameObject.DestroyImmediate(_runtimeInstance.gameObject);
}
}
public void Dispose() public bool NeedShow
{ {
if (_runtimeInstance != null) get
{ {
if (Application.isPlaying) if (IsInViewRect && _runtimeInstance == null) return true;
{ else
GameObjectPool.Release(_runtimeInstance.gameObject); {
} if (_runtimeInstance != null && IsInViewRect && _runtimeInstance.anchoredPosition != AnchoredPosition)
else return true;
GameObject.DestroyImmediate(_runtimeInstance.gameObject); else
} 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();
}
public void UpdateView(bool force = false) UpdateLayout();
{ }
if (IsInViewRect) else
{ {
if (_runtimeInstance == null) ReleaseInstance();
{ }
_runtimeInstance = GetInstance(); }
_layoutElement = _runtimeInstance.GetComponent<LayoutGroup>();
UpdateViewData();
}
else if (force)
{
UpdateViewData();
}
UpdateLayout(); public void UpdateLayout()
} {
else if (_runtimeInstance != null)
{ {
ReleaseInstance(); _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();
}
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;
}
private void UpdateViewData() _parent.CacheItemScripts.TryGetValue(_runtimeInstance.gameObject, out ScripteInterface si);
{ si.SetDataList(_parent.DataList[Index], Index);
if (Application.isPlaying) if (_parent.DependencyProperty != null)
{ 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;
}
ScripteInterface si; public void UpdateDP()
{
if (_runtimeInstance == null) return;
_parent.CacheItemScripts.TryGetValue(_runtimeInstance.gameObject, out si); _parent.CacheItemScripts.TryGetValue(_runtimeInstance.gameObject, out ScripteInterface luaInterface);
si.SetDataList(_parent.DataList[Index], Index); if (luaInterface == null) return;
if (_parent.DependencyProperty != null)
si.SetDependencyProperty(_parent.DependencyProperty);
}
}
public void UpdateDP() if (_parent.DependencyProperty != null)
{ luaInterface.SetDependencyProperty(_parent.DependencyProperty);
if (_runtimeInstance == null) return; }
ScripteInterface luaInterface;
_parent.CacheItemScripts.TryGetValue(_runtimeInstance.gameObject, out luaInterface);
if (luaInterface == null) return;
if (_parent.DependencyProperty != null) private RectTransform GetInstance()
luaInterface.SetDependencyProperty(_parent.DependencyProperty); {
} var res = GameObjectPool.GetInstance(_template.gameObject, _parent.RectTransform).GetComponent<RectTransform>();
return res;
}
private RectTransform GetInstance() private void ReleaseInstance()
{ {
var res = GameObjectPool.GetInstance(_template.gameObject, _parent.RectTransform).GetComponent<RectTransform>(); if (_runtimeInstance == null) return;
return res;
}
private void ReleaseInstance() _layoutElement = null;
{
if (_runtimeInstance == null) return;
_layoutElement = null; if (Application.isPlaying)
{
if (Application.isPlaying) _parent.CacheItemScripts.TryGetValue(_runtimeInstance.gameObject, out ScripteInterface si);
{ if (si != null) si.Release();
ScripteInterface si; GameObjectPool.Release(_runtimeInstance.gameObject);
_parent.CacheItemScripts.TryGetValue(_runtimeInstance.gameObject, out si); _runtimeInstance = null;
if (si != null) si.Release(); }
GameObjectPool.Release(_runtimeInstance.gameObject); else
_runtimeInstance = null; {
} GameObject.DestroyImmediate(_runtimeInstance.gameObject);
else _runtimeInstance = null;
{ }
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,18 +269,16 @@ namespace AxibugEmuOnline.Client
private void CreateRuntimeMenuItem(OptionMenu menuData) private void CreateRuntimeMenuItem(OptionMenu menuData)
{ {
if (menuData is ExecuteMenu) if (menuData is ExecuteMenu executeMenu)
{ {
ExecuteMenu executeMenu = (ExecuteMenu)menuData; var menuUI = Instantiate(TEMPLATE_EXECUTEITEM.gameObject, TEMPLATE_EXECUTEITEM.transform.parent).GetComponent<OptionUI_ExecuteItem>();
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) else if (menuData is ValueSetMenu valueSetMenu)
{ {
var valueSetMenu = (ValueSetMenu)menuData; var menuUI = Instantiate(TEMPLATE_VALUEEDITITEM.gameObject, TEMPLATE_VALUEEDITITEM.transform.parent).GetComponent<OptionUI_ValueEditItem>();
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,10 +17,9 @@ 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) if (menuData is ValueSetMenu valueMenu)
{ {
var valueMenu = (ValueSetMenu)menuData; if (valueMenu.ValueType == typeof(float))
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)
{ {
ValueTuple<Action<string>, string, string> t = (ValueTuple<Action<string>, string, string>)param; (Action<string> callback, string placeHolder, string defaultText) t = ((Action<string> callback, string placeHolder, string defaultText))param;
OnCommit = t.Item1; OnCommit = t.callback;
(m_input.placeholder as Text).text = t.Item2; (m_input.placeholder as Text).text = t.placeHolder;
m_input.text = t.Item3; m_input.text = t.defaultText;
} }
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(new ValueTuple<Action<string>, string, string>(callback, placeHolder, defaultText)); s_ins.m_InputUI.Show((callback, placeHolder, defaultText));
return s_ins.m_InputUI; return s_ins.m_InputUI;
} }

View File

@ -9,136 +9,132 @@ 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;
Protobuf_Room_MiniInfo roomInfo; if (App.roomMgr.GetRoomListMiniInfo(roomID, out var roomInfo))
if (App.roomMgr.GetRoomListMiniInfo(roomID, out roomInfo)) UpdateUI(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
{ {
Protobuf_Room_MiniInfo MiniInfo; if (!App.roomMgr.GetRoomListMiniInfo(RoomID, out Protobuf_Room_MiniInfo MiniInfo))
if (!App.roomMgr.GetRoomListMiniInfo(RoomID, out MiniInfo)) {
{ OverlayManager.PopTip("房间不存在");
OverlayManager.PopTip("房间不存在"); return false;
return false; }
}
int[] freeSlots;
if (!MiniInfo.GetFreeSlot(out freeSlots))
{
OverlayManager.PopTip("无空闲位置");
return false;
}
App.roomMgr.SendJoinRoom(RoomID); if (!MiniInfo.GetFreeSlot(out var freeSlots))
return true; {
} OverlayManager.PopTip("无空闲位置");
} return false;
}
private void UpdateUI(Protobuf_Room_MiniInfo roomInfo) App.roomMgr.SendJoinRoom(RoomID);
{ return true;
var hostNick = roomInfo.GetHostNickName(); }
int cur; int max; }
roomInfo.GetRoomPlayers(out cur, out max); private void UpdateUI(Protobuf_Room_MiniInfo roomInfo)
SetBaseInfo("--", $"<b>{hostNick}</b>的房间", $"{cur}/{max}"); {
SetIcon(null); var hostNick = roomInfo.GetHostNickName();
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 && ((ThirdMenuRoot)data).SelectIndex == Index)); SetSelectState(data is ThirdMenuRoot tr && tr.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,10 +184,6 @@ 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>();
@ -201,17 +197,8 @@ namespace AxibugEmuOnline.Client
return clone.GetComponent<MenuItem>(); return clone.GetComponent<MenuItem>();
} }
#else #else
var item = GameObject.Instantiate(template.gameObject, parent).GetComponent<MenuItem>(); return GameObject.Instantiate(SubMenuItemTemplate.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,8 +9,7 @@ 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)
{ {
Material material; if (_caches.TryGetValue(graphic, out var material))
if (_caches.TryGetValue(graphic, out material))
{ {
return material; return material;
} }

View File

@ -34,10 +34,7 @@ public class XMBInfoBar : MonoBehaviour
RefreshFps(); RefreshFps();
} }
/// <summary> (uint lastFrame, float lastTime) m_lastFrameInfo;
/// (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())
@ -45,18 +42,14 @@ 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 gap = App.emu.Core.Frame - m_lastFrameInfo.Item1; var fps = gap / time;
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,9 +36,7 @@ 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)
{ {
RomFile romFile; if (s_RomFileCahcesInRoomInfo.TryGetValue(roomInfo.GameRomID, out RomFile romFile))
if (s_RomFileCahcesInRoomInfo.TryGetValue(roomInfo.GameRomID, out romFile))
{ {
callback.Invoke(roomInfo, romFile); callback.Invoke(roomInfo, romFile);
return; return;
@ -48,11 +46,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;
} }