示例#1
0
文件: Share.cs 项目: HJfod/gdtools
            public Share()
            {
                this.Name = "Sharing";
                this.Dock = DockStyle.Fill;
                Meth.HandleTheme(this);

                ImportLeveLArea          = new FlowLayoutPanel();
                ImportLeveLArea.Dock     = DockStyle.Fill;
                ImportLeveLArea.AutoSize = true;

                ExportSelect              = new Elem.Select();
                ExportSelect.DoubleClick += (s, e) => ViewInfo();

                foreach (dynamic lvl in GDTools.GetLevelList(null, null, true))
                {
                    ExportSelect.AddItem(lvl.Name);
                }

                ExportCompressed          = new CheckBox();
                ExportCompressed.Text     = "Export compressed (.gmdc)";
                ExportCompressed.AutoSize = true;

                RefreshDiv          = new TableLayoutPanel();
                RefreshDiv.AutoSize = true;
                RefreshDiv.Visible  = false;

                RefreshDiv.Controls.Add(new Elem.Text("After importing all you want, make sure to refresh data in order to use the app further."));
                RefreshDiv.Controls.Add(new Elem.But("Refresh", (s, e) => Program.MainForm.FullReload()));

                FlowLayoutPanel ExportControls = new FlowLayoutPanel();

                ExportControls.AutoSize = true;

                ExportControls.Controls.Add(new Elem.But("Export", (s, e) => ExportLevel(), "Exports all the level(s) you've selected on the list"));
                ExportControls.Controls.Add(new Elem.But("View", (s, e) => ViewInfo(), "Shows info for the topmost level you've selected on the list."));

                this.Controls.Add(ExportSelect);
                this.Controls.Add(ExportControls);
                this.Controls.Add(ExportCompressed);
                this.Controls.Add(new Elem.NewLine());
                this.Controls.Add(new Elem.But("Help", (s, e) => Pages.SettingPage.ShowHelp("share")));
                this.Controls.Add(new Elem.SectionBreak());
                this.Controls.Add(new Elem.NewLine());
                this.Controls.Add(new Elem.But("Import", (s, e) => OpenImport(), "Opens a file browsing dialog where you can select level(s) to add to imports."));
                this.Controls.Add(RefreshDiv);
                this.Controls.Add(ImportLeveLArea);
            }
示例#2
0
文件: Collab.cs 项目: HJfod/gdtools
            public Collabs()
            {
                this.Name = "Collab";
                this.Dock = DockStyle.Fill;
                Meth.HandleTheme(this);

                TableLayoutPanel con = new TableLayoutPanel();

                con.AutoSize = true;
                con.Visible  = Settings.DevMode;

                MergeList = new Elem.Select(false);
                MergeBase = new Elem.Text("Base not selected");

                FlowLayoutPanel MergeControls = new FlowLayoutPanel();

                MergeControls.AutoSize = true;

                MergeControls.Controls.Add(new Elem.But("Set base", (s, e) => {
                    Elem.ChooseForm Select = new Elem.ChooseForm("Select base source",
                                                                 new string[] { "Set base from file", "Set base from local levels", "Set base by ID" });

                    Select.Show();

                    Select.Finish += res => {
                        if (res == 0)
                        {
                            using (OpenFileDialog ofd = new OpenFileDialog()) {
                                ofd.InitialDirectory = "c:\\";
                                ofd.Filter           = GDTools.Ext.Filter;
                                ofd.FilterIndex      = 1;
                                ofd.RestoreDirectory = true;
                                ofd.Multiselect      = true;

                                if (ofd.ShowDialog() == DialogResult.OK)
                                {
                                    foreach (string file in ofd.FileNames)
                                    {
                                        Elem.MsgBox LoadInfo = new Elem.MsgBox("Loading...");
                                        LoadInfo.Show();
                                        AddBase(file);
                                        LoadInfo.Close();
                                        LoadInfo.Dispose();
                                    }
                                }
                            }
                        }
                        else if (res == 1)
                        {
                            Form Choose = new Form();
                            Choose.Text = "Double-click to select";
                            Choose.Size = new Size(400, 300);
                            Meth.HandleTheme(Choose);

                            Elem.Select ExportSelect = new Elem.Select(false);

                            EventHandler Pick = (s, e) => {
                                if (ExportSelect.SelectedItem == null)
                                {
                                    return;
                                }
                                AddBase(((Elem.Select.SelectItem)ExportSelect.SelectedItem).Text);
                                Choose.Close();
                                Choose.Dispose();
                            };

                            ExportSelect.DoubleClick += Pick;

                            foreach (dynamic lvl in GDTools.GetLevelList())
                            {
                                ExportSelect.AddItem(lvl.Name);
                            }

                            Choose.Controls.Add(ExportSelect);

                            Choose.Show();
                        }
                        else if (res == 2)
                        {
                            Elem.ChooseForm c = new Elem.ChooseForm("Type Level ID",
                                                                    new string[] { "IS-INPUT::INT", "::Add", "Cancel" },
                                                                    "Type in level ID"
                                                                    );

                            c.Show();

                            c.FinishStr += resc => {
                                if (resc != "")
                                {
                                    Elem.MsgBox LoadInfo = new Elem.MsgBox("Loading...");
                                    LoadInfo.Show();

                                    string r = GDTools.RequestGDLevel(resc);

                                    if (r.StartsWith("-"))
                                    {
                                        MessageBox.Show($"Error: {GDTools.VerifyRequest(r)}", "Could not get level!");
                                    }

                                    AddBase($"{resc} ({GDTools.GetRequestKey(r, "2")})");

                                    LoadInfo.Dispose();
                                }
                            };
                        }
                    };
                }));
                MergeControls.Controls.Add(new Elem.But("Add part(s)", (s, e) => {
                    Elem.ChooseForm Select = new Elem.ChooseForm("Select part source",
                                                                 new string[] { "Add part(s) from file", "Add part(s) from local levels", "Add part(s) by ID" });

                    Select.Show();

                    Select.Finish += res => {
                        if (res == 0)
                        {
                            using (OpenFileDialog ofd = new OpenFileDialog()) {
                                ofd.InitialDirectory = "c:\\";
                                ofd.Filter           = GDTools.Ext.Filter;
                                ofd.FilterIndex      = 1;
                                ofd.RestoreDirectory = true;
                                ofd.Multiselect      = true;

                                if (ofd.ShowDialog() == DialogResult.OK)
                                {
                                    foreach (string file in ofd.FileNames)
                                    {
                                        Elem.MsgBox LoadInfo = new Elem.MsgBox("Loading...");
                                        LoadInfo.Show();
                                        AddMerge(file);
                                        LoadInfo.Close();
                                        LoadInfo.Dispose();
                                    }
                                }
                            }
                        }
                        else if (res == 1)
                        {
                            Form Choose = new Form();
                            Choose.Text = "Double-click to select";
                            Choose.Size = new Size(400, 300);
                            Meth.HandleTheme(Choose);

                            Elem.Select ExportSelect = new Elem.Select();

                            EventHandler Pick = (s, e) => {
                                if (ExportSelect.SelectedItems[0] == null)
                                {
                                    return;
                                }
                                foreach (Elem.Select.SelectItem x in ExportSelect.SelectedItems)
                                {
                                    AddMerge(x.Text);
                                }
                                Choose.Close();
                                Choose.Dispose();
                            };

                            ExportSelect.DoubleClick += Pick;

                            foreach (dynamic lvl in GDTools.GetLevelList())
                            {
                                ExportSelect.AddItem(lvl.Name);
                            }

                            Choose.Controls.Add(new Elem.Div(new Control[] {
                                ExportSelect,
                                new Elem.But("Select", Pick)
                            }));

                            Choose.ShowDialog(Select);
                        }
                        else if (res == 2)
                        {
                            Elem.ChooseForm c = new Elem.ChooseForm("Type Level ID(s)",
                                                                    new string[] { "IS-INPUT-BIG::INS", "::Add", "Cancel" },
                                                                    "Type in level ID(s) (Separated by spaces)"
                                                                    );

                            c.Show();

                            c.FinishStr += resc => {
                                if (resc != "")
                                {
                                    int i          = 0;
                                    string[] rescs = resc.Split(" ");
                                    foreach (string ress in rescs)
                                    {
                                        i++;
                                        Elem.MsgBox LoadInfo = new Elem.MsgBox($"Loading ({i}/{rescs.Length})...");
                                        LoadInfo.Show();

                                        if (ress.Length < 3)
                                        {
                                            LoadInfo.Dispose();
                                            continue;
                                        }

                                        string r = GDTools.RequestGDLevel(ress);

                                        if (r.StartsWith("-"))
                                        {
                                            MessageBox.Show($"Error with {ress}: {GDTools.VerifyRequest(r)}", "Could not get level!");
                                            LoadInfo.Dispose();
                                            continue;
                                        }

                                        AddMerge($"{ress} ({GDTools.GetRequestKey(r, "2")})");

                                        LoadInfo.Dispose();
                                    }
                                }
                            };
                        }
                    };
                }));
                MergeControls.Controls.Add(new Elem.But("Remove part", (s, e) => {
                    if (MergeList.SelectedItem == null)
                    {
                        return;
                    }
                    MergeList.Items.Remove(MergeList.SelectedItem);
                }));
                MergeControls.Controls.Add(new Elem.But("Merge", (s, e) => {
                    string err = MergeParts();
                    if (err.Length > 0)
                    {
                        MessageBox.Show(err, "Error merging");
                    }
                }));

                CheckBox UseReferenceToggle = new CheckBox();

                UseReferenceToggle.Text     = "Use reference objects";
                UseReferenceToggle.AutoSize = true;
                UseReferenceToggle.Checked  = UseReferenceObjects;
                UseReferenceToggle.Click   += (s, e) =>
                                              UseReferenceObjects = UseReferenceToggle.Checked;

                CheckBox MergeLinkToggle = new CheckBox();

                MergeLinkToggle.Text                           = "Link part objects";
                MergeLinkToggle.AutoSize                       = true;
                MergeLinkToggle.Click                         += (s, e) =>
                                                     MergeLink = MergeLinkToggle.Checked;

                CheckBox AutoReassignToggle = new CheckBox();

                AutoReassignToggle.Text     = "Reassign groups and colours";
                AutoReassignToggle.AutoSize = true;
                AutoReassignToggle.Checked  = AutoReassignGroups;
                AutoReassignToggle.Click   += (s, e) =>
                                              AutoReassignGroups = AutoReassignToggle.Checked;

                con.Controls.Add(new Elem.Text("Part merging"));
                con.Controls.Add(MergeList);
                con.Controls.Add(MergeBase);
                con.Controls.Add(MergeControls);
                con.Controls.Add(MergeLinkToggle);
                con.Controls.Add(AutoReassignToggle);
                con.Controls.Add(UseReferenceToggle);

                this.Controls.Add(con);
                if (!Settings.DevMode)
                {
                    this.Controls.Add(new Elem.DevToolWarning((s, e) => { con.Visible = true; }));
                }
            }
示例#3
0
文件: Backups.cs 项目: HJfod/gdtools
            public Backups()
            {
                this.Name = "Backups";
                this.Dock = DockStyle.Fill;
                Meth.HandleTheme(this);

                EventHandler ViewBackup = (s, e) => {
                    if (BackupSelect.SelectedItem != null)
                    {
                        Elem.Select.SelectItem backup = (Elem.Select.SelectItem)BackupSelect.SelectedItem;

                        Form Info = new Form();
                        Info.Size        = new Size(Meth._S(350), Meth._S(400));
                        Info.Text        = $"Viewing {backup.Text}";
                        Info.Icon        = new Icon(Settings.IconPath);
                        Info.FormClosed += (s, e) => Info.Dispose();

                        Meth.HandleTheme(Info);

                        Elem.Text Load = new Elem.Text("Loading...");

                        Info.Show();

                        Info.Controls.Add(Load);

                        dynamic BackupInfo = GDTools.Backups.GetBackupInfo(backup.Text);

                        string User = "";

                        Elem.Select Levels = new Elem.Select(false);
                        Levels.DoubleClick += (s, e) => {
                            if (Levels.SelectedItem != null)
                            {
                                Elem.Select.SelectItem lvl = (Elem.Select.SelectItem)Levels.SelectedItem;
                                dynamic LevelInfo          = GDTools.GetLevelInfo(lvl.Text, BackupInfo.Levels);

                                string Info = "";

                                foreach (PropertyInfo i in LevelInfo.GetType().GetProperties())
                                {
                                    if (i.Name != "Name" && i.Name != "Creator" && i.Name != "Description")
                                    {
                                        Info += $"{i.Name.Replace("_", " ")}: {i.GetValue(LevelInfo)}\n";
                                    }
                                }

                                MessageBox.Show(Info, $"Info for {lvl.Text}", MessageBoxButtons.OK, MessageBoxIcon.None);
                            }
                        };

                        foreach (PropertyInfo i in BackupInfo.User.Stats.GetType().GetProperties())
                        {
                            User += $"{i.Name.Replace("_", " ")}: {i.GetValue(BackupInfo.User.Stats)}\r\n";
                        }

                        foreach (dynamic lvl in BackupInfo.Levels)
                        {
                            Levels.AddItem(lvl.Name);
                        }

                        Info.Controls.Remove(Load);

                        FlowLayoutPanel Contain = new FlowLayoutPanel();
                        Contain.Dock     = DockStyle.Fill;
                        Contain.AutoSize = true;

                        Contain.Controls.Add(new Elem.Text(User));
                        Contain.Controls.Add(new Elem.BigNewLine());
                        Contain.Controls.Add(Levels);
                        Contain.Controls.Add(new Elem.Text("Double-click to view level"));

                        Info.Controls.Add(Contain);
                    }
                };

                GDTools.Backups.InitBackups();

                BackupSelect              = new Elem.Select(false);
                BackupSelect.DoubleClick += ViewBackup;

                BackupPath  = new Elem.Text();
                BackupsSize = new Elem.Text();

                RefreshBackupList();

                ContextMenuStrip CM = new ContextMenuStrip();

                CM.Items.Add(new ToolStripMenuItem("View selected backup", null, ViewBackup));
                BackupSelect.ContextMenuStrip = CM;

                this.Controls.Add(BackupSelect);

                this.Controls.Add(BackupsSize);

                this.Controls.Add(new Elem.Div(new Control[] {
                    new Elem.But("View", ViewBackup, "This button shows info about the backup. (You can do the same by double-clicking a backup on the list)"),
                    new Elem.But("Load", (s, e) => {
                        Elem.ChooseForm BackupCurrent = new Elem.ChooseForm(
                            "Backup current progress?",
                            new string[] { "Yes", "No", "Cancel" },
                            "Would you like to backup your current GD progress before loading?"
                            );

                        BackupCurrent.Show();

                        BackupCurrent.Finish += (s) => {
                            if (s == 2)
                            {
                                return;
                            }
                            if (BackupSelect.SelectedItem != null)
                            {
                                if (s == 0)
                                {
                                    GDTools.Backups.CreateNewBackup();
                                }

                                GDTools.Backups.SwitchToBackup(((Elem.Select.SelectItem)BackupSelect.SelectedItem).Text);

                                Program.MainForm.FullReload();
                            }
                        };
                    }, "Switches your current GD progress to that of the backup. Asks you before switching if you'd like to save your current progress."),
                    new Elem.But("Delete", (s, e) => {
                        if (BackupSelect.SelectedItem != null)
                        {
                            Elem.ChooseForm Y = new Elem.ChooseForm("Are you sure?", new string[] { "Yes", "Cancel" }, "Are you sure you want to delete this backup?");

                            Y.Show();

                            Y.Finish += s => {
                                if (s != 0)
                                {
                                    return;
                                }

                                GDTools.Backups.DeleteBackup(((Elem.Select.SelectItem)BackupSelect.SelectedItem).Text);

                                RefreshBackupList();
                            };
                        }
                    }, "Deletes the selected backup permanently.")
                }));

                this.Controls.Add(new Elem.Div(new Control[] {
                    new Elem.But("New", (s, e) => {
                        GDTools.Backups.CreateNewBackup();
                        RefreshBackupList();
                    }, "Creates a new backup of your current GD progress."),
                    new Elem.But("Import Backup", (s, e) => {
                        Elem.ChooseForm FileOrFolder = new Elem.ChooseForm("Select backup type", new string[] { "Folder", $"Compressed file (.zip / .{GDTools.Ext.Backup})" });

                        FileOrFolder.Show();

                        FileOrFolder.Finish += (s) => {
                            if (s == 0)
                            {
                                using (FolderBrowserDialog ofd = new FolderBrowserDialog()) {
                                    ofd.Description = "Select a backup folder";

                                    if (ofd.ShowDialog() == DialogResult.OK)
                                    {
                                        GDTools.Backups.ImportBackup(ofd.SelectedPath);
                                        RefreshBackupList();
                                    }
                                }
                            }
                            else
                            {
                                using (OpenFileDialog ofd = new OpenFileDialog()) {
                                    ofd.InitialDirectory = "c:\\";
                                    ofd.Filter           = GDTools.Ext.BackupFilter;
                                    ofd.FilterIndex      = 1;
                                    ofd.RestoreDirectory = true;
                                    ofd.Multiselect      = true;

                                    if (ofd.ShowDialog() == DialogResult.OK)
                                    {
                                        foreach (string file in ofd.FileNames)
                                        {
                                            ImportBackup(file);
                                        }
                                    }
                                }
                            }
                        };
                    }, "This button lets you import backups you've made before.")
                }));

                this.Controls.Add(new Elem.BigNewLine());
                this.Controls.Add(BackupPath);

                this.Controls.Add(new Elem.Div(new Control[] {
                    new Elem.But("Change Folder", (s, e) => {
                        using (FolderBrowserDialog ofd = new FolderBrowserDialog()) {
                            ofd.Description = "Select backup directory";

                            if (ofd.ShowDialog() == DialogResult.OK)
                            {
                                GDTools.Backups.SetBackupLocation(ofd.SelectedPath);
                                RefreshBackupList();
                            }
                        }
                    }, "Change the folder where backups are saved. All backups are automatically moved to the new location."),
                    new Elem.But("Open Folder", (s, e) => Process.Start("explorer.exe", GDTools._BackupDirectory), "Opens the backup folder in File Explorer."),
                    new Elem.But("Refresh Folder", (s, e) => RefreshBackupList(), "Reloads the backup list.")
                }));
                this.Controls.Add(new Elem.BigNewLine());
                this.Controls.Add(new Elem.But("Help", (s, e) => Pages.SettingPage.ShowHelp("backups")));
                //this.Controls.Add(new Elem.BigNewLine());
                //this.Controls.Add(new Elem.But("Link backups to Google Drive"));
            }
示例#4
0
            public LevelEdit() {
                this.Name = "Level";
                this.Dock = DockStyle.Fill;
                Meth.HandleTheme(this);

                this.SelectPanel = new TableLayoutPanel();
                this.SelectPanel.AutoSize = true;

                this.SelectLevel = new Elem.Select(false);
                this.SelectLevel.DoubleClick += (s, e) => this.SelectLevelToEdit();

                foreach (dynamic lvl in GDTools.GetLevelList(null, null, true))
                    this.SelectLevel.AddItem(lvl.Name);
                
                this.SelectPanel.Controls.Add(SelectLevel);
                this.SelectPanel.Controls.Add(new Elem.But("Select", (s, e) => this.SelectLevelToEdit(), "Select a level to edit"));



                this.EditPanel = new TableLayoutPanel();
                this.EditPanel.Visible = false;
                this.EditPanel.AutoSize = true;

                this.EditPanel.Controls.Add(new Elem.But("⟵", (s, e) => {
                    this.SelectedLevelContent = new {};
                    this.SelectPanel.Visible = true;
                    this.EditPanel.Visible = false;
                }));

                this.EditPanel.Controls.Add(new Elem.NewLine());

                this.LevelName = new Elem.Text();
                this.EditPanel.Controls.Add(LevelName);
                this.EditPanel.Controls.Add(new Elem.BigNewLine());

                CheckBox ExportCompressed = new CheckBox();
                ExportCompressed.Text = "Export compressed (.gmdc)";
                ExportCompressed.AutoSize = true;

                this.EditPanel.Controls.Add(new Elem.But("Create guidelines from BPM", (s, e) => {
                    Form c = new Form();
                    c.Text = "Enter BPM";
                    Meth.HandleTheme(c);
                    
                    TableLayoutPanel con = new TableLayoutPanel();
                    con.AutoSize = true;

                    con.Controls.Add(new Elem.Input("__i_BPM", "INT", "BPM"));
                    con.Controls.Add(new Elem.Input("__i_OFFSET", "INT", "Offset (ms)"));
                    con.Controls.Add(new Elem.Input("__i_TIMESIG", "INT", "Time signature (x/4)"));
                    con.Controls.Add(new Elem.Input("__i_LENGTH", "INT", "Length (s)"));
                    
                    CheckBox KeepOldGuidelines = new CheckBox();
                    KeepOldGuidelines.Text = "Keep old guidelines";
                    KeepOldGuidelines.AutoSize = true;
                    KeepOldGuidelines.Checked = true;

                    con.Controls.Add(KeepOldGuidelines);

                    con.Controls.Add(new Elem.Div(new Control[] {
                        new Elem.But("Create", (s, e) => {
                            string iBPM = con.Controls.Find("__i_BPM", false)[0].Text;
                            string iOFF = con.Controls.Find("__i_OFFSET", false)[0].Text;
                            string iSIG = con.Controls.Find("__i_TIMESIG", false)[0].Text;
                            string iLGT = con.Controls.Find("__i_LENGTH", false)[0].Text;

                            if (iBPM.Length == 0 || iOFF.Length == 0 || iSIG.Length == 0 || iLGT.Length == 0) return;

                            float BPMmultiplier = 60F / Int32.Parse(iBPM);

                            int LineCount = Int32.Parse(iLGT) * Int16.Parse(iSIG);
                            int TimeSignature = Int16.Parse(iSIG);
                            float offset = Int32.Parse(iOFF) / 1000F;
                            string bpmData = "";

                            for (int i = 0; i < LineCount; i++)
                                bpmData += $"{Math.Round((float)i * BPMmultiplier + offset, 2)}~{(i % TimeSignature == 0 ? "1" : "0")}~";

                            string ndat = this.SelectedLevelContent.Data;
                            string dat = this.SelectedLevelContent.k4;

                            if (KeepOldGuidelines.Checked)
                                bpmData += $"{GDTools.GetStartKey(dat, "kA14")}~";

                            ndat = GDTools.SetKey(ndat, "k4", GDTools.SetStartKey(dat, "kA14", bpmData.Substring(0, bpmData.Length - 1)));

                            GDTools.UpdateLevel(ndat);

                            c.Dispose();

                            Program.MainForm.FullReload();
                        }),
                        new Elem.But("Cancel", (s, e) => c.Dispose())
                    }));

                    c.Controls.Add(con);

                    c.Show();
                }, "Used to generate automatic guidelines in the level out of the song's BPM to ease syncing."));

                this.EditPanel.Controls.Add(new Elem.But("Edit level properties", (s, e) => {
                    Elem.BasicForm c = new Elem.BasicForm();
                    c.Text = "Edit level properties";
                    c.Size = new Size(Meth._S(350),Meth._S(350));

                    string newData = this.SelectedLevelContent.Data;
                    
                    TableLayoutPanel con = new TableLayoutPanel();
                    con.AutoSize = true;

                    con.ColumnCount = 3;
                    con.RowCount = 6;

                    con.Controls.Add(new Elem.Text("Name: "), 0, 0);
                    con.Controls.Add(new Elem.Input("__L_NAME", "ANY", "", GDTools.GetKey(newData, "k2"), true), 1, 0);

                    con.Controls.Add(new Elem.Text("Creator: "), 0, 1);
                    con.Controls.Add(new Elem.Input("__L_CREATOR", "ANY", "", GDTools.GetKey(newData, "k5"), true), 1, 1);

                    con.Controls.Add(new Elem.Text("Password: "******"__L_PASSWORD", "INT", "", GDTools.GetKey(newData, "k41"), true), 1, 2);

                    string desc = GDTools.GetKey(newData, "k3");
                    try { desc = Encoding.UTF8.GetString(GDTools.DecryptBase64(desc)); } catch (Exception) {};

                    con.Controls.Add(new Elem.Text("Description: "), 0, 3);
                    con.Controls.Add(new Elem.Input("__L_DESC", "ANY", "", desc, true), 1, 3);

                    con.Controls.Add(new Elem.Text(""), 0, 4);

                    con.Controls.Add(new Elem.But("Apply changes", (s, e) => {
                        newData = GDTools.SetKey(newData, "k2",     con.Controls.Find("__L_NAME", true)[0].Text);
                        newData = GDTools.SetKey(newData, "k5",     con.Controls.Find("__L_CREATOR", true)[0].Text);
                        newData = GDTools.SetKey(newData, "k41",    con.Controls.Find("__L_PASSWORD", true)[0].Text);
                        newData = GDTools.SetKey(newData, "k3",     GDTools.EncryptBase64(Encoding.UTF8.GetBytes(con.Controls.Find("__L_DESC", true)[0].Text)));

                        GDTools.UpdateLevel(newData.Replace(System.Environment.NewLine, ""));

                        c.Dispose();

                        Program.MainForm.FullReload();
                    }), 0, 5);

                    c.Controls.Add(con);

                    c.Show();
                }, "Edit level properties such as name, description, etc. (Hint: You can add newlines to descriptions!)"));

                this.EditPanel.Controls.Add(new Elem.But("View level info", (s, e) => {
                    dynamic LevelInfo = GDTools.GetLevelInfo(this.SelectedLevel);
                        
                    string Info = "";

                    foreach (PropertyInfo i in LevelInfo.GetType().GetProperties()) 
                        Info += $"{i.Name.Replace("_", " ")}: {i.GetValue(LevelInfo)}\n";

                    MessageBox.Show(Info, $"Info for {this.SelectedLevel}", MessageBoxButtons.OK, MessageBoxIcon.None);
                }, "View info about the selected level."));

                this.EditPanel.Controls.Add(new Elem.But("Generate T4 glow", (s, e) => {
                    Elem.BasicForm c = new Elem.BasicForm();
                    c.Text = "Generate T4 glow";
                    c.Size = new Size(Meth._S(350),Meth._S(350));

                    string newData = this.SelectedLevelContent.Data;
                    
                    TableLayoutPanel con = new TableLayoutPanel();
                    con.AutoSize = true;

                    con.ColumnCount = 3;
                    con.RowCount = 7;

                    con.Controls.Add(new Elem.Text("X position: "), 0, 0);
                    con.Controls.Add(new Elem.Input("__L_X", "INT", "", "0"), 1, 0);

                    con.Controls.Add(new Elem.Text("Y position: "), 0, 1);
                    con.Controls.Add(new Elem.Input("__L_Y", "INT", "", "0"), 1, 1);

                    con.Controls.Add(new Elem.Text("Scale: "), 0, 2);
                    con.Controls.Add(new Elem.Input("__L_S", "FLT", "", "1"), 1, 2);

                    con.Controls.Add(new Elem.Text(""), 0, 4);

                    con.Controls.Add(new Elem.But("Generate", (s, e) => {
                        string obj = GDTools.DecodeLevelData(GDTools.GetKey(newData, "k4"));

                        obj += $"1,1888,2,{con.Controls.Find("__L_X", true)[0].Text},3,{con.Controls.Find("__L_Y", true)[0].Text},24,10,32,{con.Controls.Find("__L_S", true)[0].Text};";

                        newData = GDTools.SetKey(newData, "k4", GDTools.EncodeLevelData(obj));

                        GDTools.UpdateLevel(newData);

                        c.Dispose();

                        Program.MainForm.FullReload();
                    }), 0, 5);

                    con.Controls.Add(new Elem.Text("T4 glow is Blending glow that can be put above T3 solid objects.\r\n\r\nYou have to give the glow a color that has Blending enabled.", new Size(150, 0)), 0, 6);

                    c.Controls.Add(con);

                    c.Show();
                }, "Generates a piece of T4 glow at the start of the level."));

                this.EditPanel.Controls.Add(new Elem.But("Edit level data", (s, e) => {
                    Elem.BasicForm DataEditor = new Elem.BasicForm();
                    DataEditor.Size = new Size(800, 600);

                    int ControlsHeight = 50;

                    TableLayoutPanel DataEditorMain = new TableLayoutPanel();
                    DataEditorMain.AutoSize = true;
                    DataEditorMain.Dock = DockStyle.Fill;

                    TableLayoutPanel DataEditorEditor = new TableLayoutPanel();
                    DataEditorEditor.ColumnCount = 2;
                    DataEditorEditor.Dock = DockStyle.Fill;
                    DataEditorEditor.AutoScroll = true;
                    DataEditorEditor.Size = new Size(DataEditor.Size.Width - 30, DataEditor.Size.Height - ControlsHeight - 100);

                    FlowLayoutPanel DataEditorControls = new FlowLayoutPanel();
                    DataEditorControls.AutoSize = true;
                    DataEditorControls.Dock = DockStyle.Bottom;
                    DataEditorControls.Height = ControlsHeight;

                    string[] objs = this.SelectedLevelContent.k4.Split(";");
                    int page = 0;
                    int show = 20;

                    Elem.Text PageNum = new Elem.Text();
                    Elem.Text PageAmt = new Elem.Text();

                    void PageUpdate() {
                        DataEditorEditor.Controls.Clear(true);

                        PageNum.Text = $"Page: {page / show + 1} / {objs.Length / show + 1}";
                        PageAmt.Text = $"Amount of object(s) shown on page: {show}";
                        
                        int i = 0;
                        foreach (string obj in objs.Red(page, show)) {
                            if (obj == null) continue;
                            DataEditorEditor.Controls.Add(new Elem.Text($"{page + i}:"), 0, i);
                            DataEditorEditor.Controls.Add(new Elem.Text($"{obj}"), 1, i);

                            i++;
                        }
                    };

                    PageUpdate();

                    DataEditorControls.Controls.Add(PageNum);
                    DataEditorControls.Controls.Add(PageAmt);
                    DataEditorControls.Controls.Add(new Elem.But("Next", (s, e) => {
                        if (page < objs.Length) { page += show; PageUpdate(); };
                    }));
                    DataEditorControls.Controls.Add(new Elem.But("Previous", (s, e) => {
                        if (page > 0) { page -= show; PageUpdate(); };
                    }));
                    DataEditorControls.Controls.Add(new Elem.But("Go to page", (s, e) => {
                        Elem.ChooseForm c = new Elem.ChooseForm( "Go to page", 
                            new string[] { "IS-INPUT::INT", "::Go", "Cancel" }
                        );

                        c.Show();

                        c.FinishStr += resc => {
                            if (resc != "") {
                                int np = Int32.Parse(resc) - 1;
                                if (np >= 0 && np <= objs.Length / show)
                                    page = np * show;

                                PageUpdate();
                                c.Dispose();
                            }
                        };
                    }));

                    DataEditorMain.Controls.Add(DataEditorEditor);
                    DataEditorMain.Controls.Add(DataEditorControls);
                    DataEditor.Controls.Add(DataEditorMain);

                    DataEditor.Show();
                }));

                this.EditPanel.Controls.Add(new Elem.But("Rearrange Groups And Colours", (s, e) => {
                    Elem.BasicForm c = new Elem.BasicForm();
                    c.Text = "Rearrange Groups And Colours";
                    c.Size = new Size(Meth._S(350),Meth._S(250));

                    string newData = this.SelectedLevelContent.k4;
                    
                    TableLayoutPanel con = new TableLayoutPanel();
                    con.AutoSize = true;

                    con.ColumnCount = 3;
                    con.RowCount = 7;

                    con.Controls.Add(new Elem.Text("Group Range"), 0, 0);
                    con.Controls.Add(new Elem.Input("__G_RANGE", "ANY", "", "x - y", false, false), 0, 1);

                    con.Controls.Add(new Elem.Text("Offset"), 1, 0);
                    con.Controls.Add(new Elem.Input("__G_OFF", "INN", "", "+0", false, false), 1, 1);

                    con.Controls.Add(new Elem.Text(""), 0, 2);

                    con.Controls.Add(new Elem.Text("Color Range"), 0, 3);
                    con.Controls.Add(new Elem.Input("__C_RANGE", "ANY", "", "x - y", false, false), 0, 4);

                    con.Controls.Add(new Elem.Text("Offset"), 1, 3);
                    con.Controls.Add(new Elem.Input("__C_OFF", "INN", "", "+0", false, false), 1, 4);

                    con.Controls.Add(new Elem.Text(""), 0, 5);

                    con.Controls.Add(new Elem.But("Apply changes", (s, e) => {
                        try {
                            string grang = con.Controls.Find("__G_RANGE", true)[0].Text.Trim();
                            if (!Regex.IsMatch(grang, @"\d+\s*\-\s*\d+")) throw new Exception("Invalid input in group range!");

                            string goff = con.Controls.Find("__G_OFF", true)[0].Text.Trim();
                            if (!Regex.IsMatch(goff, @"[+|-]?\s*\d+")) throw new Exception("Invalid input in group offset!");

                            string crang = con.Controls.Find("__C_RANGE", true)[0].Text.Trim();
                            if (!Regex.IsMatch(crang, @"\d+\s*\-\s*\d+")) throw new Exception("Invalid input in color range!");

                            string coff = con.Controls.Find("__C_OFF", true)[0].Text.Trim();
                            if (!Regex.IsMatch(coff, @"[+|-]?\s*\d+")) throw new Exception("Invalid input in color offset!");

                            // groups are separated like a.b.c.d.e
                            // colors are just the color id

                            // things you need to affect: color triggers, pulse triggers, literally every trigger that takes groups

                            string new_data = "";
                            foreach (dynamic obj in GDTools.GetObjectsByKey(newData))
                                if (GDTools.GetObjectKey(obj.Data, "57") != null) {
                                    int o = Int32.Parse(GDTools.GetObjectKey(obj.Data, "57"));
                                    string n = obj.Data;
                                    if (Int32.Parse(grang.Split("-")[0] < o && o < Int32.Parse(grang.Split("-")[1]))
                                        n = GDTools.SetObjectKey(obj.Data, "57", (o + Int32.Parse(goff)).ToString());
                                    new_data += n + ";";
                                } else new_data += obj.Data + ";";
                        } catch (Exception err) {
                            MessageBox.Show($"Error: {err}", "Error");
                        }
                    }), 0, 6);

                    con.Controls.Add(new Elem.But("Cancel", (s, e) => c.Dispose()), 1, 6);

                    c.Controls.Add(con);

                    c.Show();
                }));