Mesen-X/GUI.NET/Controls/ctrlRecentGames.cs

344 lines
9.7 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using Mesen.GUI.Config;
using Mesen.GUI.Forms;
using Mesen.GUI.Controls;
namespace Mesen.GUI.Controls
{
public partial class ctrlRecentGames : BaseControl
{
private int _columnCount = 0;
private int _rowCount = 0;
private int _elementsPerPage = 0;
private bool _needResume = false;
private int _currentIndex = 0;
private List<RecentGameInfo> _recentGames = new List<RecentGameInfo>();
private List<ctrlRecentGame> _controls = new List<ctrlRecentGame>();
public delegate void RecentGameLoadedHandler(RecentGameInfo gameInfo);
public event RecentGameLoadedHandler OnRecentGameLoaded;
public new event MouseEventHandler MouseMove
{
add { this.tlpPreviousState.MouseMove += value; this.tlpTitle.MouseMove += value; }
remove { this.tlpPreviousState.MouseMove -= value; this.tlpTitle.MouseMove -= value; }
}
public new event EventHandler DoubleClick
{
add { this.tlpPreviousState.DoubleClick += value; this.tlpTitle.DoubleClick += value; }
remove { this.tlpPreviousState.DoubleClick -= value; this.tlpTitle.DoubleClick -= value; }
}
public ctrlRecentGames()
{
InitializeComponent();
if(IsDesignMode) {
return;
}
DoubleBuffered = true;
picPrevGame.Image.RotateFlip(RotateFlipType.RotateNoneFlipX);
ThemeHelper.ExcludeFromTheme(this);
}
private void InitGrid()
{
int columnCount = 1;
if(ClientSize.Width > 850 && ClientSize.Height > 850) {
columnCount = 3;
} else if(ClientSize.Width > 450 && ClientSize.Height > 450) {
columnCount = 2;
}
if(_recentGames.Count <= 1) {
columnCount = 1;
} else if(_recentGames.Count <= 4) {
columnCount = Math.Min(2, columnCount);
}
int elementsPerPage = columnCount * columnCount;
int rowCount = columnCount;
if(Mode != GameScreenMode.RecentGames) {
elementsPerPage = 12;
columnCount = 4;
rowCount = 3;
}
if(_columnCount == columnCount && _elementsPerPage == elementsPerPage && _rowCount == rowCount) {
return;
}
_columnCount = columnCount;
_rowCount = rowCount;
_elementsPerPage = elementsPerPage;
_controls = new List<ctrlRecentGame>();
tlpGrid.SuspendLayout();
tlpGrid.ColumnCount = _columnCount;
tlpGrid.RowCount = _rowCount;
tlpGrid.ColumnStyles.Clear();
tlpGrid.RowStyles.Clear();
tlpGrid.Controls.Clear();
for(int j = 0; j < _columnCount; j++) {
tlpGrid.RowStyles.Add(new RowStyle(SizeType.Percent, 100F / _columnCount));
tlpGrid.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F / _columnCount));
}
for(int j = 0; j < _rowCount; j++) {
for(int i = 0; i < _columnCount; i++) {
ctrlRecentGame ctrl = new ctrlRecentGame();
ctrl.OnRecentGameLoaded += RecentGameLoaded;
ctrl.Dock = DockStyle.Fill;
ctrl.Margin = new Padding(2);
tlpGrid.Controls.Add(ctrl, i, j);
_controls.Add(ctrl);
}
}
tlpGrid.ResumeLayout();
UpdateGameInfo();
picPrevGame.Visible = _recentGames.Count > _elementsPerPage;
picNextGame.Visible = _recentGames.Count > _elementsPerPage;
}
public int GameCount
{
get { return _recentGames.Count; }
}
public GameScreenMode Mode { get; private set; } = GameScreenMode.RecentGames;
private bool Pause()
{
if(!InteropEmu.IsPaused()) {
InteropEmu.Pause();
return true;
}
return false;
}
public void ShowScreen(GameScreenMode mode)
{
if(mode == GameScreenMode.RecentGames && ConfigManager.Config.PreferenceInfo.DisableGameSelectionScreen) {
this.Visible = false;
return;
} else if(mode != GameScreenMode.RecentGames && Mode == mode && this.Visible) {
this.Visible = false;
if(_needResume) {
InteropEmu.Resume();
}
return;
}
Mode = mode;
_recentGames = new List<RecentGameInfo>();
_currentIndex = 0;
if(mode == GameScreenMode.RecentGames) {
_needResume = false;
tlpTitle.Visible = false;
List<string> files = Directory.GetFiles(ConfigManager.RecentGamesFolder, "*.rgd").OrderByDescending((file) => new FileInfo(file).LastWriteTime).ToList();
for(int i = 0; i < files.Count && _recentGames.Count < 36; i++) {
_recentGames.Add(new RecentGameInfo() { FileName = files[i] });
}
} else {
if(!this.Visible) {
_needResume = Pause();
}
lblScreenTitle.Text = mode == GameScreenMode.LoadState ? ResourceHelper.GetMessage("LoadStateDialog") : ResourceHelper.GetMessage("SaveStateDialog");
tlpTitle.Visible = true;
string romName = InteropEmu.GetRomInfo().GetRomName();
for(int i = 0; i < (mode == GameScreenMode.LoadState ? 11 : 10); i++) {
_recentGames.Add(new RecentGameInfo() { FileName = Path.Combine(ConfigManager.SaveStateFolder, romName + "_" + (i + 1) + ".mst"), Name = i == 10 ? ResourceHelper.GetMessage("AutoSave") : ResourceHelper.GetMessage("SlotNumber", i+1), SaveSlot = (uint)i+1 });
}
if(mode == GameScreenMode.LoadState) {
_recentGames.Add(new RecentGameInfo() { FileName = Path.Combine(ConfigManager.RecentGamesFolder, romName + ".rgd"), Name = ResourceHelper.GetMessage("LastSession") });
}
}
InitGrid();
if(_recentGames.Count == 0) {
this.Visible = false;
tmrInput.Enabled = false;
} else {
UpdateGameInfo();
tmrInput.Enabled = true;
}
picPrevGame.Visible = _recentGames.Count > _elementsPerPage;
picNextGame.Visible = _recentGames.Count > _elementsPerPage;
this.Visible = true;
}
public void UpdateGameInfo()
{
int count = _recentGames.Count;
int pageStart = _currentIndex / _elementsPerPage * _elementsPerPage;
for(int i = 0; i < _elementsPerPage; i++) {
_controls[i].Mode = Mode;
_controls[i].RecentGame = count > pageStart + i ? _recentGames[pageStart + i] : null;
_controls[i].Highlight = (_currentIndex % _elementsPerPage) == i;
}
}
protected override void OnResize(EventArgs e)
{
if(Program.IsMono) {
//Fix resize issues
picNextGame.Dock = DockStyle.None;
picPrevGame.Dock = DockStyle.None;
picNextGame.Dock = DockStyle.Fill;
picPrevGame.Dock = DockStyle.Fill;
}
if(this._columnCount > 0) {
InitGrid();
}
base.OnResize(e);
}
private void picNextGame_MouseDown(object sender, MouseEventArgs e)
{
GoToNextPage();
}
private void picPrevGame_MouseDown(object sender, MouseEventArgs e)
{
GoToPreviousPage();
}
private void GoToPreviousPage()
{
if(_currentIndex < _elementsPerPage) {
_currentIndex = _recentGames.Count - 1;
} else {
_currentIndex -= _elementsPerPage;
}
UpdateGameInfo();
}
private bool IsOnLastPage { get { return (_currentIndex / _elementsPerPage) == ((_recentGames.Count - 1) / _elementsPerPage); } }
private void GoToNextPage()
{
if(_currentIndex + _elementsPerPage < _recentGames.Count) {
_currentIndex += _elementsPerPage;
} else {
_currentIndex = IsOnLastPage ? 0 : (_recentGames.Count - 1);
}
UpdateGameInfo();
}
private void RecentGameLoaded(RecentGameInfo gameInfo)
{
if(this.Mode == GameScreenMode.RecentGames) {
OnRecentGameLoaded?.Invoke(gameInfo);
}
if(this._needResume) {
InteropEmu.Resume();
}
this.Visible = false;
}
private bool _waitForRelease = false;
private void tmrInput_Tick(object sender, EventArgs e)
{
//Use player 1's controls to navigate the recent game selection screen
if(Application.OpenForms.Count > 0 && Application.OpenForms[0].ContainsFocus && this.Visible) {
if(Mode != GameScreenMode.RecentGames && !InteropEmu.IsPaused()) {
this.Visible = false;
return;
}
List<uint> keyCodes = InteropEmu.GetPressedKeys();
uint keyCode = keyCodes.Count > 0 ? keyCodes[0] : 0;
if(keyCode > 0) {
if(!_waitForRelease) {
foreach(KeyMappings mapping in ConfigManager.Config.InputInfo.Controllers[0].Keys) {
if(mapping.Left == keyCode) {
_waitForRelease = true;
if(_currentIndex == 0) {
_currentIndex = _recentGames.Count - 1;
} else {
_currentIndex--;
}
UpdateGameInfo();
} else if(mapping.Right == keyCode) {
_waitForRelease = true;
_currentIndex = (_currentIndex + 1) % _recentGames.Count;
UpdateGameInfo();
} else if(mapping.Down == keyCode) {
_waitForRelease = true;
if(_currentIndex + _columnCount < _recentGames.Count) {
_currentIndex += _columnCount;
} else {
_currentIndex = Math.Min(_currentIndex % _columnCount, _recentGames.Count - 1);
}
UpdateGameInfo();
} else if(mapping.Up == keyCode) {
_waitForRelease = true;
if(_currentIndex < _columnCount) {
_currentIndex = _recentGames.Count - (_columnCount - (_currentIndex % _columnCount));
} else {
_currentIndex -= _columnCount;
}
UpdateGameInfo();
} else if(mapping.A == keyCode || mapping.B == keyCode || mapping.Select == keyCode || mapping.Start == keyCode) {
_waitForRelease = true;
_controls[_currentIndex % _elementsPerPage].ProcessClick();
}
}
}
} else {
_waitForRelease = false;
}
}
}
private void picClose_Click(object sender, EventArgs e)
{
if(_needResume) {
InteropEmu.Resume();
}
this.Visible = false;
}
}
public class DBTableLayoutPanel : TableLayoutPanel
{
public DBTableLayoutPanel()
{
DoubleBuffered = true;
}
}
public class RecentGameInfo
{
public string FileName { get; set; }
public string Name { get; set; }
public uint SaveSlot { get; set; }
public ResourcePath RomPath { get; set; }
}
public enum GameScreenMode
{
RecentGames,
LoadState,
SaveState
}
}