diff --git a/GameLauncher.csproj b/GameLauncher.csproj index b187788..e69d6a5 100644 --- a/GameLauncher.csproj +++ b/GameLauncher.csproj @@ -27,7 +27,7 @@ Form - + Form diff --git a/Management.cs b/Management.cs index bb1f143..abb2493 100644 --- a/Management.cs +++ b/Management.cs @@ -23,7 +23,7 @@ internal static class Management public static readonly Version Version = Assembly.GetEntryAssembly()!.GetName().Version!; public static readonly string VersionString = Version.ToString(3); - public static readonly string ExecutablePath = Assembly.GetEntryAssembly()!.Location; + public static readonly string ExecutablePath = Environment.ProcessPath!; public static Config Config; public static bool IGDBViable => !string.IsNullOrEmpty(Config.IGDBId) && !string.IsNullOrEmpty(Config.IGDBSecret); public static event Action ThemeChange; diff --git a/Models/LocalGame.cs b/Models/LocalGame.cs index 02dd45f..dcb9893 100644 --- a/Models/LocalGame.cs +++ b/Models/LocalGame.cs @@ -39,6 +39,7 @@ public string GamePath private string launchPath; public string? CoverPath => this.coverPath; + public string GameMetadataPath => this.gameMetadataPath; public bool HasCover => this.CoverPath != null && File.Exists(this.CoverPath); public LocalGame(string filePath) @@ -151,18 +152,9 @@ public void LoadOrDownloadResources() if (game == null) { MessageBox.Show("Game not found on IGDB", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); - IGDBSearchResultsForm form = new(Path.GetFileName(this.GamePath)); - DialogResult result = form.ShowDialog(); - - if (result == DialogResult.OK && form.SelectedGame != null) - { - string newPath = $"{this.GamePath.TrimEnd('\\', '/')} [{form.SelectedGame.Id}]"; - Directory.Move(this.GamePath, newPath); - this.GamePath = newPath; - + if (MetadataOverrideForm.OverrideMetadata(this)) game = Management.IGDBObj.Search(Path.GetFileName(this.GamePath)) .FirstOrDefault(); - } else return; } diff --git a/Program.cs b/Program.cs index e713335..6096aa2 100644 --- a/Program.cs +++ b/Program.cs @@ -53,7 +53,7 @@ static void Main() //splashForm.Invoke(splashForm.Close); - Application.Run(new Form1()); + Application.Run(new MainForm()); } private static void UnhandledException(object sender, UnhandledExceptionEventArgs e) diff --git a/README.md b/README.md index 22dd930..51f39f5 100644 --- a/README.md +++ b/README.md @@ -11,16 +11,11 @@ ## To-do - [ ] Improve game automatic detection for launch.dat - [ ] Play time counter -- [ ] Make uninstall work - [ ] Save file management and quick swapping -- [ ] Add auto-updating - [ ] Possibly add game source providing -- [ ] Fix dir names feature - [ ] Note unrecognized games - [ ] Add splash screen -- [ ] Custom metadata override - - +- [ ] Fix dark mode ## Versions @@ -28,8 +23,7 @@ - [ ] Added auto-updating - [ ] Added custom metadata override -- [ ] Fixed dark theme -- [ ] Added game name cleanup +- [ ] Added game name matching ### Beta 1.4.8 diff --git a/UI/Controls/GamePanelControl.cs b/UI/Controls/GamePanelControl.cs index f6d4dc6..2a873ea 100644 --- a/UI/Controls/GamePanelControl.cs +++ b/UI/Controls/GamePanelControl.cs @@ -18,9 +18,9 @@ namespace GameLauncher public partial class GamePanelControl : UserControl, ITick { public LocalGame Game; - private Form1 originForm; + private MainForm originForm; private bool stillLoading = true; - public GamePanelControl(Form1 originForm, LocalGame game) + public GamePanelControl(MainForm originForm, LocalGame game) { this.originForm = originForm; this.Game = game; diff --git a/UI/Forms/IGDBSearchResultsForm.Designer.cs b/UI/Forms/IGDBSearchResultsForm.Designer.cs deleted file mode 100644 index 2b28325..0000000 --- a/UI/Forms/IGDBSearchResultsForm.Designer.cs +++ /dev/null @@ -1,118 +0,0 @@ -namespace GameLauncher.UI.Forms -{ - partial class IGDBSearchResultsForm - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - ResultBox = new ListBox(); - SearchBox = new TextBox(); - label1 = new Label(); - SelectButton = new Button(); - SearchButton = new Button(); - this.SuspendLayout(); - // - // ResultBox - // - ResultBox.FormattingEnabled = true; - ResultBox.ItemHeight = 32; - ResultBox.Location = new Point(22, 85); - ResultBox.Margin = new Padding(6, 6, 6, 6); - ResultBox.Name = "ResultBox"; - ResultBox.Size = new Size(615, 228); - ResultBox.TabIndex = 0; - // - // SearchBox - // - SearchBox.Location = new Point(154, 18); - SearchBox.Margin = new Padding(6, 6, 6, 6); - SearchBox.Name = "SearchBox"; - SearchBox.Size = new Size(335, 39); - SearchBox.TabIndex = 1; - SearchBox.KeyDown += this.SearchBox_KeyDown; - // - // label1 - // - label1.AutoSize = true; - label1.Location = new Point(15, 21); - label1.Margin = new Padding(6, 0, 6, 0); - label1.Name = "label1"; - label1.Size = new Size(131, 32); - label1.TabIndex = 2; - label1.Text = "Term or ID:"; - // - // SelectButton - // - SelectButton.Location = new Point(501, 331); - SelectButton.Margin = new Padding(6, 6, 6, 6); - SelectButton.Name = "SelectButton"; - SelectButton.Size = new Size(139, 49); - SelectButton.TabIndex = 3; - SelectButton.Text = "Select"; - SelectButton.UseVisualStyleBackColor = true; - SelectButton.Click += this.SelectButton_Click; - // - // SearchButton - // - SearchButton.Location = new Point(501, 13); - SearchButton.Margin = new Padding(6, 6, 6, 6); - SearchButton.Name = "SearchButton"; - SearchButton.Size = new Size(139, 49); - SearchButton.TabIndex = 4; - SearchButton.Text = "Search"; - SearchButton.UseVisualStyleBackColor = true; - SearchButton.Click += this.SearchButton_Click; - // - // IGDBSearchResultsForm - // - this.AutoScaleDimensions = new SizeF(13F, 32F); - this.AutoScaleMode = AutoScaleMode.Font; - this.ClientSize = new Size(652, 395); - this.Controls.Add(SearchButton); - this.Controls.Add(SelectButton); - this.Controls.Add(label1); - this.Controls.Add(SearchBox); - this.Controls.Add(ResultBox); - this.FormBorderStyle = FormBorderStyle.FixedDialog; - this.Margin = new Padding(6, 6, 6, 6); - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "IGDBSearchResultsForm"; - this.Text = "IGDB Search Results"; - this.Load += this.IGDBSearchResultsForm_Load; - this.ResumeLayout(false); - this.PerformLayout(); - } - - #endregion - - private ListBox ResultBox; - private TextBox SearchBox; - private Label label1; - private Button SelectButton; - private Button SearchButton; - } -} \ No newline at end of file diff --git a/UI/Forms/IGDBSearchResultsForm.cs b/UI/Forms/IGDBSearchResultsForm.cs deleted file mode 100644 index 7319d44..0000000 --- a/UI/Forms/IGDBSearchResultsForm.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; -using IGDB.Models; - -namespace GameLauncher.UI.Forms -{ - public partial class IGDBSearchResultsForm : Form - { - public Game? SelectedGame => this._results?.ElementAtOrDefault(this.ResultBox.SelectedIndex); - private string _initialResult; - private Game[]? _results; - public IGDBSearchResultsForm(string initialResult) - { - this._initialResult = initialResult; - this.DialogResult = DialogResult.Cancel; - InitializeComponent(); - } - - private void IGDBSearchResultsForm_Load(object sender, EventArgs e) - { - this.SearchBox.Text = this._initialResult; - this.PerformSearch(); - } - - private void SearchButton_Click(object? sender, EventArgs e) - { - PerformSearch(); - } - - private void PerformSearch() - { - this.SearchButton.Enabled = false; - this.SelectButton.Enabled = false; - string query = this.SearchBox.Text; - if (query.All(char.IsNumber)) - query = $"[{query}]"; - - Management.IGDBObj.SearchAsync(query, results => - { - this._results = results; - - this.Invoke(() => - { - this.ResultBox.BeginUpdate(); - this.ResultBox.Items.Clear(); - - // ReSharper disable once CoVariantArrayConversion - this.ResultBox.Items.AddRange(results.Select(x => x.Name).ToArray()); - - this.ResultBox.EndUpdate(); - - this.SearchButton.Enabled = true; - this.SelectButton.Enabled = true; - }); - }, 25); - } - - private void SelectButton_Click(object? sender, EventArgs e) - { - this.DialogResult = DialogResult.OK; - this.Close(); - } - - private void SearchBox_KeyDown(object sender, KeyEventArgs e) - { - if (e.KeyCode == Keys.Enter) - PerformSearch(); - } - } -} diff --git a/UI/Forms/Form1.Designer.cs b/UI/Forms/MainForm.Designer.cs similarity index 98% rename from UI/Forms/Form1.Designer.cs rename to UI/Forms/MainForm.Designer.cs index c54dda3..cf9e928 100644 --- a/UI/Forms/Form1.Designer.cs +++ b/UI/Forms/MainForm.Designer.cs @@ -1,6 +1,6 @@ namespace GameLauncher { - partial class Form1 + partial class MainForm { /// /// Required designer variable. @@ -29,7 +29,7 @@ protected override void Dispose(bool disposing) private void InitializeComponent() { this.components = new System.ComponentModel.Container(); - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1)); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); flowLayoutPanel1 = new FlowLayoutPanel(); contextMenuStrip1 = new ContextMenuStrip(this.components); addManuallyToolStripMenuItem = new ToolStripMenuItem(); @@ -109,7 +109,7 @@ private void InitializeComponent() this.Controls.Add(flowLayoutPanel1); this.Controls.Add(LoadingProgressBar); this.Icon = (Icon)resources.GetObject("$this.Icon"); - this.Name = "Form1"; + this.Name = "MainForm"; this.Text = "Game Launcher"; this.FormClosed += this.Form1_FormClosed; this.Load += this.Form1_Load; diff --git a/UI/Forms/Form1.cs b/UI/Forms/MainForm.cs similarity index 88% rename from UI/Forms/Form1.cs rename to UI/Forms/MainForm.cs index 9f8a370..38e677b 100644 --- a/UI/Forms/Form1.cs +++ b/UI/Forms/MainForm.cs @@ -8,14 +8,14 @@ namespace GameLauncher { - public partial class Form1 : Form + public partial class MainForm : Form { private static LocalGame[]? Games; private static Thread? ProcessMonitorThread; private static Thread? RichPresenceThread; - public Form1() + public MainForm() { this.InitializeComponent(); } @@ -183,9 +183,19 @@ public void CheckForUpdates(Action callback) Version newVer = GitHub.GetLatestVersion(); if (newVer > Management.Version) { - DialogResult result = MessageBox.Show($"New version available: {newVer}", "Update", MessageBoxButtons.YesNo, MessageBoxIcon.Information); - if (result == DialogResult.Yes) - GitHub.UpdateToVersion(newVer); + DialogResult result = MessageBox.Show($"New version is available: {newVer}\nWould you like to update?", "Update", MessageBoxButtons.YesNo, MessageBoxIcon.Information); + try + { + if (result == DialogResult.Yes) + GitHub.UpdateToVersion(newVer); + } + catch (Exception ex) + { + string backupFile = Path.Combine(Path.GetDirectoryName(Management.ExecutablePath), "GameLauncher.exe.bak"); + if (File.Exists(backupFile)) + File.Move(backupFile, Management.ExecutablePath); + MessageBox.Show($"Failed to update: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } callback(); } else diff --git a/UI/Forms/Form1.resx b/UI/Forms/MainForm.resx similarity index 100% rename from UI/Forms/Form1.resx rename to UI/Forms/MainForm.resx diff --git a/UI/Forms/MetadataOverrideForm.Designer.cs b/UI/Forms/MetadataOverrideForm.Designer.cs new file mode 100644 index 0000000..ee37eb3 --- /dev/null +++ b/UI/Forms/MetadataOverrideForm.Designer.cs @@ -0,0 +1,262 @@ +namespace GameLauncher.UI.Forms +{ + partial class MetadataOverrideForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + ResultBox = new ListBox(); + SearchBox = new TextBox(); + label1 = new Label(); + SelectButton = new Button(); + SearchButton = new Button(); + CustomMetadataButton = new Button(); + CustomOverridePanel = new Panel(); + ThumnailPathLabel = new Label(); + GenresBox = new TextBox(); + label5 = new Label(); + label4 = new Label(); + label3 = new Label(); + label2 = new Label(); + ChooseThumbnailButton = new Button(); + DescriptionBox = new RichTextBox(); + NameBox = new TextBox(); + UpdateDirNameBox = new CheckBox(); + CustomOverridePanel.SuspendLayout(); + this.SuspendLayout(); + // + // ResultBox + // + ResultBox.FormattingEnabled = true; + ResultBox.ItemHeight = 32; + ResultBox.Location = new Point(22, 85); + ResultBox.Margin = new Padding(6); + ResultBox.Name = "ResultBox"; + ResultBox.Size = new Size(615, 228); + ResultBox.TabIndex = 0; + // + // SearchBox + // + SearchBox.Location = new Point(154, 18); + SearchBox.Margin = new Padding(6); + SearchBox.Name = "SearchBox"; + SearchBox.Size = new Size(335, 39); + SearchBox.TabIndex = 1; + SearchBox.KeyDown += this.SearchBox_KeyDown; + // + // label1 + // + label1.AutoSize = true; + label1.Location = new Point(15, 21); + label1.Margin = new Padding(6, 0, 6, 0); + label1.Name = "label1"; + label1.Size = new Size(131, 32); + label1.TabIndex = 2; + label1.Text = "Term or ID:"; + // + // SelectButton + // + SelectButton.Location = new Point(501, 331); + SelectButton.Margin = new Padding(6); + SelectButton.Name = "SelectButton"; + SelectButton.Size = new Size(139, 49); + SelectButton.TabIndex = 3; + SelectButton.Text = "Select"; + SelectButton.UseVisualStyleBackColor = true; + SelectButton.Click += this.SelectButton_Click; + // + // SearchButton + // + SearchButton.Location = new Point(501, 13); + SearchButton.Margin = new Padding(6); + SearchButton.Name = "SearchButton"; + SearchButton.Size = new Size(139, 49); + SearchButton.TabIndex = 4; + SearchButton.Text = "Search"; + SearchButton.UseVisualStyleBackColor = true; + SearchButton.Click += this.SearchButton_Click; + // + // CustomMetadataButton + // + CustomMetadataButton.Location = new Point(339, 332); + CustomMetadataButton.Name = "CustomMetadataButton"; + CustomMetadataButton.Size = new Size(150, 46); + CustomMetadataButton.TabIndex = 5; + CustomMetadataButton.Text = "Custom"; + CustomMetadataButton.UseVisualStyleBackColor = true; + CustomMetadataButton.Click += this.CustomMetadataButton_Click; + // + // CustomOverridePanel + // + CustomOverridePanel.Controls.Add(ThumnailPathLabel); + CustomOverridePanel.Controls.Add(GenresBox); + CustomOverridePanel.Controls.Add(label5); + CustomOverridePanel.Controls.Add(label4); + CustomOverridePanel.Controls.Add(label3); + CustomOverridePanel.Controls.Add(label2); + CustomOverridePanel.Controls.Add(ChooseThumbnailButton); + CustomOverridePanel.Controls.Add(DescriptionBox); + CustomOverridePanel.Controls.Add(NameBox); + CustomOverridePanel.Location = new Point(22, 12); + CustomOverridePanel.Name = "CustomOverridePanel"; + CustomOverridePanel.Size = new Size(615, 301); + CustomOverridePanel.TabIndex = 6; + CustomOverridePanel.Visible = false; + // + // ThumnailPathLabel + // + ThumnailPathLabel.Font = new Font("Segoe UI", 5F, FontStyle.Regular, GraphicsUnit.Point); + ThumnailPathLabel.Location = new Point(322, 252); + ThumnailPathLabel.Name = "ThumnailPathLabel"; + ThumnailPathLabel.Size = new Size(276, 32); + ThumnailPathLabel.TabIndex = 8; + ThumnailPathLabel.TextAlign = ContentAlignment.MiddleLeft; + // + // GenresBox + // + GenresBox.Location = new Point(166, 189); + GenresBox.Name = "GenresBox"; + GenresBox.Size = new Size(432, 39); + GenresBox.TabIndex = 7; + // + // label5 + // + label5.AutoSize = true; + label5.Location = new Point(20, 251); + label5.Name = "label5"; + label5.Size = new Size(133, 32); + label5.TabIndex = 6; + label5.Text = "Thumbnail:"; + // + // label4 + // + label4.AutoSize = true; + label4.Location = new Point(20, 192); + label4.Name = "label4"; + label4.Size = new Size(93, 32); + label4.TabIndex = 5; + label4.Text = "Genres:"; + // + // label3 + // + label3.AutoSize = true; + label3.Location = new Point(20, 76); + label3.Name = "label3"; + label3.Size = new Size(140, 32); + label3.TabIndex = 4; + label3.Text = "Description:"; + // + // label2 + // + label2.AutoSize = true; + label2.Location = new Point(20, 20); + label2.Name = "label2"; + label2.Size = new Size(90, 32); + label2.TabIndex = 3; + label2.Text = "Name: "; + // + // ChooseThumbnailButton + // + ChooseThumbnailButton.Location = new Point(166, 245); + ChooseThumbnailButton.Name = "ChooseThumbnailButton"; + ChooseThumbnailButton.Size = new Size(150, 46); + ChooseThumbnailButton.TabIndex = 2; + ChooseThumbnailButton.Text = "Select"; + ChooseThumbnailButton.UseVisualStyleBackColor = true; + // + // DescriptionBox + // + DescriptionBox.BorderStyle = BorderStyle.FixedSingle; + DescriptionBox.Location = new Point(166, 73); + DescriptionBox.Name = "DescriptionBox"; + DescriptionBox.Size = new Size(432, 104); + DescriptionBox.TabIndex = 1; + DescriptionBox.Text = ""; + // + // NameBox + // + NameBox.Location = new Point(166, 18); + NameBox.Name = "NameBox"; + NameBox.Size = new Size(432, 39); + NameBox.TabIndex = 0; + // + // UpdateDirNameBox + // + UpdateDirNameBox.AutoSize = true; + UpdateDirNameBox.Location = new Point(23, 338); + UpdateDirNameBox.Name = "UpdateDirNameBox"; + UpdateDirNameBox.Size = new Size(291, 36); + UpdateDirNameBox.TabIndex = 7; + UpdateDirNameBox.Text = "Update directory name"; + UpdateDirNameBox.UseVisualStyleBackColor = true; + // + // MetadataOverrideForm + // + this.AutoScaleDimensions = new SizeF(13F, 32F); + this.AutoScaleMode = AutoScaleMode.Font; + this.ClientSize = new Size(652, 395); + this.Controls.Add(UpdateDirNameBox); + this.Controls.Add(CustomOverridePanel); + this.Controls.Add(CustomMetadataButton); + this.Controls.Add(SearchButton); + this.Controls.Add(SelectButton); + this.Controls.Add(label1); + this.Controls.Add(SearchBox); + this.Controls.Add(ResultBox); + this.FormBorderStyle = FormBorderStyle.FixedDialog; + this.Margin = new Padding(6); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MetadataOverrideForm"; + this.Text = "Metadata Override"; + this.Load += this.IGDBSearchResultsForm_Load; + CustomOverridePanel.ResumeLayout(false); + CustomOverridePanel.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + } + + #endregion + + private ListBox ResultBox; + private TextBox SearchBox; + private Label label1; + private Button SelectButton; + private Button SearchButton; + private Button CustomMetadataButton; + private Panel CustomOverridePanel; + private Label label4; + private Label label3; + private Label label2; + private Button ChooseThumbnailButton; + private RichTextBox DescriptionBox; + private TextBox NameBox; + private TextBox GenresBox; + private Label label5; + private Label ThumnailPathLabel; + private CheckBox UpdateDirNameBox; + } +} \ No newline at end of file diff --git a/UI/Forms/MetadataOverrideForm.cs b/UI/Forms/MetadataOverrideForm.cs new file mode 100644 index 0000000..23b37a6 --- /dev/null +++ b/UI/Forms/MetadataOverrideForm.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Net; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Windows.Forms; +using GameLauncher.Connections; +using GameLauncher.Utils; +using IGDB.Models; + +namespace GameLauncher.UI.Forms +{ + public partial class MetadataOverrideForm : Form + { + public Game? SelectedGame => this._results?.ElementAtOrDefault(this.ResultBox.SelectedIndex); + private string _initialResult; + private Game[]? _results; + private bool inCustomMode => CustomOverridePanel.Visible; + public MetadataOverrideForm(string initialResult, LocalGame? oldGame = null) + { + this._initialResult = initialResult; + + InitializeComponent(); + + this.NameBox.Text = initialResult; + this.DialogResult = DialogResult.Cancel; + + if (oldGame != null) + { + this.NameBox.Text = oldGame.Name ?? initialResult; + this.DescriptionBox.Text = oldGame.Summary ?? ""; + this.GenresBox.Text = oldGame.Genres ?? ""; + this.ThumnailPathLabel.Text = oldGame.CoverUrl ?? "No cover"; + } + } + + private void IGDBSearchResultsForm_Load(object sender, EventArgs e) + { + this.SearchBox.Text = this._initialResult; + this.PerformSearch(); + } + + private void SearchButton_Click(object? sender, EventArgs e) + { + PerformSearch(); + } + + private void PerformSearch() + { + this.SearchButton.Enabled = false; + this.SelectButton.Enabled = false; + string query = this.SearchBox.Text; + if (query.All(char.IsNumber)) + query = $"[{query}]"; + + Management.IGDBObj.SearchAsync(query, results => + { + this._results = results; + + this.Invoke(() => + { + this.ResultBox.BeginUpdate(); + this.ResultBox.Items.Clear(); + + // ReSharper disable once CoVariantArrayConversion + this.ResultBox.Items.AddRange(results.Select(x => x.Name).ToArray()); + + this.ResultBox.EndUpdate(); + + this.SearchButton.Enabled = true; + this.SelectButton.Enabled = true; + }); + }, 25); + } + + private void SelectButton_Click(object? sender, EventArgs e) + { + this.DialogResult = DialogResult.OK; + this.Close(); + } + + private void SearchBox_KeyDown(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Enter) + PerformSearch(); + } + + private void CustomMetadataButton_Click(object sender, EventArgs e) + { + CustomOverridePanel.Visible = !CustomOverridePanel.Visible; + CustomMetadataButton.Text = inCustomMode ? "IGDB Search" : "Custom"; + } + + public static bool OverrideMetadata(LocalGame game) + { + MetadataOverrideForm form = new(game.Name, game); + DialogResult result = form.ShowDialog(); + + if (result != DialogResult.OK) return false; + + if (form.inCustomMode) + { + // Download image as cover. + + WebClient client = new(); + byte[] imageBytes = client.DownloadData(form.ThumnailPathLabel.Text); + File.WriteAllBytes(game.CoverPath, imageBytes); + + game.GameMetaData = new() + { + { "name", form.NameBox.Text }, + { "genres", form.GenresBox.Text }, + { "summary", form.DescriptionBox.Text }, + { "cover_url", form.ThumnailPathLabel.Text } + }; + + DatFile.Save(game.GameMetadataPath, game.GameMetaData); + + if (form.UpdateDirNameBox.Checked) + { + // change folder name to match the game name. + string dir = Path.GetDirectoryName(game.GamePath)!; + + string newGamePath = Path.Join(dir, game.Name.CleanFileName()); + Directory.Move(game.GamePath, newGamePath); + game.GamePath = newGamePath; + } + } + else + { + Game? selectedGame = form.SelectedGame; + if (selectedGame == null) return false; + + string dir = Path.GetDirectoryName(game.GamePath)!; + string name = Path.GetFileName(game.GamePath); + if (form.UpdateDirNameBox.Checked) + name = selectedGame.Name; + + name = Regex.Replace(name, @"\[(\d+)\]", ""); + name = $"{name.TrimEnd()} [{selectedGame.Id}]"; + + string newPath = Path.Join(dir, name.CleanFileName()); + Directory.Move(game.GamePath, newPath); + game.GamePath = newPath; + } + + return true; + } + } +} diff --git a/UI/Forms/IGDBSearchResultsForm.resx b/UI/Forms/MetadataOverrideForm.resx similarity index 100% rename from UI/Forms/IGDBSearchResultsForm.resx rename to UI/Forms/MetadataOverrideForm.resx diff --git a/UI/Pages/GameDetailsPage.cs b/UI/Pages/GameDetailsPage.cs index f22d756..3ccdaea 100644 --- a/UI/Pages/GameDetailsPage.cs +++ b/UI/Pages/GameDetailsPage.cs @@ -16,7 +16,7 @@ namespace GameLauncher { public partial class GameDetailsControl : UserControl, ITick { - public Form1? MainForm; + public MainForm? MainForm; private LocalGame game; public GameDetailsControl(LocalGame game) { @@ -34,7 +34,7 @@ private void ExpandButton_Click(object sender, EventArgs e) private void GameDetailsControl_Load(object sender, EventArgs e) { - this.MainForm = (this.ParentForm as Form1)!; + this.MainForm = (this.ParentForm as MainForm)!; this.UpdateUIFromMetadata(); @@ -126,20 +126,8 @@ private void uninstallToolStripMenuItem_Click(object sender, EventArgs e) private void overrideMetadataToolStripMenuItem_Click(object sender, EventArgs e) { - IGDBSearchResultsForm form = new(Path.GetFileName(this.game.GamePath)); - DialogResult result = form.ShowDialog(); - - if (result == DialogResult.OK && form.SelectedGame != null) + if (MetadataOverrideForm.OverrideMetadata(this.game)) { - string dir = Path.GetDirectoryName(this.game.GamePath); - string name = Path.GetFileName(this.game.GamePath); - name = Regex.Replace(name, @"\[(\d+)\]", ""); - name = $"{name.TrimEnd()} [{form.SelectedGame.Id}]"; - - string newPath = Path.Join(dir, name); - Directory.Move(this.game.GamePath, newPath); - this.game.GamePath = newPath; - this.RefreshMetadata(); this.UpdateUIFromMetadata(); } diff --git a/UI/Pages/SettingsPage.cs b/UI/Pages/SettingsPage.cs index a634e33..5d31ba8 100644 --- a/UI/Pages/SettingsPage.cs +++ b/UI/Pages/SettingsPage.cs @@ -13,7 +13,7 @@ namespace GameLauncher { public partial class SettingsPage : UserControl { - public Form1? MainForm; + public MainForm? MainForm; public SettingsPage() { this.InitializeComponent(); @@ -21,7 +21,7 @@ public SettingsPage() private void SettingsPage_Load(object sender, EventArgs e) { - this.MainForm = (this.ParentForm as Form1)!; + this.MainForm = (this.ParentForm as MainForm)!; Dictionary settings = new(); settings.Add("Add custom game", new Action(this.MainForm.AddGameManually)); diff --git a/Utils/Extensions.cs b/Utils/Extensions.cs index 19f4f10..d37049f 100644 --- a/Utils/Extensions.cs +++ b/Utils/Extensions.cs @@ -105,5 +105,10 @@ public static Color GetColor(this LauncherTheme theme, LauncherThemeKey key) } };; } + + public static string CleanFileName(this string fileName) + { + return Path.GetInvalidFileNameChars().Aggregate(fileName, (current, c) => current.Replace(c.ToString(), string.Empty)); + } } }