From 81d6bb407a1888de4867e6a1fd8a700d6c700754 Mon Sep 17 00:00:00 2001 From: TenebrisNoctua <172976441+TenebrisNoctua@users.noreply.github.com> Date: Thu, 10 Sep 2026 23:29:06 +0300 Subject: [PATCH 1/6] Replace Forms with WinUI --- ProjectSrc/App.config | 11 - ProjectSrc/Bootstrapper/StudioBootstrapper.cs | 33 +- ProjectSrc/FodyWeavers.xml | 5 - ProjectSrc/Forms/BootstrapperForm.Designer.cs | 139 ---- ProjectSrc/Forms/BootstrapperForm.cs | 163 ----- ProjectSrc/Forms/FlagCreator.Designer.cs | 170 ----- ProjectSrc/Forms/FlagCreator.cs | 54 -- ProjectSrc/Forms/FlagEditor.Designer.cs | 347 --------- ProjectSrc/Forms/FlagEditor.cs | 677 ------------------ ProjectSrc/Forms/Launcher.Designer.cs | 276 ------- ProjectSrc/Forms/Launcher.cs | 499 ------------- ProjectSrc/Properties/AssemblyInfo.cs | 38 - ProjectSrc/Properties/Resources.Designer.cs | 83 --- ProjectSrc/Properties/Resources.resx | 68 -- ProjectSrc/RobloxStudioModManager.csproj | 291 -------- ProjectSrc/RobloxStudioModManager.sln | 32 +- ProjectSrc/Utility/BootstrapProgressStyle.cs | 8 + ProjectSrc/Utility/FlagManager.cs | 42 ++ .../ModManagerEnvironment.cs} | 26 +- ProjectSrc/WinUI/App.xaml | 22 + ProjectSrc/WinUI/App.xaml.cs | 27 + .../{Resources => WinUI/Assets}/Icon.ico | Bin .../{Resources => WinUI/Assets}/Logo.png | Bin ProjectSrc/WinUI/BackdropHelper.cs | 10 + ProjectSrc/WinUI/BootstrapWindow.xaml | 81 +++ ProjectSrc/WinUI/BootstrapWindow.xaml.cs | 255 +++++++ ProjectSrc/WinUI/FlagCreatorDialog.xaml | 42 ++ ProjectSrc/WinUI/FlagCreatorDialog.xaml.cs | 44 ++ ProjectSrc/WinUI/FlagEditorWindow.xaml | 212 ++++++ ProjectSrc/WinUI/FlagEditorWindow.xaml.cs | 544 ++++++++++++++ ProjectSrc/WinUI/MainWindow.xaml | 78 ++ ProjectSrc/WinUI/MainWindow.xaml.cs | 509 +++++++++++++ .../WinUI/RobloxStudioModManager.WinUI.csproj | 72 ++ ProjectSrc/WinUI/SystemSound.cs | 35 + ProjectSrc/WinUI/WindowPositioning.cs | 28 + ProjectSrc/WinUI/app.manifest | 27 + ProjectSrc/app.manifest | 18 - 37 files changed, 2070 insertions(+), 2896 deletions(-) delete mode 100644 ProjectSrc/App.config delete mode 100644 ProjectSrc/FodyWeavers.xml delete mode 100644 ProjectSrc/Forms/BootstrapperForm.Designer.cs delete mode 100644 ProjectSrc/Forms/BootstrapperForm.cs delete mode 100644 ProjectSrc/Forms/FlagCreator.Designer.cs delete mode 100644 ProjectSrc/Forms/FlagCreator.cs delete mode 100644 ProjectSrc/Forms/FlagEditor.Designer.cs delete mode 100644 ProjectSrc/Forms/FlagEditor.cs delete mode 100644 ProjectSrc/Forms/Launcher.Designer.cs delete mode 100644 ProjectSrc/Forms/Launcher.cs delete mode 100644 ProjectSrc/Properties/AssemblyInfo.cs delete mode 100644 ProjectSrc/Properties/Resources.Designer.cs delete mode 100644 ProjectSrc/Properties/Resources.resx delete mode 100644 ProjectSrc/RobloxStudioModManager.csproj create mode 100644 ProjectSrc/Utility/BootstrapProgressStyle.cs create mode 100644 ProjectSrc/Utility/FlagManager.cs rename ProjectSrc/{Program.cs => Utility/ModManagerEnvironment.cs} (92%) create mode 100644 ProjectSrc/WinUI/App.xaml create mode 100644 ProjectSrc/WinUI/App.xaml.cs rename ProjectSrc/{Resources => WinUI/Assets}/Icon.ico (100%) rename ProjectSrc/{Resources => WinUI/Assets}/Logo.png (100%) create mode 100644 ProjectSrc/WinUI/BackdropHelper.cs create mode 100644 ProjectSrc/WinUI/BootstrapWindow.xaml create mode 100644 ProjectSrc/WinUI/BootstrapWindow.xaml.cs create mode 100644 ProjectSrc/WinUI/FlagCreatorDialog.xaml create mode 100644 ProjectSrc/WinUI/FlagCreatorDialog.xaml.cs create mode 100644 ProjectSrc/WinUI/FlagEditorWindow.xaml create mode 100644 ProjectSrc/WinUI/FlagEditorWindow.xaml.cs create mode 100644 ProjectSrc/WinUI/MainWindow.xaml create mode 100644 ProjectSrc/WinUI/MainWindow.xaml.cs create mode 100644 ProjectSrc/WinUI/RobloxStudioModManager.WinUI.csproj create mode 100644 ProjectSrc/WinUI/SystemSound.cs create mode 100644 ProjectSrc/WinUI/WindowPositioning.cs create mode 100644 ProjectSrc/WinUI/app.manifest delete mode 100644 ProjectSrc/app.manifest diff --git a/ProjectSrc/App.config b/ProjectSrc/App.config deleted file mode 100644 index 57a2b76..0000000 --- a/ProjectSrc/App.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - -
- - - - - - diff --git a/ProjectSrc/Bootstrapper/StudioBootstrapper.cs b/ProjectSrc/Bootstrapper/StudioBootstrapper.cs index ee74f95..05f4349 100644 --- a/ProjectSrc/Bootstrapper/StudioBootstrapper.cs +++ b/ProjectSrc/Bootstrapper/StudioBootstrapper.cs @@ -8,7 +8,6 @@ using System.Net; using System.Runtime.InteropServices; using System.Threading.Tasks; -using System.Windows.Forms; using Newtonsoft.Json; using RobloxDeployHistory; @@ -17,6 +16,7 @@ namespace RobloxStudioModManager { public delegate void MessageFeed(string message); + public delegate Task ConfirmPrompt(string message, string title); public class StudioBootstrapper { @@ -32,6 +32,7 @@ public class StudioBootstrapper public event MessageFeed EchoFeed; public event MessageFeed StatusFeed; + public event ConfirmPrompt ConfirmFeed; private readonly IBootstrapperState mainState; private readonly VersionManifest versionData; @@ -51,7 +52,7 @@ public class StudioBootstrapper public int Progress = 0; public int MaxProgress = 0; - public ProgressBarStyle ProgressBarStyle = ProgressBarStyle.Continuous; + public BootstrapProgressStyle ProgressBarStyle = BootstrapProgressStyle.Determinate; public object ProgressLock = new object(); @@ -646,25 +647,21 @@ private async Task shutdownStudioProcesses() if (initialRunning.Count > 0) { - DialogResult result = DialogResult.OK; + bool proceed = true; if (mainState == Program.State) { - result = MessageBox.Show + proceed = ConfirmFeed == null || await ConfirmFeed.Invoke ( "All Roblox Studio processes need to be closed in order to update Roblox Studio!\n" + "Press Ok once you've saved your work, or\n" + "Press Cancel to skip this update temporarily.", - "Notice", - MessageBoxButtons.OKCancel, - MessageBoxIcon.Warning, - MessageBoxDefaultButton.Button1, - MessageBoxOptions.DefaultDesktopOnly - ); + "Notice" + ).ConfigureAwait(true); } - if (result == DialogResult.Cancel) + if (!proceed) { safeToContinue = true; cancelled = true; @@ -707,7 +704,7 @@ private async Task shutdownStudioProcesses() Progress = 0; MaxProgress = retries * granularity; - ProgressBarStyle = ProgressBarStyle.Continuous; + ProgressBarStyle = BootstrapProgressStyle.Determinate; for (int i = 0; i < retries; i++) { @@ -826,7 +823,7 @@ public async Task Bootstrap(string targetVersion = "") Progress = 0; MaxProgress = 0; - ProgressBarStyle = ProgressBarStyle.Continuous; + ProgressBarStyle = BootstrapProgressStyle.Determinate; // Verify all of these packages are available to install. foreach (Package package in pkgManifest) @@ -864,7 +861,7 @@ await Task Progress = 1; MaxProgress = 1; - ProgressBarStyle = ProgressBarStyle.Marquee; + ProgressBarStyle = BootstrapProgressStyle.Indeterminate; var timeout = Task.Delay(2000); await timeout.ConfigureAwait(false); @@ -974,11 +971,11 @@ await Task versionData.VersionGuid = buildVersion; versionData.VersionOverload = targetVersion; - ProgressBarStyle = ProgressBarStyle.Marquee; + ProgressBarStyle = BootstrapProgressStyle.Indeterminate; } else { - ProgressBarStyle = ProgressBarStyle.Marquee; + ProgressBarStyle = BootstrapProgressStyle.Indeterminate; echo("Update cancelled. Launching on current version."); } } @@ -1018,7 +1015,7 @@ await Task if (ApplyModManagerPatches && string.IsNullOrEmpty(OverrideStudioDirectory)) { echo("Applying flag configuration..."); - FlagEditor.ApplyFlags(); + FlagManager.ApplyFlags(); // Secret feature only for me :( // Feel free to patch in your own thing if you want. @@ -1029,7 +1026,7 @@ await Task #endif } - ProgressBarStyle = ProgressBarStyle.Marquee; + ProgressBarStyle = BootstrapProgressStyle.Indeterminate; MaxProgress = 1; Progress = 1; diff --git a/ProjectSrc/FodyWeavers.xml b/ProjectSrc/FodyWeavers.xml deleted file mode 100644 index 4da11b3..0000000 --- a/ProjectSrc/FodyWeavers.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/ProjectSrc/Forms/BootstrapperForm.Designer.cs b/ProjectSrc/Forms/BootstrapperForm.Designer.cs deleted file mode 100644 index e62e8bb..0000000 --- a/ProjectSrc/Forms/BootstrapperForm.Designer.cs +++ /dev/null @@ -1,139 +0,0 @@ -namespace RobloxStudioModManager -{ - partial class BootstrapperForm - { - /// - /// 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() - { - this.components = new System.ComponentModel.Container(); - this.progressBar = new System.Windows.Forms.ProgressBar(); - this.logo = new System.Windows.Forms.PictureBox(); - this.statusLbl = new System.Windows.Forms.Label(); - this.log = new System.Windows.Forms.RichTextBox(); - this.progressTimer = new System.Windows.Forms.Timer(this.components); - ((System.ComponentModel.ISupportInitialize)(this.logo)).BeginInit(); - this.SuspendLayout(); - // - // progressBar - // - this.progressBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.progressBar.Location = new System.Drawing.Point(6, 194); - this.progressBar.Margin = new System.Windows.Forms.Padding(1); - this.progressBar.MarqueeAnimationSpeed = 1; - this.progressBar.Name = "progressBar"; - this.progressBar.Size = new System.Drawing.Size(582, 29); - this.progressBar.Step = 0; - this.progressBar.Style = System.Windows.Forms.ProgressBarStyle.Marquee; - this.progressBar.TabIndex = 1; - this.progressBar.Value = 100; - // - // logo - // - this.logo.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left))); - this.logo.BackColor = System.Drawing.Color.Transparent; - this.logo.BackgroundImage = global::RobloxStudioModManager.Properties.Resources.Logo; - this.logo.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom; - this.logo.InitialImage = global::RobloxStudioModManager.Properties.Resources.Logo; - this.logo.Location = new System.Drawing.Point(6, 8); - this.logo.Margin = new System.Windows.Forms.Padding(2); - this.logo.Name = "logo"; - this.logo.Size = new System.Drawing.Size(121, 153); - this.logo.TabIndex = 9; - this.logo.TabStop = false; - this.logo.WaitOnLoad = true; - // - // statusLbl - // - this.statusLbl.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.statusLbl.AutoSize = true; - this.statusLbl.Font = new System.Drawing.Font("Segoe UI Light", 16F); - this.statusLbl.Location = new System.Drawing.Point(0, 163); - this.statusLbl.Margin = new System.Windows.Forms.Padding(0); - this.statusLbl.Name = "statusLbl"; - this.statusLbl.Size = new System.Drawing.Size(225, 30); - this.statusLbl.TabIndex = 11; - this.statusLbl.Text = "Checking for updates..."; - this.statusLbl.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; - // - // log - // - this.log.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.log.BackColor = System.Drawing.Color.White; - this.log.Font = new System.Drawing.Font("Consolas", 8.25F); - this.log.ForeColor = System.Drawing.Color.Black; - this.log.Location = new System.Drawing.Point(131, 8); - this.log.Margin = new System.Windows.Forms.Padding(2); - this.log.Name = "log"; - this.log.ReadOnly = true; - this.log.Size = new System.Drawing.Size(458, 154); - this.log.TabIndex = 12; - this.log.Text = ""; - // - // progressTimer - // - this.progressTimer.Enabled = true; - // - // BootstrapperForm - // - this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.ClientSize = new System.Drawing.Size(596, 249); - this.Controls.Add(this.log); - this.Controls.Add(this.statusLbl); - this.Controls.Add(this.logo); - this.Controls.Add(this.progressBar); - this.DoubleBuffered = true; - this.Font = new System.Drawing.Font("Consolas", 8.25F); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; - this.Icon = global::RobloxStudioModManager.Properties.Resources.Icon; - this.Margin = new System.Windows.Forms.Padding(1); - this.MinimumSize = new System.Drawing.Size(451, 205); - this.Name = "BootstrapperForm"; - this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "Roblox Studio Bootstrapper"; - this.TopMost = true; - this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.BootstrapperForm_FormClosing); - this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.BootstrapperForm_FormClosed); - ((System.ComponentModel.ISupportInitialize)(this.logo)).EndInit(); - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private System.Windows.Forms.ProgressBar progressBar; - private System.Windows.Forms.PictureBox logo; - private System.Windows.Forms.Label statusLbl; - private System.Windows.Forms.RichTextBox log; - private System.Windows.Forms.Timer progressTimer; - } -} \ No newline at end of file diff --git a/ProjectSrc/Forms/BootstrapperForm.cs b/ProjectSrc/Forms/BootstrapperForm.cs deleted file mode 100644 index 65bd932..0000000 --- a/ProjectSrc/Forms/BootstrapperForm.cs +++ /dev/null @@ -1,163 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Diagnostics.Contracts; -using System.Threading; -using System.Threading.Tasks; -using System.Windows.Forms; - -using RobloxDeployHistory; - -namespace RobloxStudioModManager -{ - public partial class BootstrapperForm : Form - { - public StudioBootstrapper Bootstrapper { get; private set; } - private ConcurrentBag logQueue = new ConcurrentBag(); - private readonly bool exitOnClose = false; - - public BootstrapperForm(StudioBootstrapper bootstrapper, bool exitWhenClosed = false) - { - Contract.Requires(bootstrapper != null); - InitializeComponent(); - - Bootstrapper = bootstrapper; - exitOnClose = exitWhenClosed; - - bootstrapper.EchoFeed += new MessageFeed(echo); - bootstrapper.StatusFeed += new MessageFeed(setStatus); - - Show(); - BringToFront(); - } - - public async Task Bootstrap() - { - var state = Program.State; - var targetVersion = state.TargetVersion; - - progressTimer.Tick += new EventHandler((sender, args) => - { - var progress = Bootstrapper.Progress; - progressBar.Style = Bootstrapper.ProgressBarStyle; - - var maxProgress = Bootstrapper.MaxProgress; - progressBar.Maximum = maxProgress; - - if (progress > maxProgress) - { - progressBar.Value = Math.Max(0, maxProgress - 1); - return; - } - - if (!logQueue.IsEmpty) - { - string blob = string.Join("\n", logQueue) + '\n'; - var newQueue = new ConcurrentBag(); - - Interlocked.Exchange(ref logQueue, newQueue); - log.AppendText(blob); - } - - progressBar.Value = Math.Min(progress, maxProgress); - Refresh(); - }); - - var bootstrap = Bootstrapper.Bootstrap(targetVersion); - await bootstrap.ConfigureAwait(true); - } - - public static async Task BringUpToDate(string expectedVersion, string updateReason) - { - var versionData = Program.State.VersionData; - string currentVersion = versionData.VersionGuid; - - if (currentVersion != expectedVersion) - { - DialogResult check = DialogResult.Yes; - - if (!string.IsNullOrEmpty(currentVersion)) - { - check = MessageBox.Show - ( - "Roblox Studio is out of date!\n" - + updateReason + - "\nWould you like to update now?", - - "Out of date!", - MessageBoxButtons.YesNo, - MessageBoxIcon.Warning - ); - } - - if (check == DialogResult.Yes) - { - var bootstrapper = new StudioBootstrapper(); - - using (var installer = new BootstrapperForm(bootstrapper)) - { - var bootstrap = installer.Bootstrap(); - await bootstrap.ConfigureAwait(true); - } - } - } - } - - private void setStatus(string status) - { - if (statusLbl.InvokeRequired) - { - var action = new Action(setStatus); - statusLbl.Invoke(action, status); - } - else - { - statusLbl.Text = status; - statusLbl.Refresh(); - BringToFront(); - } - } - - private void echo(string msg) - { - logQueue.Add(msg); - } - - private void BootstrapperForm_FormClosed(object sender, FormClosedEventArgs e) - { - Program.SaveState(); - - if (exitOnClose && e.CloseReason == CloseReason.UserClosing) - { - Application.Exit(); - } - } - - private void BootstrapperForm_FormClosing(object sender, FormClosingEventArgs e) - { - if (e.CloseReason != CloseReason.UserClosing) - return; - - DialogResult result = MessageBox.Show - ( - this, - - "The installation has not finished yet!\n" + - "Closing this window will exit the mod manager.\n" + - "Are you sure you want to continue?", - - "Warning", - - MessageBoxButtons.YesNo, - MessageBoxIcon.Warning - ); - - if (result != DialogResult.No) - { - Environment.Exit(0); - return; - } - - e.Cancel = true; - } - } -} diff --git a/ProjectSrc/Forms/FlagCreator.Designer.cs b/ProjectSrc/Forms/FlagCreator.Designer.cs deleted file mode 100644 index 5ca8166..0000000 --- a/ProjectSrc/Forms/FlagCreator.Designer.cs +++ /dev/null @@ -1,170 +0,0 @@ - -namespace RobloxStudioModManager -{ - partial class FlagCreator - { - /// - /// 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() - { - this.nameLabel = new System.Windows.Forms.Label(); - this.flagName = new System.Windows.Forms.TextBox(); - this.typeLabel = new System.Windows.Forms.Label(); - this.flagType = new System.Windows.Forms.ComboBox(); - this.cancelButton = new System.Windows.Forms.Button(); - this.createButton = new System.Windows.Forms.Button(); - this.flagClass = new System.Windows.Forms.ComboBox(); - this.classLabel = new System.Windows.Forms.Label(); - this.SuspendLayout(); - // - // nameLabel - // - this.nameLabel.AutoSize = true; - this.nameLabel.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.nameLabel.Location = new System.Drawing.Point(12, 8); - this.nameLabel.Name = "nameLabel"; - this.nameLabel.Size = new System.Drawing.Size(63, 25); - this.nameLabel.TabIndex = 0; - this.nameLabel.Text = "Name:"; - // - // flagName - // - this.flagName.Location = new System.Drawing.Point(81, 11); - this.flagName.Name = "flagName"; - this.flagName.Size = new System.Drawing.Size(235, 26); - this.flagName.TabIndex = 1; - // - // typeLabel - // - this.typeLabel.AutoSize = true; - this.typeLabel.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.typeLabel.Location = new System.Drawing.Point(12, 81); - this.typeLabel.Name = "typeLabel"; - this.typeLabel.Size = new System.Drawing.Size(53, 25); - this.typeLabel.TabIndex = 2; - this.typeLabel.Text = "Type:"; - // - // flagType - // - this.flagType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.flagType.FormattingEnabled = true; - this.flagType.Items.AddRange(new object[] { - "Flag", - "Int", - "Log", - "String"}); - this.flagType.Location = new System.Drawing.Point(81, 84); - this.flagType.Name = "flagType"; - this.flagType.Size = new System.Drawing.Size(235, 28); - this.flagType.TabIndex = 3; - // - // cancelButton - // - this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.cancelButton.Location = new System.Drawing.Point(17, 130); - this.cancelButton.Name = "cancelButton"; - this.cancelButton.Size = new System.Drawing.Size(142, 33); - this.cancelButton.TabIndex = 4; - this.cancelButton.Text = "Cancel"; - this.cancelButton.UseVisualStyleBackColor = true; - this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); - // - // createButton - // - this.createButton.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.createButton.Location = new System.Drawing.Point(174, 130); - this.createButton.Name = "createButton"; - this.createButton.Size = new System.Drawing.Size(142, 33); - this.createButton.TabIndex = 5; - this.createButton.Text = "Create"; - this.createButton.UseVisualStyleBackColor = true; - this.createButton.Click += new System.EventHandler(this.createButton_Click); - // - // flagClass - // - this.flagClass.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.flagClass.FormattingEnabled = true; - this.flagClass.Items.AddRange(new object[] { - "Fast (F)", - "Dynamic Fast (DF)", - "Synchronized Fast (SF)"}); - this.flagClass.Location = new System.Drawing.Point(81, 47); - this.flagClass.Name = "flagClass"; - this.flagClass.Size = new System.Drawing.Size(235, 28); - this.flagClass.TabIndex = 7; - // - // classLabel - // - this.classLabel.AutoSize = true; - this.classLabel.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.classLabel.Location = new System.Drawing.Point(12, 45); - this.classLabel.Name = "classLabel"; - this.classLabel.Size = new System.Drawing.Size(56, 25); - this.classLabel.TabIndex = 6; - this.classLabel.Text = "Class:"; - // - // FlagCreator - // - this.AcceptButton = this.createButton; - this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.ClientSize = new System.Drawing.Size(331, 176); - this.Controls.Add(this.flagClass); - this.Controls.Add(this.classLabel); - this.Controls.Add(this.createButton); - this.Controls.Add(this.cancelButton); - this.Controls.Add(this.flagType); - this.Controls.Add(this.typeLabel); - this.Controls.Add(this.flagName); - this.Controls.Add(this.nameLabel); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.Margin = new System.Windows.Forms.Padding(4); - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "FlagCreator"; - this.ShowIcon = false; - this.ShowInTaskbar = false; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "Add Custom Flag"; - this.TopMost = true; - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private System.Windows.Forms.Label nameLabel; - private System.Windows.Forms.TextBox flagName; - private System.Windows.Forms.Label typeLabel; - private System.Windows.Forms.ComboBox flagType; - private System.Windows.Forms.Button cancelButton; - private System.Windows.Forms.Button createButton; - private System.Windows.Forms.ComboBox flagClass; - private System.Windows.Forms.Label classLabel; - } -} \ No newline at end of file diff --git a/ProjectSrc/Forms/FlagCreator.cs b/ProjectSrc/Forms/FlagCreator.cs deleted file mode 100644 index d57e41d..0000000 --- a/ProjectSrc/Forms/FlagCreator.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.RegularExpressions; -using System.Windows.Forms; - -namespace RobloxStudioModManager -{ - public partial class FlagCreator : Form - { - public CustomFlag Result { get; private set; } - private static readonly string[] classes = new string[3] { "F", "DF", "SF" }; - - public FlagCreator() - { - InitializeComponent(); - flagType.SelectedIndex = 0; - flagClass.SelectedIndex = 0; - } - - private void createButton_Click(object sender, EventArgs e) - { - string classType = classes[flagClass.SelectedIndex]; - string type = classType + flagType.SelectedItem.ToString(); - string name = Regex.Replace(flagName.Text, "[^A-z0-9_]", ""); - - if (flagName.Text != name) - flagName.Text = name; - - if (string.IsNullOrEmpty(name)) - { - MessageBox.Show - ( - $"Please enter a name for the {type}!", - "Invalid submission!", - - MessageBoxButtons.OK, - MessageBoxIcon.Error - ); - - return; - } - - Result = new CustomFlag(type, name); - DialogResult = DialogResult.OK; - - Close(); - } - - private void cancelButton_Click(object sender, EventArgs e) - { - Close(); - } - } -} diff --git a/ProjectSrc/Forms/FlagEditor.Designer.cs b/ProjectSrc/Forms/FlagEditor.Designer.cs deleted file mode 100644 index 630aaad..0000000 --- a/ProjectSrc/Forms/FlagEditor.Designer.cs +++ /dev/null @@ -1,347 +0,0 @@ -namespace RobloxStudioModManager -{ - partial class FlagEditor - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - - #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() - { - this.components = new System.ComponentModel.Container(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle(); - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FlagEditor)); - this.tabs = new System.Windows.Forms.TabControl(); - this.viewFlagsTab = new System.Windows.Forms.TabPage(); - this.addCustom = new System.Windows.Forms.Button(); - this.overrideStatus = new System.Windows.Forms.Label(); - this.overrideSelected = new System.Windows.Forms.Button(); - this.flagSearchFilter = new System.Windows.Forms.TextBox(); - this.searchTitle = new System.Windows.Forms.Label(); - this.flagDataGridView = new System.Windows.Forms.DataGridView(); - this.nameColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.typeColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.valueColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.overridesTab = new System.Windows.Forms.TabPage(); - this.removeAll = new System.Windows.Forms.Button(); - this.removeSelected = new System.Windows.Forms.Button(); - this.overrideDataGridView = new System.Windows.Forms.DataGridView(); - this.overrideNameColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.overrideTypeColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.initialOverrideValueColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.notification = new System.Windows.Forms.NotifyIcon(this.components); - this.tabs.SuspendLayout(); - this.viewFlagsTab.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.flagDataGridView)).BeginInit(); - this.overridesTab.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.overrideDataGridView)).BeginInit(); - this.SuspendLayout(); - // - // tabs - // - this.tabs.Controls.Add(this.viewFlagsTab); - this.tabs.Controls.Add(this.overridesTab); - this.tabs.Dock = System.Windows.Forms.DockStyle.Fill; - this.tabs.Location = new System.Drawing.Point(0, 0); - this.tabs.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); - this.tabs.Name = "tabs"; - this.tabs.SelectedIndex = 0; - this.tabs.Size = new System.Drawing.Size(513, 563); - this.tabs.TabIndex = 0; - // - // viewFlagsTab - // - this.viewFlagsTab.Controls.Add(this.addCustom); - this.viewFlagsTab.Controls.Add(this.overrideStatus); - this.viewFlagsTab.Controls.Add(this.overrideSelected); - this.viewFlagsTab.Controls.Add(this.flagSearchFilter); - this.viewFlagsTab.Controls.Add(this.searchTitle); - this.viewFlagsTab.Controls.Add(this.flagDataGridView); - this.viewFlagsTab.Location = new System.Drawing.Point(4, 22); - this.viewFlagsTab.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); - this.viewFlagsTab.Name = "viewFlagsTab"; - this.viewFlagsTab.Padding = new System.Windows.Forms.Padding(3, 4, 3, 4); - this.viewFlagsTab.Size = new System.Drawing.Size(505, 537); - this.viewFlagsTab.TabIndex = 0; - this.viewFlagsTab.Text = "View Flags"; - this.viewFlagsTab.UseVisualStyleBackColor = true; - // - // addCustom - // - this.addCustom.Location = new System.Drawing.Point(201, 37); - this.addCustom.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); - this.addCustom.Name = "addCustom"; - this.addCustom.Size = new System.Drawing.Size(130, 20); - this.addCustom.TabIndex = 5; - this.addCustom.Text = "Add Custom"; - this.addCustom.UseVisualStyleBackColor = true; - this.addCustom.Click += new System.EventHandler(this.addCustom_Click); - // - // overrideStatus - // - this.overrideStatus.AutoSize = true; - this.overrideStatus.Location = new System.Drawing.Point(62, 66); - this.overrideStatus.Name = "overrideStatus"; - this.overrideStatus.Size = new System.Drawing.Size(0, 13); - this.overrideStatus.TabIndex = 4; - // - // overrideSelected - // - this.overrideSelected.Location = new System.Drawing.Point(65, 37); - this.overrideSelected.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); - this.overrideSelected.Name = "overrideSelected"; - this.overrideSelected.Size = new System.Drawing.Size(130, 20); - this.overrideSelected.TabIndex = 3; - this.overrideSelected.Text = "Override Selected"; - this.overrideSelected.UseVisualStyleBackColor = true; - this.overrideSelected.Click += new System.EventHandler(this.overrideSelected_Click); - // - // flagSearchFilter - // - this.flagSearchFilter.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Suggest; - this.flagSearchFilter.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.CustomSource; - this.flagSearchFilter.Location = new System.Drawing.Point(65, 13); - this.flagSearchFilter.Margin = new System.Windows.Forms.Padding(1, 4, 3, 4); - this.flagSearchFilter.Name = "flagSearchFilter"; - this.flagSearchFilter.Size = new System.Drawing.Size(429, 20); - this.flagSearchFilter.TabIndex = 2; - this.flagSearchFilter.TextChanged += new System.EventHandler(this.flagSearchFilter_TextChanged); - // - // searchTitle - // - this.searchTitle.AutoSize = true; - this.searchTitle.Font = new System.Drawing.Font("Segoe UI Semilight", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.searchTitle.Location = new System.Drawing.Point(7, 10); - this.searchTitle.Margin = new System.Windows.Forms.Padding(1, 0, 1, 0); - this.searchTitle.Name = "searchTitle"; - this.searchTitle.Size = new System.Drawing.Size(56, 20); - this.searchTitle.TabIndex = 1; - this.searchTitle.Text = "Search:"; - // - // flagDataGridView - // - this.flagDataGridView.AllowUserToAddRows = false; - this.flagDataGridView.AllowUserToDeleteRows = false; - this.flagDataGridView.AllowUserToResizeColumns = false; - this.flagDataGridView.AllowUserToResizeRows = false; - this.flagDataGridView.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.DisplayedCells; - this.flagDataGridView.BackgroundColor = System.Drawing.SystemColors.Control; - this.flagDataGridView.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.flagDataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; - this.flagDataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { - this.nameColumn, - this.typeColumn, - this.valueColumn}); - this.flagDataGridView.Dock = System.Windows.Forms.DockStyle.Bottom; - this.flagDataGridView.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically; - this.flagDataGridView.Location = new System.Drawing.Point(3, 83); - this.flagDataGridView.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); - this.flagDataGridView.MultiSelect = false; - this.flagDataGridView.Name = "flagDataGridView"; - this.flagDataGridView.RowHeadersVisible = false; - this.flagDataGridView.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.DisableResizing; - this.flagDataGridView.RowTemplate.Resizable = System.Windows.Forms.DataGridViewTriState.False; - this.flagDataGridView.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; - this.flagDataGridView.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; - this.flagDataGridView.Size = new System.Drawing.Size(499, 450); - this.flagDataGridView.TabIndex = 0; - this.flagDataGridView.VirtualMode = true; - this.flagDataGridView.CellFormatting += new System.Windows.Forms.DataGridViewCellFormattingEventHandler(this.flagDataGridView_CellFormatting); - this.flagDataGridView.CellMouseClick += new System.Windows.Forms.DataGridViewCellMouseEventHandler(this.flagDataGridView_CellMouseClick); - this.flagDataGridView.CellValueNeeded += new System.Windows.Forms.DataGridViewCellValueEventHandler(this.flagDataGridView_CellValueNeeded); - // - // nameColumn - // - this.nameColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.None; - this.nameColumn.FillWeight = 250F; - this.nameColumn.HeaderText = "Name"; - this.nameColumn.MinimumWidth = 8; - this.nameColumn.Name = "nameColumn"; - this.nameColumn.ReadOnly = true; - this.nameColumn.Resizable = System.Windows.Forms.DataGridViewTriState.False; - this.nameColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.nameColumn.Width = 278; - // - // typeColumn - // - this.typeColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.None; - this.typeColumn.FillWeight = 50F; - this.typeColumn.HeaderText = "Type"; - this.typeColumn.MinimumWidth = 8; - this.typeColumn.Name = "typeColumn"; - this.typeColumn.ReadOnly = true; - this.typeColumn.Resizable = System.Windows.Forms.DataGridViewTriState.False; - this.typeColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.typeColumn.Width = 55; - // - // valueColumn - // - this.valueColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.None; - this.valueColumn.FillWeight = 150F; - this.valueColumn.HeaderText = "Value"; - this.valueColumn.MinimumWidth = 8; - this.valueColumn.Name = "valueColumn"; - this.valueColumn.ReadOnly = true; - this.valueColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - this.valueColumn.Width = 165; - // - // overridesTab - // - this.overridesTab.Controls.Add(this.removeAll); - this.overridesTab.Controls.Add(this.removeSelected); - this.overridesTab.Controls.Add(this.overrideDataGridView); - this.overridesTab.Location = new System.Drawing.Point(4, 22); - this.overridesTab.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); - this.overridesTab.Name = "overridesTab"; - this.overridesTab.Padding = new System.Windows.Forms.Padding(3, 4, 3, 4); - this.overridesTab.Size = new System.Drawing.Size(505, 537); - this.overridesTab.TabIndex = 1; - this.overridesTab.Text = "Overrides"; - this.overridesTab.UseVisualStyleBackColor = true; - // - // removeAll - // - this.removeAll.Location = new System.Drawing.Point(255, 8); - this.removeAll.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); - this.removeAll.Name = "removeAll"; - this.removeAll.Size = new System.Drawing.Size(241, 29); - this.removeAll.TabIndex = 3; - this.removeAll.Text = "Remove All"; - this.removeAll.UseVisualStyleBackColor = true; - this.removeAll.Click += new System.EventHandler(this.removeAll_Click); - // - // removeSelected - // - this.removeSelected.Location = new System.Drawing.Point(7, 8); - this.removeSelected.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); - this.removeSelected.Name = "removeSelected"; - this.removeSelected.Size = new System.Drawing.Size(241, 29); - this.removeSelected.TabIndex = 2; - this.removeSelected.Text = "Remove Selected"; - this.removeSelected.UseVisualStyleBackColor = true; - this.removeSelected.Click += new System.EventHandler(this.removeSelected_Click); - // - // overrideDataGridView - // - this.overrideDataGridView.AllowUserToAddRows = false; - this.overrideDataGridView.AllowUserToDeleteRows = false; - this.overrideDataGridView.AllowUserToResizeColumns = false; - this.overrideDataGridView.AllowUserToResizeRows = false; - this.overrideDataGridView.BackgroundColor = System.Drawing.SystemColors.Control; - this.overrideDataGridView.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.overrideDataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; - this.overrideDataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { - this.overrideNameColumn, - this.overrideTypeColumn, - this.initialOverrideValueColumn}); - this.overrideDataGridView.Dock = System.Windows.Forms.DockStyle.Bottom; - this.overrideDataGridView.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnEnter; - this.overrideDataGridView.Location = new System.Drawing.Point(3, 42); - this.overrideDataGridView.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); - this.overrideDataGridView.MultiSelect = false; - this.overrideDataGridView.Name = "overrideDataGridView"; - this.overrideDataGridView.RowHeadersVisible = false; - this.overrideDataGridView.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders; - dataGridViewCellStyle1.BackColor = System.Drawing.Color.Silver; - this.overrideDataGridView.RowsDefaultCellStyle = dataGridViewCellStyle1; - this.overrideDataGridView.RowTemplate.DefaultCellStyle.BackColor = System.Drawing.Color.White; - this.overrideDataGridView.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; - this.overrideDataGridView.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; - this.overrideDataGridView.Size = new System.Drawing.Size(499, 491); - this.overrideDataGridView.TabIndex = 1; - this.overrideDataGridView.CellEndEdit += new System.Windows.Forms.DataGridViewCellEventHandler(this.overrideDataGridView_CellEndEdit); - this.overrideDataGridView.CellMouseEnter += new System.Windows.Forms.DataGridViewCellEventHandler(this.overrideDataGridView_CellMouseEnter); - this.overrideDataGridView.CellMouseLeave += new System.Windows.Forms.DataGridViewCellEventHandler(this.overrideDataGridView_CellMouseLeave); - // - // overrideNameColumn - // - this.overrideNameColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill; - this.overrideNameColumn.DataPropertyName = "Name"; - this.overrideNameColumn.FillWeight = 150F; - this.overrideNameColumn.HeaderText = "Name"; - this.overrideNameColumn.MinimumWidth = 8; - this.overrideNameColumn.Name = "overrideNameColumn"; - this.overrideNameColumn.ReadOnly = true; - this.overrideNameColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - // - // overrideTypeColumn - // - this.overrideTypeColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill; - this.overrideTypeColumn.DataPropertyName = "Type"; - this.overrideTypeColumn.FillWeight = 40F; - this.overrideTypeColumn.HeaderText = "Type"; - this.overrideTypeColumn.MinimumWidth = 8; - this.overrideTypeColumn.Name = "overrideTypeColumn"; - this.overrideTypeColumn.ReadOnly = true; - this.overrideTypeColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - // - // initialOverrideValueColumn - // - this.initialOverrideValueColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill; - this.initialOverrideValueColumn.DataPropertyName = "Value"; - this.initialOverrideValueColumn.HeaderText = "Value"; - this.initialOverrideValueColumn.MinimumWidth = 8; - this.initialOverrideValueColumn.Name = "initialOverrideValueColumn"; - this.initialOverrideValueColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; - // - // notification - // - this.notification.Icon = global::RobloxStudioModManager.Properties.Resources.Icon; - this.notification.Text = "notification"; - this.notification.Visible = true; - // - // FlagEditor - // - this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.ClientSize = new System.Drawing.Size(513, 563); - this.Controls.Add(this.tabs); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.Icon = global::RobloxStudioModManager.Properties.Resources.Icon; - this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); - this.MaximizeBox = false; - this.Name = "FlagEditor"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "Flag Editor"; - this.Load += new System.EventHandler(this.FlagEditor_Load); - this.tabs.ResumeLayout(false); - this.viewFlagsTab.ResumeLayout(false); - this.viewFlagsTab.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)(this.flagDataGridView)).EndInit(); - this.overridesTab.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.overrideDataGridView)).EndInit(); - this.ResumeLayout(false); - - } - - #endregion - - private System.Windows.Forms.TabControl tabs; - private System.Windows.Forms.TabPage viewFlagsTab; - private System.Windows.Forms.TabPage overridesTab; - private System.Windows.Forms.DataGridView flagDataGridView; - private System.Windows.Forms.TextBox flagSearchFilter; - private System.Windows.Forms.Label searchTitle; - private System.Windows.Forms.Button overrideSelected; - private System.Windows.Forms.DataGridView overrideDataGridView; - private System.Windows.Forms.Label overrideStatus; - private System.Windows.Forms.Button removeAll; - private System.Windows.Forms.Button removeSelected; - private System.Windows.Forms.DataGridViewTextBoxColumn overrideNameColumn; - private System.Windows.Forms.DataGridViewTextBoxColumn overrideTypeColumn; - private System.Windows.Forms.DataGridViewTextBoxColumn initialOverrideValueColumn; - private System.Windows.Forms.Button addCustom; - private System.Windows.Forms.DataGridViewTextBoxColumn nameColumn; - private System.Windows.Forms.DataGridViewTextBoxColumn typeColumn; - private System.Windows.Forms.DataGridViewTextBoxColumn valueColumn; - private System.Windows.Forms.NotifyIcon notification; - } -} \ No newline at end of file diff --git a/ProjectSrc/Forms/FlagEditor.cs b/ProjectSrc/Forms/FlagEditor.cs deleted file mode 100644 index 6990eb6..0000000 --- a/ProjectSrc/Forms/FlagEditor.cs +++ /dev/null @@ -1,677 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data; -using System.Diagnostics; -using System.Drawing; -using System.IO; -using System.Linq; -using System.Net; -using System.Reflection; -using System.Threading.Tasks; -using System.Windows.Forms; - -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace RobloxStudioModManager -{ - public partial class FlagEditor : Form - { - internal class ClientSettings - { - public Dictionary ApplicationSettings = null; - } - - private static VersionManifest versionRegistry => Program.State.VersionData; - private static SortedDictionary flagRegistry => Program.State.FlagEditor; - - private DataTable overrideTable; - private readonly Dictionary overrideRowLookup = new Dictionary(); - - private static readonly IReadOnlyDictionary flagTypes = new Dictionary() - { - {"Flag", "false"}, - {"Int", "0"}, - {"String", " "}, - {"Log", "0"}, - }; - - private const string OVERRIDE_STATUS_OFF = "No local overrides were found on load."; - private const string OVERRIDE_STATUS_ON = "Values highlighted in red were overridden locally."; - - private List flags = new List(); - private List allFlags = new List(); - - private static FVariable lastCustomFlag = null; - private readonly Dictionary flagLookup = new Dictionary(); - private string currentSearch = ""; - - public FlagEditor() - { - InitializeComponent(); - - overrideStatus.Text = OVERRIDE_STATUS_OFF; - overrideStatus.Visible = false; - - overrideStatus.Refresh(); - } - - protected override void Dispose(bool disposing) - { - if (disposing) - { - components?.Dispose(); - overrideTable?.Dispose(); - Program.SaveState(); - } - - base.Dispose(disposing); - } - - private bool confirm(string header, string message) - { - DialogResult result = MessageBox.Show(message, header, MessageBoxButtons.YesNo, MessageBoxIcon.Warning); - return result == DialogResult.Yes; - } - - private static void applyRowColor(DataGridViewRow row, Color color) - { - foreach (DataGridViewCell cell in row.Cells) - { - cell.Style.BackColor = color; - } - } - - private static string getFlagKeyByRow(DataGridViewRow row) - { - var cells = row.Cells; - - string name = cells[0].Value as string; - string type = cells[1].Value as string; - - return type + name; - } - - private bool rowMatchesSelectedRow(DataGridViewRow row) - { - FVariable selectedFlag = lastCustomFlag; - - if (selectedFlag == null && flagDataGridView.SelectedRows.Count == 1) - { - DataGridViewRow selectedRow = flagDataGridView.SelectedRows[0]; - selectedFlag = flags[selectedRow.Index]; - } - - return selectedFlag?.Key == getFlagKeyByRow(row); - } - - private void addFlagOverride(FVariable flag, bool init = false) - { - string key = flag.Key; - - if (!overrideRowLookup.ContainsKey(key)) - { - if (!init && flag.Type.EndsWith("Flag", Program.StringFormat)) - { - if (bool.TryParse(flag.Value, out bool value)) - { - string str = (!value) - .ToString(Program.Format) - .ToLower(Program.Format); - - flag.SetValue(str); - } - } - - DataRow row = overrideTable.Rows.Add - ( - flag.Name, - flag.Type, - flag.Value.ToLower(Program.Format) - ); - - overrideRowLookup.Add(key, row); - } - - overrideStatus.Text = OVERRIDE_STATUS_ON; - overrideStatus.ForeColor = Color.Red; - - if (!init) - { - // Find the row that corresponds to the flag we added. - var query = overrideDataGridView.Rows - .Cast() - .Where(rowMatchesSelectedRow); - - if (query.Any()) - { - // Select it. - var overrideRow = query.First(); - overrideDataGridView.CurrentCell = overrideRow.Cells[0]; - } - - // Clear last custom flag. - lastCustomFlag = null; - - // Switch to the overrides tab. - tabs.SelectedTab = overridesTab; - - // Record this flag in the registry. - flagRegistry[key] = flag; - } - } - - private void refreshFlags() - { - if (allFlags == null) - return; - - string search = flagSearchFilter.Text.ToLowerInvariant(); - - flags = allFlags - .Where(flag => flag.Name.ToLowerInvariant().Contains(search)) - .OrderBy(flag => flag.Name) - .ToList(); - - flagLookup.Clear(); - - for (int i = 0; i < flags.Count; i++) - { - FVariable flag = flags[i]; - flagLookup[flag.Key] = i; - flag.Dirty = true; - } - - // Start populating flag browser rows. - var currentCount = flagDataGridView.RowCount; - - if (currentCount == 0) - { - flagDataGridView.Rows.Add(); - currentCount = 1; - } - - var diff = flags.Count - currentCount; - flagDataGridView.SuspendLayout(); - - if (diff > 0) - flagDataGridView.Rows.AddCopies(0, diff); - else if (diff < 0) - flagDataGridView.RowCount += diff; - - flagDataGridView.ResumeLayout(); - } - - private async void InitializeEditor() - { - var flagNames = new HashSet(); - var studioPath = StudioBootstrapper.GetStudioPath(); - - var studioDir = StudioBootstrapper.GetStudioDirectory(); - var extraContentDir = Path.Combine(studioDir, "ExtraContent"); - - string lastFlagScanVersion = versionRegistry.LastFlagScanVersion; - string versionGuid = versionRegistry.VersionGuid; - - var cppFlags = StudioFFlagDumper.DumpCppFlags(studioPath); - var flagDump = Path.Combine(studioDir, "FFlags.json"); - var flagInfo = new FileInfo(flagDump); - - if (lastFlagScanVersion != versionGuid || !flagInfo.Exists) - { - cppFlags.ForEach(flag => flagNames.Add(flag)); - - var newJson = JsonConvert.SerializeObject(flagNames); - File.WriteAllText(flagDump, newJson); - - versionRegistry.LastFlagScanVersion = versionGuid; - Program.SaveState(); - } - - var rawFlagNames = File.ReadAllText(flagDump); - var cachedFlagNames = JsonConvert.DeserializeObject(rawFlagNames); - - foreach (var name in cachedFlagNames) - flagNames.Add(name); - - // Initialize flag browser - var json = new Dictionary(); - - using (var http = new WebClient()) - { - var settings = await http.DownloadStringTaskAsync("https://clientsettingscdn.roblox.com/v2/settings/application/PCDesktopClient"); - var data = JsonConvert.DeserializeObject(settings); - - foreach (var pair in data.ApplicationSettings) - { - string key = pair.Key; - - if (key.EndsWith("_PlaceFilter")) - continue; - - json.Add(key, pair.Value); - } - } - - foreach (var key in flagNames) - { - if (!json.ContainsKey(key)) - { - string flagClass = ""; - - if (key.StartsWith("SF")) - flagClass = "SF"; - else if (key.StartsWith("DF")) - flagClass = "DF"; - else if (key.StartsWith("F")) - flagClass = "F"; - - if (flagClass != "") - { - var prefix = key.Substring(flagClass.Length); - - foreach (var pair in flagTypes) - { - if (prefix.StartsWith(pair.Key)) - { - json.Add(key, pair.Value); - break; - } - } - } - else - { - json.Add(key, "??"); - } - } - } - - int numFlags = json.Count; - var flagSetup = new List(numFlags); - - foreach (string customFlag in flagNames) - { - if (!json.ContainsKey(customFlag)) - { - if (!flagRegistry.TryGetValue(customFlag, out var flag)) - continue; - - if (!flag.Custom) - continue; - - flagSetup.Add(flag); - } - } - - foreach (var pair in json) - { - string key = pair.Key, - value = pair.Value; - - if (!flagRegistry.TryGetValue(key, out var flag)) - flag = new FVariable(key, value); - - if (flag.Type == "") - continue; - - flagSetup.Add(flag); - } - - allFlags = flagSetup - .OrderBy(flag => flag.Key) - .ToList(); - - var propInfo = typeof(DataGridView).GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic); - propInfo.SetValue(flagDataGridView, true, null); - refreshFlags(); - - // Initialize override table. - overrideTable = new DataTable(); - - foreach (DataGridViewColumn column in overrideDataGridView.Columns) - overrideTable.Columns.Add(column.DataPropertyName); - - var overrideView = new DataView(overrideTable) { Sort = "Name" }; - - foreach (var flagName in flagRegistry.Keys) - { - var flag = flagRegistry[flagName]; - addFlagOverride(flag, true); - } - - overrideStatus.Visible = true; - overrideDataGridView.DataSource = overrideView; - } - - private async void FlagEditor_Load(object sender, EventArgs e) - { - Enabled = false; - UseWaitCursor = true; - - TopMost = true; - BringToFront(); - - Refresh(); - - var init = Task.Run(() => - { - var initializer = new Action(InitializeEditor); - Invoke(initializer); - }); - - await init.ConfigureAwait(true); - - Enabled = true; - UseWaitCursor = false; - } - - private void flagDataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e) - { - int row = e.RowIndex; - int col = e.ColumnIndex; - - if (flags.Count == 0) - { - e.Value = ""; - return; - } - - FVariable flag = flags[row]; - string value = "?"; - - if (col == 0) - value = flag.Name; - else if (col == 1) - value = flag.Type; - else if (col == 2) - value = flag.Value; - - e.Value = value; - } - - private void overrideSelected_Click(object sender, EventArgs e) - { - if (flagDataGridView.SelectedRows.Count == 1) - { - var selectedRow = flagDataGridView.SelectedRows[0]; - FVariable selectedFlag = flags[selectedRow.Index]; - addFlagOverride(selectedFlag); - } - } - - private void removeSelected_Click(object sender, EventArgs e) - { - var selectedRows = overrideDataGridView.SelectedRows; - - if (selectedRows.Count > 0) - { - var selectedRow = selectedRows[0]; - string flagKey = getFlagKeyByRow(selectedRow); - - FVariable flag = flagRegistry[flagKey]; - flag.Clear(); - - if (overrideRowLookup.ContainsKey(flagKey)) - { - DataRow rowToDelete = overrideRowLookup[flagKey]; - overrideRowLookup.Remove(flagKey); - rowToDelete.Delete(); - } - - selectedRow.Visible = false; - selectedRow.Dispose(); - - flagRegistry.Remove(flagKey); - } - - if (overrideDataGridView.Rows.Count == 0) - { - overrideStatus.Text = OVERRIDE_STATUS_OFF; - overrideStatus.ForeColor = Color.Black; - } - } - - private void removeAll_Click(object sender, EventArgs e) - { - bool doRemove = confirm("Confirmation", "Are you sure you would like to remove all flag overrides?\nThis will also delete any custom flags!"); - - if (doRemove) - { - var flagNames = flagRegistry.Keys.ToList(); - - foreach (string flagName in flagNames) - { - var flag = flagRegistry[flagName]; - flag.Clear(); - - flagRegistry.Remove(flagName); - } - - overrideStatus.Text = OVERRIDE_STATUS_OFF; - overrideStatus.ForeColor = Color.Black; - - overrideTable.Rows.Clear(); - overrideRowLookup.Clear(); - } - } - - private void overrideDataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e) - { - DataGridViewRow row = overrideDataGridView.Rows[e.RowIndex]; - string flagKey = getFlagKeyByRow(row); - - DataGridViewCell cell = row.Cells[e.ColumnIndex]; - string value = cell.Value as string; - - var cells = row.Cells; - var flagType = cells[1].Value as string; - - // Check if this input should be cancelled. - var format = Program.StringFormat; - bool badInput = false; - - if (flagType.EndsWith("Flag", format)) - { - string test = value - .ToUpperInvariant() - .Trim(); - - badInput = (test != "FALSE" && test != "TRUE"); - } - else if (flagType.EndsWith("Int", format)) - { - badInput = !int.TryParse(value, out int _); - } - - if (flagLookup.ContainsKey(flagKey)) - { - int index = flagLookup[flagKey]; - FVariable flag = flags[index]; - - if (!badInput) - { - flag.SetValue(value); - return; - } - - // If we have bad input, reset the value to the original value. - cell.Value = flag.Reset; - } - } - - private void flagSearchFilter_TextChanged(object sender, EventArgs e) - { - if (flagSearchFilter.Text != currentSearch) - { - currentSearch = flagSearchFilter.Text; - flagDataGridView.RowCount = 0; - refreshFlags(); - } - } - - private void overrideDataGridView_CellMouseEnter(object sender, DataGridViewCellEventArgs e) - { - if (e.ColumnIndex == 2 && e.RowIndex >= 0) - { - DataGridViewRow row = overrideDataGridView.Rows[e.RowIndex]; - var cells = row.Cells; - - var valueCell = cells[2]; - Type cellType = valueCell.GetType(); - - string flagType = cells[1].Value as string; - - if (flagType.EndsWith("Flag", Program.StringFormat) && cellType != typeof(DataGridViewComboBoxCell)) - { - // Switch the cell to a combo box. - // The user needs to select either true or false. - var newValueCell = new DataGridViewComboBoxCell(); - newValueCell.Items.Add("true"); - newValueCell.Items.Add("false"); - - newValueCell.Value = valueCell.Value - .ToString() - .ToLower(Program.Format); - - row.Cells[2] = newValueCell; - newValueCell.ReadOnly = false; - } - } - } - - private void overrideDataGridView_CellMouseLeave(object sender, DataGridViewCellEventArgs e) - { - if (e.ColumnIndex == 2 && e.RowIndex >= 0) - { - DataGridViewRow row = overrideDataGridView.Rows[e.RowIndex]; - var cells = row.Cells; - - var valueCell = cells[2]; - Type cellType = valueCell.GetType(); - - string flagType = cells[1].Value as string; - - if (flagType.EndsWith("Flag", Program.StringFormat) && cellType != typeof(DataGridViewTextBoxCell)) - { - string value = valueCell.Value.ToString(); - var newValueCell = new DataGridViewTextBoxCell() { Value = value }; - - row.Cells[2] = newValueCell; - newValueCell.ReadOnly = true; - } - } - } - - private void flagDataGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) - { - int index = e.RowIndex; - var row = flagDataGridView.Rows[index]; - - if (flags.Count == 0) - { - applyRowColor(row, Color.White); - return; - } - - FVariable flag = flags[index]; - - if (flag.Dirty) - { - if (flagRegistry.ContainsKey(flag.Key)) - { - var valueCell = row.Cells[2]; - valueCell.Value = flag.Value; - applyRowColor(row, Color.Pink); - } - else - { - applyRowColor(row, Color.White); - } - - flag.Dirty = false; - } - } - - public static void ApplyFlags() - { - var json = new JObject(); - - foreach (string flagName in flagRegistry.Keys) - { - var flag = flagRegistry[flagName]; - string value = flag.Value; - - var token = JToken.FromObject(value); - json.Add(flagName, token); - }; - - string file = json.ToString(); - string studioDir = StudioBootstrapper.GetStudioDirectory(); - string localAppData = Environment.GetEnvironmentVariable("LocalAppData"); - - string clientSettings_DEPRECATED = Path.Combine(studioDir, "ClientSettings"); - Directory.CreateDirectory(clientSettings_DEPRECATED); - - string filePath_DEPRECATED = Path.Combine(clientSettings_DEPRECATED, "ClientAppSettings.json"); - File.WriteAllText(filePath_DEPRECATED, file); - - string clientSettings_NEW = Path.Combine(localAppData, "Roblox", "ClientSettings"); - Directory.CreateDirectory(clientSettings_NEW); - - string filePath_NEW = Path.Combine(clientSettings_NEW, "ClientAppSettings.json"); - File.WriteAllText(filePath_NEW, file); - } - - private void addCustom_Click(object sender, EventArgs e) - { - using (FlagCreator flagCreator = new FlagCreator()) - { - Enabled = false; - UseWaitCursor = true; - - flagCreator.BringToFront(); - flagCreator.ShowDialog(); - - Enabled = true; - UseWaitCursor = false; - - if (flagCreator.DialogResult == DialogResult.OK) - { - var customFlag = flagCreator.Result; - string flagType = customFlag.Type; - - string flagValue = flagTypes - .Select(pair => pair.Key) - .Where(key => flagType.EndsWith(key, Program.StringFormat)) - .Select(key => flagTypes[key]) - .FirstOrDefault(); - - string flagName = flagType + customFlag.Name; - var newFlag = new FVariable(flagName, flagValue, true); - - flagRegistry[flagName] = newFlag; - lastCustomFlag = newFlag; - - addFlagOverride(newFlag); - } - } - } - - private void flagDataGridView_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e) - { - if (e.ColumnIndex != 2) - return; - - if (e.Button != MouseButtons.Right) - return; - - var rowIndex = e.RowIndex; - FVariable flag = flags[rowIndex]; - Clipboard.SetText(flag.Value); - - notification.BalloonTipTitle = flag.Name; - notification.BalloonTipText = "Value copied to clipboard!"; - notification.ShowBalloonTip(2000); - } - } -} \ No newline at end of file diff --git a/ProjectSrc/Forms/Launcher.Designer.cs b/ProjectSrc/Forms/Launcher.Designer.cs deleted file mode 100644 index 8260c7e..0000000 --- a/ProjectSrc/Forms/Launcher.Designer.cs +++ /dev/null @@ -1,276 +0,0 @@ -namespace RobloxStudioModManager -{ - partial class Launcher - { - /// - /// 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() - { - this.launchStudio = new System.Windows.Forms.Button(); - this.manageMods = new System.Windows.Forms.Button(); - this.forceRebuild = new System.Windows.Forms.CheckBox(); - this.openFlagEditor = new System.Windows.Forms.Button(); - this.openStudioDirectory = new System.Windows.Forms.CheckBox(); - this.targetVersionLabel = new System.Windows.Forms.Label(); - this.title = new System.Windows.Forms.Label(); - this.targetVersion = new System.Windows.Forms.ComboBox(); - this.releaseTag = new System.Windows.Forms.Label(); - this.logo = new System.Windows.Forms.PictureBox(); - this.channelNameBox = new System.Windows.Forms.TextBox(); - this.channelNameTitle = new System.Windows.Forms.Label(); - this.channelTokenTitle = new System.Windows.Forms.Label(); - this.channelTokenBox = new System.Windows.Forms.TextBox(); - ((System.ComponentModel.ISupportInitialize)(this.logo)).BeginInit(); - this.SuspendLayout(); - // - // launchStudio - // - this.launchStudio.AccessibleName = "Launch Roblox Studio"; - this.launchStudio.AccessibleRole = System.Windows.Forms.AccessibleRole.None; - this.launchStudio.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.launchStudio.Cursor = System.Windows.Forms.Cursors.Default; - this.launchStudio.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.launchStudio.Location = new System.Drawing.Point(11, 123); - this.launchStudio.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3); - this.launchStudio.Name = "launchStudio"; - this.launchStudio.Size = new System.Drawing.Size(142, 23); - this.launchStudio.TabIndex = 6; - this.launchStudio.Text = "Launch Studio"; - this.launchStudio.UseVisualStyleBackColor = true; - this.launchStudio.Click += new System.EventHandler(this.launchStudio_Click); - // - // manageMods - // - this.manageMods.AccessibleName = "Open Mod Folder"; - this.manageMods.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.manageMods.Cursor = System.Windows.Forms.Cursors.Default; - this.manageMods.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.manageMods.Location = new System.Drawing.Point(11, 152); - this.manageMods.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3); - this.manageMods.Name = "manageMods"; - this.manageMods.Size = new System.Drawing.Size(142, 23); - this.manageMods.TabIndex = 9; - this.manageMods.Text = "Open Mod Folder"; - this.manageMods.UseVisualStyleBackColor = true; - this.manageMods.Click += new System.EventHandler(this.manageMods_Click); - // - // forceRebuild - // - this.forceRebuild.AccessibleName = "Force Client Rebuild"; - this.forceRebuild.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.forceRebuild.AutoSize = true; - this.forceRebuild.Location = new System.Drawing.Point(11, 234); - this.forceRebuild.Margin = new System.Windows.Forms.Padding(2); - this.forceRebuild.Name = "forceRebuild"; - this.forceRebuild.Size = new System.Drawing.Size(119, 17); - this.forceRebuild.TabIndex = 12; - this.forceRebuild.Text = "Force Reinstallation"; - this.forceRebuild.UseVisualStyleBackColor = true; - // - // openFlagEditor - // - this.openFlagEditor.AccessibleName = "Open Flag Editor"; - this.openFlagEditor.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.openFlagEditor.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.openFlagEditor.Location = new System.Drawing.Point(11, 181); - this.openFlagEditor.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3); - this.openFlagEditor.Name = "openFlagEditor"; - this.openFlagEditor.Size = new System.Drawing.Size(142, 23); - this.openFlagEditor.TabIndex = 15; - this.openFlagEditor.Text = "Edit Fast Flags"; - this.openFlagEditor.UseVisualStyleBackColor = true; - this.openFlagEditor.Click += new System.EventHandler(this.editFVariables_Click); - // - // openStudioDirectory - // - this.openStudioDirectory.AccessibleName = "Just Open Studio Path"; - this.openStudioDirectory.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.openStudioDirectory.AutoSize = true; - this.openStudioDirectory.Location = new System.Drawing.Point(11, 212); - this.openStudioDirectory.Margin = new System.Windows.Forms.Padding(2); - this.openStudioDirectory.Name = "openStudioDirectory"; - this.openStudioDirectory.Size = new System.Drawing.Size(140, 17); - this.openStudioDirectory.TabIndex = 14; - this.openStudioDirectory.Text = "Open Working Directory"; - this.openStudioDirectory.UseVisualStyleBackColor = true; - // - // targetVersionLabel - // - this.targetVersionLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.targetVersionLabel.AutoSize = true; - this.targetVersionLabel.BackColor = System.Drawing.Color.Transparent; - this.targetVersionLabel.CausesValidation = false; - this.targetVersionLabel.Font = new System.Drawing.Font("Segoe UI", 9F); - this.targetVersionLabel.ForeColor = System.Drawing.SystemColors.ControlText; - this.targetVersionLabel.Location = new System.Drawing.Point(168, 114); - this.targetVersionLabel.Name = "targetVersionLabel"; - this.targetVersionLabel.Size = new System.Drawing.Size(83, 15); - this.targetVersionLabel.TabIndex = 17; - this.targetVersionLabel.Text = "Target Version:"; - // - // title - // - this.title.Font = new System.Drawing.Font("Segoe UI Light", 20F); - this.title.Location = new System.Drawing.Point(135, 18); - this.title.Name = "title"; - this.title.Size = new System.Drawing.Size(176, 88); - this.title.TabIndex = 20; - this.title.Text = "Roblox Studio\r\nMod Manager"; - this.title.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; - // - // targetVersion - // - this.targetVersion.AccessibleName = "Target Version"; - this.targetVersion.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.targetVersion.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.targetVersion.FormattingEnabled = true; - this.targetVersion.Items.AddRange(new object[] { - "(Use Latest)"}); - this.targetVersion.Location = new System.Drawing.Point(171, 131); - this.targetVersion.Name = "targetVersion"; - this.targetVersion.Size = new System.Drawing.Size(152, 21); - this.targetVersion.TabIndex = 18; - this.targetVersion.SelectedIndexChanged += new System.EventHandler(this.targetVersion_SelectedIndexChanged); - // - // releaseTag - // - this.releaseTag.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.releaseTag.AutoSize = true; - this.releaseTag.ForeColor = System.Drawing.Color.DarkGray; - this.releaseTag.Location = new System.Drawing.Point(266, 5); - this.releaseTag.Name = "releaseTag"; - this.releaseTag.Size = new System.Drawing.Size(0, 13); - this.releaseTag.TabIndex = 23; - this.releaseTag.TextAlign = System.Drawing.ContentAlignment.TopRight; - // - // logo - // - this.logo.BackgroundImage = global::RobloxStudioModManager.Properties.Resources.Logo; - this.logo.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom; - this.logo.Location = new System.Drawing.Point(37, 18); - this.logo.Margin = new System.Windows.Forms.Padding(2); - this.logo.Name = "logo"; - this.logo.Size = new System.Drawing.Size(90, 88); - this.logo.TabIndex = 22; - this.logo.TabStop = false; - // - // channelNameBox - // - this.channelNameBox.Location = new System.Drawing.Point(171, 176); - this.channelNameBox.Name = "channelNameBox"; - this.channelNameBox.Size = new System.Drawing.Size(152, 20); - this.channelNameBox.TabIndex = 24; - this.channelNameBox.Text = "LIVE"; - // - // channelNameTitle - // - this.channelNameTitle.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.channelNameTitle.AutoSize = true; - this.channelNameTitle.BackColor = System.Drawing.Color.Transparent; - this.channelNameTitle.CausesValidation = false; - this.channelNameTitle.Font = new System.Drawing.Font("Segoe UI", 9F); - this.channelNameTitle.ForeColor = System.Drawing.SystemColors.ControlText; - this.channelNameTitle.Location = new System.Drawing.Point(168, 158); - this.channelNameTitle.Name = "channelNameTitle"; - this.channelNameTitle.Size = new System.Drawing.Size(89, 15); - this.channelNameTitle.TabIndex = 25; - this.channelNameTitle.Text = "Channel Name:"; - // - // channelTokenTitle - // - this.channelTokenTitle.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.channelTokenTitle.AutoSize = true; - this.channelTokenTitle.BackColor = System.Drawing.Color.Transparent; - this.channelTokenTitle.CausesValidation = false; - this.channelTokenTitle.Font = new System.Drawing.Font("Segoe UI", 9F); - this.channelTokenTitle.ForeColor = System.Drawing.SystemColors.ControlText; - this.channelTokenTitle.Location = new System.Drawing.Point(168, 206); - this.channelTokenTitle.Name = "channelTokenTitle"; - this.channelTokenTitle.Size = new System.Drawing.Size(127, 15); - this.channelTokenTitle.TabIndex = 26; - this.channelTokenTitle.Text = "Channel Access Token:"; - // - // channelTokenBox - // - this.channelTokenBox.Location = new System.Drawing.Point(171, 221); - this.channelTokenBox.Name = "channelTokenBox"; - this.channelTokenBox.Size = new System.Drawing.Size(152, 20); - this.channelTokenBox.TabIndex = 27; - this.channelTokenBox.UseSystemPasswordChar = true; - this.channelTokenBox.Leave += new System.EventHandler(this.channelTokenBox_Leave); - // - // Launcher - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.BackColor = System.Drawing.SystemColors.Control; - this.ClientSize = new System.Drawing.Size(335, 274); - this.Controls.Add(this.channelTokenBox); - this.Controls.Add(this.channelTokenTitle); - this.Controls.Add(this.channelNameTitle); - this.Controls.Add(this.channelNameBox); - this.Controls.Add(this.releaseTag); - this.Controls.Add(this.logo); - this.Controls.Add(this.title); - this.Controls.Add(this.targetVersion); - this.Controls.Add(this.targetVersionLabel); - this.Controls.Add(this.openFlagEditor); - this.Controls.Add(this.openStudioDirectory); - this.Controls.Add(this.forceRebuild); - this.Controls.Add(this.manageMods); - this.Controls.Add(this.launchStudio); - this.DoubleBuffered = true; - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; - this.Icon = global::RobloxStudioModManager.Properties.Resources.Icon; - this.MaximizeBox = false; - this.Name = "Launcher"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "Roblox Studio Mod Manager"; - this.Load += new System.EventHandler(this.Launcher_Load); - ((System.ComponentModel.ISupportInitialize)(this.logo)).EndInit(); - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private System.Windows.Forms.Button launchStudio; - private System.Windows.Forms.Button manageMods; - private System.Windows.Forms.CheckBox forceRebuild; - private System.Windows.Forms.Button openFlagEditor; - private System.Windows.Forms.CheckBox openStudioDirectory; - private System.Windows.Forms.Label targetVersionLabel; - private System.Windows.Forms.Label title; - private System.Windows.Forms.ComboBox targetVersion; - private System.Windows.Forms.Label releaseTag; - private System.Windows.Forms.PictureBox logo; - private System.Windows.Forms.TextBox channelNameBox; - private System.Windows.Forms.Label channelNameTitle; - private System.Windows.Forms.Label channelTokenTitle; - private System.Windows.Forms.TextBox channelTokenBox; - } -} - diff --git a/ProjectSrc/Forms/Launcher.cs b/ProjectSrc/Forms/Launcher.cs deleted file mode 100644 index bf2bb74..0000000 --- a/ProjectSrc/Forms/Launcher.cs +++ /dev/null @@ -1,499 +0,0 @@ -using RobloxDeployHistory; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Drawing; -using System.IO; -using System.Linq; -using System.Media; -using System.Net; -using System.Windows.Forms; - -namespace RobloxStudioModManager -{ - public partial class Launcher : Form - { - private static VersionManifest versionRegistry => Program.State.VersionData; - private readonly string[] args = null; - - public Launcher(params string[] mainArgs) - { - if (mainArgs.Length > 0) - args = mainArgs; - - InitializeComponent(); - releaseTag.Text = Program.ReleaseTag; - } - - private void promptNewRelease(string releaseTag) - { - #if !DEBUG - Enabled = false; - - DialogResult result = MessageBox.Show - ( - "There's a new version of the mod manager available!\n" + - "This version is likely broken or no longer supported.\n" + - "Would you like to check it out?", - - "Update available!", - MessageBoxButtons.YesNo, - MessageBoxIcon.Information - ); - - if (result == DialogResult.Yes) - { - Process.Start($"https://www.github.com/{Program.RepoOwner}/{Program.RepoName}/releases/tag/{releaseTag}"); - Application.Exit(); - } - - Enabled = true; - #endif - } - - private async void setVersionHistory(string channelName = "LIVE", string channelToken = "") - { - // Grab the version currently being targeted. - string targetId = Program.State.TargetVersion; - const string latest = "(Use Latest)"; - - // Clear the current list of target items. - targetVersion.Items.Clear(); - targetVersion.Items.Add(latest); - - // Populate the items list using the deploy history. - var deployLogs = await StudioDeployLogs.Get(Program.AllowUnsupportedVersions, channelName, channelToken); - HashSet targets = deployLogs.CurrentLogs; - - targetVersion.Enabled = deployLogs.HasHistory; - targetVersionLabel.Enabled = deployLogs.HasHistory; - - if (deployLogs.ChannelName == channelName || deployLogs.ChannelName == "zbeta") - { - if (!string.IsNullOrEmpty(channelName)) Program.State.ChannelData.ChannelName = channelName; - if (!string.IsNullOrEmpty(channelToken)) Program.State.ChannelData.ChannelToken = channelToken; - } - else - { - MessageBox.Show("Could not fetch client version info with the channel name and token!\nEnsure you have entered them correctly.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - Program.State.ChannelData.ChannelName = "LIVE"; - Program.State.ChannelData.ChannelToken = ""; - channelNameBox.Text = "LIVE"; - channelTokenBox.Text = ""; - } - - if (deployLogs.HasHistory) - { - var items = targets - .OrderByDescending(t => t.CommitId) - .Cast() - .ToArray(); - - targetVersion.Items.AddRange(items); - } - - // Select the deploy log being targeted. - DeployLog target = targets - .Where(log => log.VersionId == targetId) - .FirstOrDefault(); - - if (target != null) - { - targetVersion.SelectedItem = target; - UseWaitCursor = false; - Enabled = true; - return; - } - - // If the target isn't valid, fallback to live. - targetVersion.SelectedItem = latest; - } - - private async void Launcher_Load(object sender, EventArgs e) - { - Enabled = false; - UseWaitCursor = true; - - if (args != null) - { - launchStudio_Click(); - Hide(); - return; - } - - using (var http = new WebClient()) - { - var get = http.DownloadStringTaskAsync(Program.BaseConfigUrl + "LatestReleaseTag.txt"); - - await get.ContinueWith(task => - { - if (task.IsFaulted) - { - MessageBox.Show("Could not fetch latest release tag!\nYou may not have an internet connection.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - return; - } - - if (!task.IsCompleted) - return; - - string releaseTag = task.Result.Trim(); - - if (releaseTag == Program.ReleaseTag) - return; - - Invoke(new Action(promptNewRelease), releaseTag); - }); - } - - setVersionHistory(); - UseWaitCursor = false; - Enabled = true; - } - - public static string getModPath() - { - string root = Path.Combine(Program.RootDir, "ModFiles"); - - if (!Directory.Exists(root)) - { - // Build a folder structure so the usage is more clear. - Directory.CreateDirectory(root); - - string[] folderPaths = new string[] - { - "BuiltInPlugins", - "ClientSettings", - - "content/avatar", - "content/fonts", - "content/models", - "content/scripts", - "content/sky", - "content/sounds", - "content/textures", - "content/translations" - }; - - foreach (string f in folderPaths) - { - string path = Path.Combine(root, f); - Directory.CreateDirectory(path); - } - } - - return root; - } - - private void manageMods_Click(object sender, EventArgs e) - { - string modPath = getModPath(); - - var open = new ProcessStartInfo() - { - FileName = modPath, - UseShellExecute = true, - Verb = "open" - }; - - Process.Start(open); - } - - private static Form createFlagWarningPrompt() - { - var warningForm = new Form() - { - Text = "WARNING: HERE BE DRAGONS", - - Width = 425, - Height = 250, - MaximizeBox = false, - MinimizeBox = false, - - FormBorderStyle = FormBorderStyle.FixedDialog, - StartPosition = FormStartPosition.CenterScreen, - - ShowInTaskbar = false - }; - - var errorIcon = new PictureBox() - { - Image = SystemIcons.Error.ToBitmap(), - Location = new Point(12, 12), - Size = new Size(32, 32), - }; - - var dontShowAgain = new CheckBox() - { - AutoSize = true, - Location = new Point(54, 145), - Text = "Do not show this warning again.", - Font = new Font("Microsoft Sans Serif", 9.75f), - }; - - var buttonPanel = new FlowLayoutPanel() - { - FlowDirection = FlowDirection.RightToLeft, - BackColor = SystemColors.ControlLight, - Padding = new Padding(4), - Dock = DockStyle.Bottom, - Size = new Size(0, 40) - }; - - var infoLabel = new Label() - { - AutoSize = true, - - Font = new Font("Microsoft Sans Serif", 9.75f), - Text = "Editing flags can make Roblox Studio unstable, and could potentially corrupt your places and game data.\n\n" + - "You should not edit them unless you are just experimenting with new features locally, and you know what you're doing.\n\n" + - "Are you sure you would like to continue?", - - Location = new Point(50, 14), - MaximumSize = new Size(350, 0), - }; - - var yes = new Button() - { - Size = new Size(100, 23), - Text = "Yes", - }; - - var no = new Button() - { - Size = new Size(100, 23), - Text = "No", - }; - - yes.Click += (sender, e) => - { - warningForm.DialogResult = DialogResult.Yes; - warningForm.Enabled = dontShowAgain.Checked; - warningForm.Close(); - }; - - no.Click += (sender, e) => - { - warningForm.DialogResult = DialogResult.No; - warningForm.Enabled = dontShowAgain.Checked; - warningForm.Close(); - }; - - buttonPanel.Controls.Add(no); - buttonPanel.Controls.Add(yes); - - warningForm.Controls.Add(errorIcon); - warningForm.Controls.Add(infoLabel); - warningForm.Controls.Add(buttonPanel); - warningForm.Controls.Add(dontShowAgain); - - return warningForm; - } - - private async void editFVariables_Click(object sender, EventArgs e) - { - bool allow = true; - - // Create a warning prompt if the user hasn't disabled this warning. - var warningDisabled = Program.State.DisableFlagWarning; - - if (!warningDisabled) - { - SystemSounds.Hand.Play(); - allow = false; - - using (Form warningPrompt = createFlagWarningPrompt()) - { - warningPrompt.ShowDialog(); - - if (warningPrompt.DialogResult == DialogResult.Yes) - { - Program.State.DisableFlagWarning = warningPrompt.Enabled; - allow = true; - } - } - } - - if (allow) - { - Enabled = false; - UseWaitCursor = true; - - var info = await StudioBootstrapper.GetCurrentVersionInfo(); - Hide(); - - await BootstrapperForm.BringUpToDate(info.VersionGuid, "Some newer flags might be missing."); - - using (FlagEditor editor = new FlagEditor()) - editor.ShowDialog(); - - Show(); - BringToFront(); - - Enabled = true; - UseWaitCursor = false; - } - } - - private async void launchStudio_Click(object sender = null, EventArgs e = null) - { - var overrideGuid = ""; - - if (args != null && args.Length > 0 && args[0].StartsWith("version-")) - overrideGuid = args[0]; - - var bootstrapper = new StudioBootstrapper - { - ForceInstall = forceRebuild.Checked, - ApplyModManagerPatches = true, - OverrideGuid = overrideGuid - }; - - Hide(); - - using (var installer = new BootstrapperForm(bootstrapper)) - await installer.Bootstrap(); - - string studioRoot = StudioBootstrapper.GetStudioDirectory(); - string modPath = getModPath(); - - var modFiles = Directory.GetFiles(modPath, "*.*", SearchOption.AllDirectories); - - foreach (string file in modFiles) - { - try - { - var info = new FileInfo(file); - var filePath = file; - var delete = false; - - if (info.Length == 0 && info.Name.StartsWith("DELETE")) - { - var dir = info.DirectoryName; - - var realName = info.Name - .Substring(6) - .TrimStart(); - - filePath = Path.Combine(dir, realName); - delete = true; - } - - string relativeFile = filePath.Replace(modPath, studioRoot); - - string relativeDir = Directory - .GetParent(relativeFile) - .ToString(); - - if (!Directory.Exists(relativeDir)) - Directory.CreateDirectory(relativeDir); - - byte[] contents = info.Length > 0 - ? File.ReadAllBytes(file) - : Array.Empty(); - - if (File.Exists(relativeFile)) - { - byte[] relative = File.ReadAllBytes(relativeFile); - - if (relative.Length == contents.Length) - if (relative.SequenceEqual(contents)) - continue; - - if (delete) - { - File.Delete(relativeFile); - continue; - } - - info.CopyTo(relativeFile, true); - } - else - { - if (delete) - continue; - - File.WriteAllBytes(relativeFile, contents); - } - } - catch - { - Console.WriteLine("Failed to overwrite {0}!", file); - } - } - - var robloxStudioInfo = new ProcessStartInfo() - { - FileName = StudioBootstrapper.GetStudioPath(), - Arguments = $"" - }; - - if (args != null) - { - string firstArg = args[0]; - - if (firstArg != null && firstArg.StartsWith("roblox-studio", Program.StringFormat)) - { - // Arguments were passed by URI. - robloxStudioInfo.Arguments = firstArg; - } - else - { - // Arguments were passed directly. - for (int i = 0; i < args.Length; i++) - { - string arg = args[i]; - - if (arg.Contains(' ')) - arg = $"\"{arg}\""; - - robloxStudioInfo.Arguments += ' ' + arg; - } - } - } - - - if (openStudioDirectory.Checked) - { - Process.Start(studioRoot); - } - else - { - string currentVersion = versionRegistry.VersionGuid; - versionRegistry.LastExecutedVersion = currentVersion; - - Process.Start(robloxStudioInfo); - } - - Program.SaveState(); - Environment.Exit(Environment.ExitCode); - } - - private void targetVersion_SelectedIndexChanged(object sender, EventArgs e) - { - if (targetVersion.SelectedIndex == 0) - { - Program.State.TargetVersion = ""; - return; - } - - if (!(targetVersion.SelectedItem is DeployLog target)) return; - Program.State.TargetVersion = target.VersionId; - - if (target.Unsupported) - { - MessageBox.Show( - "This version of Roblox Studio is no longer supported!\nYou are strongly advised against using it in the future.\nNo technical support will be provided, use it at your own risk!", - "Tread Lightly!", - - MessageBoxButtons.OK, - MessageBoxIcon.Warning - ); - } - } - - private void channelTokenBox_Leave(object sender, EventArgs e) - { - setVersionHistory(channelNameBox.Text, channelTokenBox.Text); - } - } -} diff --git a/ProjectSrc/Properties/AssemblyInfo.cs b/ProjectSrc/Properties/AssemblyInfo.cs deleted file mode 100644 index 7a46b03..0000000 --- a/ProjectSrc/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Resources; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Roblox Studio Mod Manager")] -[assembly: AssemblyDescription("An unofficial, open-source, custom bootstrapper for Roblox Studio that provides more flexibility to power users looking to make experimental customizations to Roblox Studio, and test new features before they are available to the public.")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Roblox Studio Mod Manager")] -[assembly: AssemblyCopyright("")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("c5691c74-2875-4593-b5f3-fa135fdb7b82")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] -[assembly: NeutralResourcesLanguage("en-US")] diff --git a/ProjectSrc/Properties/Resources.Designer.cs b/ProjectSrc/Properties/Resources.Designer.cs deleted file mode 100644 index 3372d72..0000000 --- a/ProjectSrc/Properties/Resources.Designer.cs +++ /dev/null @@ -1,83 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace RobloxStudioModManager.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RobloxStudioModManager.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). - /// - internal static System.Drawing.Icon Icon { - get { - object obj = ResourceManager.GetObject("Icon", resourceCulture); - return ((System.Drawing.Icon)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap Logo { - get { - object obj = ResourceManager.GetObject("Logo", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - } -} diff --git a/ProjectSrc/Properties/Resources.resx b/ProjectSrc/Properties/Resources.resx deleted file mode 100644 index 20e6afc..0000000 --- a/ProjectSrc/Properties/Resources.resx +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - ..\Resources\Icon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\Logo.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - \ No newline at end of file diff --git a/ProjectSrc/RobloxStudioModManager.csproj b/ProjectSrc/RobloxStudioModManager.csproj deleted file mode 100644 index 487e3d7..0000000 --- a/ProjectSrc/RobloxStudioModManager.csproj +++ /dev/null @@ -1,291 +0,0 @@ - - - - - Debug - AnyCPU - {FAD2621F-B280-4D6D-A260-F410C5B06E0C} - WinExe - Properties - RobloxStudioModManager - RobloxStudioModManager - v4.7.2 - 512 - false - - - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - https://www.twitter.com/MaxGee1019 - Roblox Studio Mod Manager - CloneTrooper1019 - 0 - 1.0.0.%2a - false - true - - - x64 - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - Off - true - - - x64 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - Resources\Icon.ico - - - false - - - true - - - LocalIntranet - - - false - - - - - - - - - - - - bin\Internal\ - TRACE;ROBLOX_INTERNAL - true - pdbonly - x64 - 7.3 - prompt - true - - - app.manifest - - - true - bin\x64\Debug\ - DEBUG;TRACE - full - x64 - Off - 7.3 - prompt - true - - - bin\x64\Release\ - TRACE - true - pdbonly - x64 - 7.3 - prompt - true - - - bin\x64\Internal\ - TRACE;ROBLOX_INTERNAL - true - pdbonly - x64 - 7.3 - prompt - true - - - bin\DebugInternal\ - TRACE;ROBLOX_INTERNAL - true - pdbonly - x64 - 7.3 - prompt - true - - - bin\x64\DebugInternal\ - TRACE;ROBLOX_INTERNAL - false - pdbonly - x64 - 7.3 - prompt - true - - - - - - - - - - - - - - - - - - - - - Form - - - FlagCreator.cs - - - - - - - - - - - - - - - - Form - - - BootstrapperForm.cs - - - Form - - - FlagEditor.cs - - - True - True - Resources.resx - - - Form - - - Launcher.cs - - - - - ResXFileCodeGenerator - Designer - Resources.Designer.cs - - - - - - - - - - False - Microsoft .NET Framework 4.5 %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - false - - - - - - - - - - - {1ce1a9df-c2ff-49c4-9b7c-792c962c339f} - RobloxDeployHistory - - - - - - - - 4.1.0 - - - 1.0.9 - - - 4.7.0 - - - 13.0.1 - - - 5.1.0 - - - - - if not $(ConfigurationName) == Release goto :end -echo Copying release build. -copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\$(TargetFileName)" -echo Done! -:end - - - if not $(ConfigurationName) == Release goto :end -echo Clearing instances of $(TargetFileName) -taskkill /f /im $(TargetFileName) /fi "memusage gt 2" -:end - - - \ No newline at end of file diff --git a/ProjectSrc/RobloxStudioModManager.sln b/ProjectSrc/RobloxStudioModManager.sln index bbcc388..400c9ae 100644 --- a/ProjectSrc/RobloxStudioModManager.sln +++ b/ProjectSrc/RobloxStudioModManager.sln @@ -1,9 +1,9 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.3.32929.385 +# Visual Studio Version 18 +VisualStudioVersion = 18.7.11911.148 stable MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RobloxStudioModManager", "RobloxStudioModManager.csproj", "{FAD2621F-B280-4D6D-A260-F410C5B06E0C}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RobloxStudioModManager.WinUI", "WinUI\RobloxStudioModManager.WinUI.csproj", "{4E0D71E5-26EF-43A0-9E7E-DDBAC358C5F1}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Include", "Include", "{599F227F-86C3-4CB6-B12D-6CBF086B240E}" EndProject @@ -13,32 +13,22 @@ Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 - Internal|Any CPU = Internal|Any CPU - Internal|x64 = Internal|x64 Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {FAD2621F-B280-4D6D-A260-F410C5B06E0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FAD2621F-B280-4D6D-A260-F410C5B06E0C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FAD2621F-B280-4D6D-A260-F410C5B06E0C}.Debug|x64.ActiveCfg = Debug|x64 - {FAD2621F-B280-4D6D-A260-F410C5B06E0C}.Debug|x64.Build.0 = Debug|x64 - {FAD2621F-B280-4D6D-A260-F410C5B06E0C}.Internal|Any CPU.ActiveCfg = Internal|Any CPU - {FAD2621F-B280-4D6D-A260-F410C5B06E0C}.Internal|Any CPU.Build.0 = Internal|Any CPU - {FAD2621F-B280-4D6D-A260-F410C5B06E0C}.Internal|x64.ActiveCfg = Internal|x64 - {FAD2621F-B280-4D6D-A260-F410C5B06E0C}.Internal|x64.Build.0 = Internal|x64 - {FAD2621F-B280-4D6D-A260-F410C5B06E0C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FAD2621F-B280-4D6D-A260-F410C5B06E0C}.Release|Any CPU.Build.0 = Release|Any CPU - {FAD2621F-B280-4D6D-A260-F410C5B06E0C}.Release|x64.ActiveCfg = Release|x64 - {FAD2621F-B280-4D6D-A260-F410C5B06E0C}.Release|x64.Build.0 = Release|x64 + {4E0D71E5-26EF-43A0-9E7E-DDBAC358C5F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E0D71E5-26EF-43A0-9E7E-DDBAC358C5F1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E0D71E5-26EF-43A0-9E7E-DDBAC358C5F1}.Debug|x64.ActiveCfg = Debug|Any CPU + {4E0D71E5-26EF-43A0-9E7E-DDBAC358C5F1}.Debug|x64.Build.0 = Debug|Any CPU + {4E0D71E5-26EF-43A0-9E7E-DDBAC358C5F1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4E0D71E5-26EF-43A0-9E7E-DDBAC358C5F1}.Release|Any CPU.Build.0 = Release|Any CPU + {4E0D71E5-26EF-43A0-9E7E-DDBAC358C5F1}.Release|x64.ActiveCfg = Release|Any CPU + {4E0D71E5-26EF-43A0-9E7E-DDBAC358C5F1}.Release|x64.Build.0 = Release|Any CPU {1CE1A9DF-C2FF-49C4-9B7C-792C962C339F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1CE1A9DF-C2FF-49C4-9B7C-792C962C339F}.Debug|Any CPU.Build.0 = Debug|Any CPU {1CE1A9DF-C2FF-49C4-9B7C-792C962C339F}.Debug|x64.ActiveCfg = Debug|x64 {1CE1A9DF-C2FF-49C4-9B7C-792C962C339F}.Debug|x64.Build.0 = Debug|x64 - {1CE1A9DF-C2FF-49C4-9B7C-792C962C339F}.Internal|Any CPU.ActiveCfg = Debug|Any CPU - {1CE1A9DF-C2FF-49C4-9B7C-792C962C339F}.Internal|Any CPU.Build.0 = Debug|Any CPU - {1CE1A9DF-C2FF-49C4-9B7C-792C962C339F}.Internal|x64.ActiveCfg = Release|x64 - {1CE1A9DF-C2FF-49C4-9B7C-792C962C339F}.Internal|x64.Build.0 = Release|x64 {1CE1A9DF-C2FF-49C4-9B7C-792C962C339F}.Release|Any CPU.ActiveCfg = Release|Any CPU {1CE1A9DF-C2FF-49C4-9B7C-792C962C339F}.Release|Any CPU.Build.0 = Release|Any CPU {1CE1A9DF-C2FF-49C4-9B7C-792C962C339F}.Release|x64.ActiveCfg = Release|x64 diff --git a/ProjectSrc/Utility/BootstrapProgressStyle.cs b/ProjectSrc/Utility/BootstrapProgressStyle.cs new file mode 100644 index 0000000..13d523c --- /dev/null +++ b/ProjectSrc/Utility/BootstrapProgressStyle.cs @@ -0,0 +1,8 @@ +namespace RobloxStudioModManager +{ + public enum BootstrapProgressStyle + { + Determinate, + Indeterminate + } +} diff --git a/ProjectSrc/Utility/FlagManager.cs b/ProjectSrc/Utility/FlagManager.cs new file mode 100644 index 0000000..6b32a8d --- /dev/null +++ b/ProjectSrc/Utility/FlagManager.cs @@ -0,0 +1,42 @@ +using System; +using System.IO; + +using Newtonsoft.Json.Linq; + +namespace RobloxStudioModManager +{ + // Agnostic flag application logic. + public static class FlagManager + { + public static void ApplyFlags() + { + var json = new JObject(); + var flagRegistry = Program.State.FlagEditor; + + foreach (string flagName in flagRegistry.Keys) + { + var flag = flagRegistry[flagName]; + string value = flag.Value; + + var token = JToken.FromObject(value); + json.Add(flagName, token); + }; + + string file = json.ToString(); + string studioDir = StudioBootstrapper.GetStudioDirectory(); + string localAppData = Environment.GetEnvironmentVariable("LocalAppData"); + + string clientSettings_DEPRECATED = Path.Combine(studioDir, "ClientSettings"); + Directory.CreateDirectory(clientSettings_DEPRECATED); + + string filePath_DEPRECATED = Path.Combine(clientSettings_DEPRECATED, "ClientAppSettings.json"); + File.WriteAllText(filePath_DEPRECATED, file); + + string clientSettings_NEW = Path.Combine(localAppData, "Roblox", "ClientSettings"); + Directory.CreateDirectory(clientSettings_NEW); + + string filePath_NEW = Path.Combine(clientSettings_NEW, "ClientAppSettings.json"); + File.WriteAllText(filePath_NEW, file); + } + } +} diff --git a/ProjectSrc/Program.cs b/ProjectSrc/Utility/ModManagerEnvironment.cs similarity index 92% rename from ProjectSrc/Program.cs rename to ProjectSrc/Utility/ModManagerEnvironment.cs index 2dafe55..6ad91f1 100644 --- a/ProjectSrc/Program.cs +++ b/ProjectSrc/Utility/ModManagerEnvironment.cs @@ -1,9 +1,9 @@ using System; +using System.Diagnostics; using System.Globalization; using System.Collections.Generic; using System.IO; using System.Net; -using System.Windows.Forms; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -12,7 +12,8 @@ namespace RobloxStudioModManager { - static class Program + // Moved some of the Program here, to make the functionality more agnostic. + static partial class Program { public const string RepoBranch = "main"; public const string RepoOwner = "MaximumADHD"; @@ -53,7 +54,7 @@ public static void UpdateStudioRegistryProtocols(string studioPath) { const string _ = ""; // Default empty key/value. - string modManagerPath = Application.ExecutablePath + string modManagerPath = Process.GetCurrentProcess().MainModule.FileName .Replace('"', ' ') .Trim(); @@ -138,15 +139,9 @@ public static void SaveState() File.WriteAllText(stateFile, json); } - static void OnExiting(object sender, EventArgs e) + // Loads/migrates persisted app state and parses launch arguments. + public static string[] Initialize(string[] rawArgs) { - SaveState(); - } - - [STAThread] - static void Main(string[] rawArgs) - { - // Initialize application state. var localAppData = Environment.GetEnvironmentVariable("localappdata"); RootDir = Path.Combine(localAppData, "Roblox Studio Mod Manager"); @@ -194,19 +189,14 @@ static void Main(string[] rawArgs) var args = unprocessedArgs.ToArray(); State = JsonConvert.DeserializeObject(json); - + if (State == null) State = new ModManagerState(); // Make sure HTTPS uses TLS 1.2 ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; - // Standard windows form jank - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - - Application.ApplicationExit += new EventHandler(OnExiting); - Application.Run(new Launcher(args)); + return args; } } } diff --git a/ProjectSrc/WinUI/App.xaml b/ProjectSrc/WinUI/App.xaml new file mode 100644 index 0000000..10cedc8 --- /dev/null +++ b/ProjectSrc/WinUI/App.xaml @@ -0,0 +1,22 @@ + + + + + + + + + + #E4212D + #E9424C + #ED6169 + #F28086 + #C41E29 + #A31A23 + #82151C + + + diff --git a/ProjectSrc/WinUI/App.xaml.cs b/ProjectSrc/WinUI/App.xaml.cs new file mode 100644 index 0000000..63ebb26 --- /dev/null +++ b/ProjectSrc/WinUI/App.xaml.cs @@ -0,0 +1,27 @@ +using Microsoft.UI.Xaml; + +// Using RobloxStudioModManager.WinUI here instead of just RobloxStudioModManager +// to prevent shadowing since WinUI compiler generates its own Program class. +namespace RobloxStudioModManager.WinUI +{ + public partial class App : Application + { + private Window mainWindow; + + public App() + { + InitializeComponent(); + } + + protected override void OnLaunched(LaunchActivatedEventArgs args) + { + var rawArgs = System.Environment.GetCommandLineArgs(); + var unprocessedArgs = RobloxStudioModManager.Program.Initialize(rawArgs[1..]); + + System.AppDomain.CurrentDomain.ProcessExit += (sender, e) => RobloxStudioModManager.Program.SaveState(); + + mainWindow = new MainWindow(unprocessedArgs); + mainWindow.Activate(); + } + } +} diff --git a/ProjectSrc/Resources/Icon.ico b/ProjectSrc/WinUI/Assets/Icon.ico similarity index 100% rename from ProjectSrc/Resources/Icon.ico rename to ProjectSrc/WinUI/Assets/Icon.ico diff --git a/ProjectSrc/Resources/Logo.png b/ProjectSrc/WinUI/Assets/Logo.png similarity index 100% rename from ProjectSrc/Resources/Logo.png rename to ProjectSrc/WinUI/Assets/Logo.png diff --git a/ProjectSrc/WinUI/BackdropHelper.cs b/ProjectSrc/WinUI/BackdropHelper.cs new file mode 100644 index 0000000..8d2c055 --- /dev/null +++ b/ProjectSrc/WinUI/BackdropHelper.cs @@ -0,0 +1,10 @@ +using System; + +namespace RobloxStudioModManager.WinUI +{ + internal static class BackdropHelper + { + // Windows 11 build numbers start at 22000. + public static bool IsWindows11 => Environment.OSVersion.Version.Build >= 22000; + } +} diff --git a/ProjectSrc/WinUI/BootstrapWindow.xaml b/ProjectSrc/WinUI/BootstrapWindow.xaml new file mode 100644 index 0000000..33c587a --- /dev/null +++ b/ProjectSrc/WinUI/BootstrapWindow.xaml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ProjectSrc/WinUI/BootstrapWindow.xaml.cs b/ProjectSrc/WinUI/BootstrapWindow.xaml.cs new file mode 100644 index 0000000..6fee244 --- /dev/null +++ b/ProjectSrc/WinUI/BootstrapWindow.xaml.cs @@ -0,0 +1,255 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.ObjectModel; +using System.Diagnostics.Contracts; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +using Microsoft.UI.Windowing; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Media; + +using RobloxStudioModManager; + +namespace RobloxStudioModManager.WinUI +{ + public sealed partial class BootstrapWindow : Window + { + public StudioBootstrapper Bootstrapper { get; } + + private ConcurrentBag logQueue = new ConcurrentBag(); + private readonly ObservableCollection logLines = new ObservableCollection(); + private readonly bool exitOnClose; + private DispatcherTimer progressTimer; + private bool programmaticClose; + + // Initializes the main bootstrap window. + public BootstrapWindow(StudioBootstrapper bootstrapper, bool exitWhenClosed = false) + { + Contract.Requires(bootstrapper != null); + InitializeComponent(); + + Bootstrapper = bootstrapper; + exitOnClose = exitWhenClosed; + + Title = "Roblox Studio Bootstrapper"; + ApplyBackdrop(); + configureWindow(); + + LogListView.ItemsSource = logLines; + + bootstrapper.EchoFeed += new MessageFeed(echo); + bootstrapper.StatusFeed += new MessageFeed(setStatus); + bootstrapper.ConfirmFeed += new ConfirmPrompt(confirm); + + AppWindow.Closing += appWindow_Closing; + Closed += bootstrapWindow_Closed; + + Activate(); + } + + // Applies a pretty backdrop to the background. + private void ApplyBackdrop() + { + SystemBackdrop = BackdropHelper.IsWindows11 + ? (SystemBackdrop)new MicaBackdrop() + : new DesktopAcrylicBackdrop(); + } + + private void configureWindow() + { + AppWindow.SetIcon(Path.Combine(AppContext.BaseDirectory, "Assets", "Icon.ico")); + + if (AppWindow.Presenter is OverlappedPresenter presenter) + { + presenter.IsResizable = false; + presenter.IsMaximizable = false; + presenter.IsMinimizable = true; + presenter.IsAlwaysOnTop = true; + } + + WindowPositioning.ResizeAndCenter(AppWindow, 560, 340); + } + + public async Task Bootstrap() + { + var state = RobloxStudioModManager.Program.State; + var targetVersion = state.TargetVersion; + + progressTimer = new DispatcherTimer + { + Interval = TimeSpan.FromMilliseconds(100) + }; + + progressTimer.Tick += (sender, args) => + { + var progress = Bootstrapper.Progress; + Progress.IsIndeterminate = Bootstrapper.ProgressBarStyle == BootstrapProgressStyle.Indeterminate; + + var maxProgress = Bootstrapper.MaxProgress; + Progress.Maximum = maxProgress; + + if (progress > maxProgress) + { + Progress.Value = Math.Max(0, maxProgress - 1); + return; + } + + if (!logQueue.IsEmpty) + { + var newQueue = new ConcurrentBag(); + var drained = Interlocked.Exchange(ref logQueue, newQueue); + + foreach (var line in drained) + logLines.Add(line); + + LogListView.ScrollIntoView(logLines[logLines.Count - 1]); + } + + Progress.Value = Math.Min(progress, maxProgress); + }; + + progressTimer.Start(); + + var bootstrap = Bootstrapper.Bootstrap(targetVersion); + await bootstrap.ConfigureAwait(true); + } + + // Closes the window without triggering the "installation hasn't + // finished" confirmation prompt. + public void RequestClose() + { + programmaticClose = true; + Close(); + } + + public static async Task BringUpToDate(string expectedVersion, string updateReason, XamlRoot xamlRoot) + { + var versionData = RobloxStudioModManager.Program.State.VersionData; + string currentVersion = versionData.VersionGuid; + + if (currentVersion != expectedVersion) + { + bool proceed = true; + + if (!string.IsNullOrEmpty(currentVersion)) + { + var dialog = new ContentDialog + { + XamlRoot = xamlRoot, + Title = "Out of date!", + + Content = "Roblox Studio is out of date!\n" + + updateReason + + "\nWould you like to update now?", + + PrimaryButtonText = "Yes", + CloseButtonText = "No", + DefaultButton = ContentDialogButton.Primary + }; + + var result = await dialog.ShowWithSoundAsync(); + proceed = result == ContentDialogResult.Primary; + } + + if (proceed) + { + var bootstrapper = new StudioBootstrapper(); + var installer = new BootstrapWindow(bootstrapper); + + await installer.Bootstrap(); + installer.RequestClose(); + } + } + } + + private void setStatus(string status) + { + if (DispatcherQueue.HasThreadAccess) + StatusText.Text = status; + else + DispatcherQueue.TryEnqueue(() => StatusText.Text = status); + } + + private void echo(string msg) + { + logQueue.Add(msg); + } + + // Backs StudioBootstrapper.ConfirmFeed. ContentDialog.ShowAsync() must + // run on this window's UI thread, so this always marshals through + // DispatcherQueue rather than assuming the caller is already there. + private Task confirm(string message, string title) + { + var tcs = new TaskCompletionSource(); + + bool enqueued = DispatcherQueue.TryEnqueue(async () => + { + try + { + var dialog = new ContentDialog + { + XamlRoot = Content.XamlRoot, + Title = title, + Content = message, + PrimaryButtonText = "OK", + CloseButtonText = "Cancel", + DefaultButton = ContentDialogButton.Primary + }; + + var result = await dialog.ShowWithSoundAsync(); + tcs.SetResult(result == ContentDialogResult.Primary); + } + catch (Exception ex) + { + tcs.SetException(ex); + } + }); + + if (!enqueued) + tcs.SetResult(true); + + return tcs.Task; + } + + private async void appWindow_Closing(AppWindow sender, AppWindowClosingEventArgs args) + { + if (programmaticClose) + return; + + // WinUI doesn't have CloseReason like WinForms, + // so we pause the close, ask and then either let it through or just cancel it. + args.Cancel = true; + + var dialog = new ContentDialog + { + XamlRoot = Content.XamlRoot, + Title = "Warning", + + Content = "The installation has not finished yet!\n" + + "Closing this window will exit the mod manager.\n" + + "Are you sure you want to continue?", + + PrimaryButtonText = "Yes", + CloseButtonText = "No", + DefaultButton = ContentDialogButton.Close + }; + + var result = await dialog.ShowWithSoundAsync(); + + if (result == ContentDialogResult.Primary) + Environment.Exit(0); + } + + private void bootstrapWindow_Closed(object sender, WindowEventArgs args) + { + progressTimer?.Stop(); + RobloxStudioModManager.Program.SaveState(); + + if (exitOnClose) + Environment.Exit(0); + } + } +} diff --git a/ProjectSrc/WinUI/FlagCreatorDialog.xaml b/ProjectSrc/WinUI/FlagCreatorDialog.xaml new file mode 100644 index 0000000..c325fc1 --- /dev/null +++ b/ProjectSrc/WinUI/FlagCreatorDialog.xaml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ProjectSrc/WinUI/FlagCreatorDialog.xaml.cs b/ProjectSrc/WinUI/FlagCreatorDialog.xaml.cs new file mode 100644 index 0000000..9692f42 --- /dev/null +++ b/ProjectSrc/WinUI/FlagCreatorDialog.xaml.cs @@ -0,0 +1,44 @@ +using System.Text.RegularExpressions; + +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; + +using RobloxStudioModManager; + +namespace RobloxStudioModManager.WinUI +{ + public sealed partial class FlagCreatorDialog : ContentDialog + { + private static readonly string[] classes = { "F", "DF", "SF" }; + + public CustomFlag Result { get; private set; } + + public FlagCreatorDialog() + { + InitializeComponent(); + FlagClassBox.SelectedIndex = 0; + FlagTypeBox.SelectedIndex = 0; + } + + private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) + { + string classType = classes[FlagClassBox.SelectedIndex]; + string typeItem = ((ComboBoxItem)FlagTypeBox.SelectedItem).Content.ToString(); + string type = classType + typeItem; + string name = Regex.Replace(FlagNameBox.Text, "[^A-z0-9_]", ""); + + if (FlagNameBox.Text != name) + FlagNameBox.Text = name; + + if (string.IsNullOrEmpty(name)) + { + ErrorText.Text = $"Please enter a name for the {type}!"; + ErrorText.Visibility = Visibility.Visible; + args.Cancel = true; + return; + } + + Result = new CustomFlag(type, name); + } + } +} diff --git a/ProjectSrc/WinUI/FlagEditorWindow.xaml b/ProjectSrc/WinUI/FlagEditorWindow.xaml new file mode 100644 index 0000000..eeeab48 --- /dev/null +++ b/ProjectSrc/WinUI/FlagEditorWindow.xaml @@ -0,0 +1,212 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +