using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Windows.Forms; using BizHawk.Client.Common; using BizHawk.Client.Common.MovieConversionExtensions; using BizHawk.Client.EmuHawk.ToolExtensions; using BizHawk.Client.EmuHawk.WinFormExtensions; namespace BizHawk.Client.EmuHawk { public partial class TAStudio { #region File Menu private void FileSubMenu_DropDownOpened(object sender, EventArgs e) { ToBk2MenuItem.Enabled = !string.IsNullOrWhiteSpace(CurrentTasMovie.Filename) && (CurrentTasMovie.Filename != DefaultTasProjName()); SaveTASMenuItem.Enabled = !string.IsNullOrWhiteSpace(CurrentTasMovie.Filename) && (CurrentTasMovie.Filename != DefaultTasProjName()); SaveTASMenuItem.Enabled = SaveAsTASMenuItem.Enabled = !_saveBackgroundWorker.IsBusy; } private void RecentSubMenu_DropDownOpened(object sender, EventArgs e) { RecentSubMenu.DropDownItems.Clear(); RecentSubMenu.DropDownItems.AddRange( Settings.RecentTas.RecentMenu(DummyLoadProject, true)); } private void NewTasMenuItem_Click(object sender, EventArgs e) { if (GlobalWin.MainForm.GameIsClosing) { Close(); } else { StartNewTasMovie(); } } private void OpenTasMenuItem_Click(object sender, EventArgs e) { if (AskSaveChanges()) { var filename = CurrentTasMovie.Filename; if (string.IsNullOrWhiteSpace(filename) || filename == DefaultTasProjName()) { filename = string.Empty; } var file = OpenFileDialog( filename, PathManager.MakeAbsolutePath(Global.Config.PathEntries.MoviesPathFragment, null), "Tas Project Files", "tasproj"); if (file != null) { LoadFile(file); } } } private bool _exiting = false; private void SaveTasMenuItem_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(CurrentTasMovie.Filename) || CurrentTasMovie.Filename == DefaultTasProjName()) { SaveAsTasMenuItem_Click(sender, e); } else { if (_exiting) { CurrentTasMovie.Save(); } else { _saveBackgroundWorker.RunWorkerAsync(); } Settings.RecentTas.Add(CurrentTasMovie.Filename); } } private void SaveAsTasMenuItem_Click(object sender, EventArgs e) { var filename = CurrentTasMovie.Filename; if (string.IsNullOrWhiteSpace(filename) || filename == DefaultTasProjName()) { filename = SuggestedTasProjName(); } var file = SaveFileDialog( filename, PathManager.MakeAbsolutePath(Global.Config.PathEntries.MoviesPathFragment, null), "Tas Project Files", "tasproj"); if (file != null) { CurrentTasMovie.Filename = file.FullName; if (_exiting) { CurrentTasMovie.Save(); } else { _saveBackgroundWorker.RunWorkerAsync(); } Settings.RecentTas.Add(CurrentTasMovie.Filename); SetTextProperty(); } } private void saveSelectionToMacroToolStripMenuItem_Click(object sender, EventArgs e) { if (TasView.LastSelectedIndex == CurrentTasMovie.InputLogLength) TasView.SelectRow(CurrentTasMovie.InputLogLength, false); if (!TasView.AnyRowsSelected) return; MovieZone macro = new MovieZone(CurrentTasMovie, TasView.FirstSelectedIndex.Value, TasView.LastSelectedIndex.Value - TasView.FirstSelectedIndex.Value + 1); MacroInputTool.SaveMacroAs(macro); } private void placeMacroAtSelectionToolStripMenuItem_Click(object sender, EventArgs e) { if (!TasView.AnyRowsSelected) return; MovieZone macro = MacroInputTool.LoadMacro(); if (macro != null) { macro.Start = TasView.FirstSelectedIndex.Value; macro.PlaceZone(CurrentTasMovie); } } private void recentMacrosToolStripMenuItem_DropDownOpened(object sender, EventArgs e) { recentMacrosToolStripMenuItem.DropDownItems.Clear(); recentMacrosToolStripMenuItem.DropDownItems.AddRange(Global.Config.RecentMacros.RecentMenu(DummyLoadMacro)); } private void ToBk2MenuItem_Click(object sender, EventArgs e) { var bk2 = CurrentTasMovie.ToBk2(true); bk2.Save(); MessageStatusLabel.Text = Path.GetFileName(bk2.Filename) + " created."; } private void ExitMenuItem_Click(object sender, EventArgs e) { Close(); } #endregion #region Edit private void UndoMenuItem_Click(object sender, EventArgs e) { if (CurrentTasMovie.ChangeLog.Undo() < Emulator.Frame) GoToFrame(CurrentTasMovie.ChangeLog.PreviousUndoFrame); else RefreshDialog(); // Currently I don't have a way to easily detect when CanUndo changes, so this button should be enabled always. //UndoMenuItem.Enabled = CurrentTasMovie.ChangeLog.CanUndo; RedoMenuItem.Enabled = CurrentTasMovie.ChangeLog.CanRedo; } private void RedoMenuItem_Click(object sender, EventArgs e) { if (CurrentTasMovie.ChangeLog.Redo() < Emulator.Frame) GoToFrame(CurrentTasMovie.ChangeLog.PreviousRedoFrame); else RefreshDialog(); //UndoMenuItem.Enabled = CurrentTasMovie.ChangeLog.CanUndo; RedoMenuItem.Enabled = CurrentTasMovie.ChangeLog.CanRedo; } private void showUndoHistoryToolStripMenuItem_Click(object sender, EventArgs e) { undoForm = new UndoHistoryForm(this); undoForm.Owner = this; undoForm.Show(); undoForm.UpdateValues(); } private void EditSubMenu_DropDownOpened(object sender, EventArgs e) { DeselectMenuItem.Enabled = SelectBetweenMarkersMenuItem.Enabled = CopyMenuItem.Enabled = CutMenuItem.Enabled = ClearMenuItem.Enabled = DeleteFramesMenuItem.Enabled = CloneMenuItem.Enabled = TruncateMenuItem.Enabled = TasView.AnyRowsSelected; ReselectClipboardMenuItem.Enabled = PasteMenuItem.Enabled = PasteInsertMenuItem.Enabled = _tasClipboard.Any(); ClearGreenzoneMenuItem.Enabled = CurrentTasMovie != null && CurrentTasMovie.TasStateManager.Any(); GreenzoneICheckSeparator.Visible = StateHistoryIntegrityCheckMenuItem.Visible = VersionInfo.DeveloperBuild; } private void DeselectMenuItem_Click(object sender, EventArgs e) { TasView.DeselectAll(); RefreshTasView(); } private void SelectAllMenuItem_Click(object sender, EventArgs e) { TasView.SelectAll(); RefreshTasView(); } private void SelectBetweenMarkersMenuItem_Click(object sender, EventArgs e) { if (TasView.AnyRowsSelected) { var prevMarker = CurrentTasMovie.Markers.PreviousOrCurrent(TasView.LastSelectedIndex.Value); var nextMarker = CurrentTasMovie.Markers.Next(TasView.LastSelectedIndex.Value); int prev = prevMarker != null ? prevMarker.Frame : 0; int next = nextMarker != null ? nextMarker.Frame : CurrentTasMovie.InputLogLength; for (int i = prev; i < next; i++) { TasView.SelectRow(i, true); } RefreshTasView(); } } private void ReselectClipboardMenuItem_Click(object sender, EventArgs e) { TasView.DeselectAll(); foreach (var item in _tasClipboard) { TasView.SelectRow(item.Frame, true); } RefreshTasView(); } private void CopyMenuItem_Click(object sender, EventArgs e) { if (TasView.AnyRowsSelected) { _tasClipboard.Clear(); var list = TasView.SelectedRows.ToList(); var sb = new StringBuilder(); foreach (var index in list) { var input = CurrentTasMovie.GetInputState(index); _tasClipboard.Add(new TasClipboardEntry(index, input)); var lg = CurrentTasMovie.LogGeneratorInstance(); lg.SetSource(input); sb.AppendLine(lg.GenerateLogEntry()); } Clipboard.SetDataObject(sb.ToString()); SetSplicer(); } } private void PasteMenuItem_Click(object sender, EventArgs e) { // TODO: if highlighting 2 rows and pasting 3, only paste 2 of them // FCEUX Taseditor does't do this, but I think it is the expected behavior in editor programs var wasPaused = GlobalWin.MainForm.EmulatorPaused; if (_tasClipboard.Any()) { var needsToRollback = TasView.FirstSelectedIndex < Emulator.Frame; CurrentTasMovie.CopyOverInput(TasView.FirstSelectedIndex.Value, _tasClipboard.Select(x => x.ControllerState)); if (needsToRollback) { GoToLastEmulatedFrameIfNecessary(TasView.FirstSelectedIndex.Value); if (wasPaused) { DoAutoRestore(); } else { GlobalWin.MainForm.UnpauseEmulator(); } } else { RefreshDialog(); } } } private void PasteInsertMenuItem_Click(object sender, EventArgs e) { var wasPaused = GlobalWin.MainForm.EmulatorPaused; if (_tasClipboard.Any()) { var needsToRollback = TasView.FirstSelectedIndex < Emulator.Frame; CurrentTasMovie.InsertInput(TasView.FirstSelectedIndex.Value, _tasClipboard.Select(x => x.ControllerState)); if (needsToRollback) { GoToLastEmulatedFrameIfNecessary(TasView.FirstSelectedIndex.Value); if (wasPaused) { DoAutoRestore(); } else { GlobalWin.MainForm.UnpauseEmulator(); } } else { RefreshDialog(); } } } private void CutMenuItem_Click(object sender, EventArgs e) { if (TasView.AnyRowsSelected) { var wasPaused = GlobalWin.MainForm.EmulatorPaused; var needsToRollback = TasView.FirstSelectedIndex < Emulator.Frame; var rollBackFrame = TasView.FirstSelectedIndex.Value; _tasClipboard.Clear(); var list = TasView.SelectedRows.ToArray(); var sb = new StringBuilder(); for (var i = 0; i < list.Length; i++) { var input = CurrentTasMovie.GetInputState(i); _tasClipboard.Add(new TasClipboardEntry(list[i], input)); var lg = CurrentTasMovie.LogGeneratorInstance(); lg.SetSource(input); sb.AppendLine(lg.GenerateLogEntry()); } Clipboard.SetDataObject(sb.ToString()); CurrentTasMovie.RemoveFrames(list); SetSplicer(); //TasView.DeselectAll(); feos: what if I want to continuously cut? if (needsToRollback) { GoToLastEmulatedFrameIfNecessary(rollBackFrame); if (wasPaused) { DoAutoRestore(); } else { GlobalWin.MainForm.UnpauseEmulator(); } } else { RefreshDialog(); } } } private void ClearMenuItem_Click(object sender, EventArgs e) { if (TasView.AnyRowsSelected) { bool wasPaused = GlobalWin.MainForm.EmulatorPaused; bool needsToRollback = !(TasView.FirstSelectedIndex > Emulator.Frame); int rollBackFrame = TasView.FirstSelectedIndex.Value; CurrentTasMovie.ChangeLog.BeginNewBatch("Clear frames " + TasView.SelectedRows.Min() + "-" + TasView.SelectedRows.Max()); foreach (int frame in TasView.SelectedRows) { CurrentTasMovie.ClearFrame(frame); } CurrentTasMovie.ChangeLog.EndBatch(); if (needsToRollback) { GoToLastEmulatedFrameIfNecessary(rollBackFrame); if (wasPaused) { DoAutoRestore(); } else { GlobalWin.MainForm.UnpauseEmulator(); } } else { RefreshDialog(); } } } private void DeleteFramesMenuItem_Click(object sender, EventArgs e) { if (TasView.AnyRowsSelected) { var wasPaused = GlobalWin.MainForm.EmulatorPaused; var needsToRollback = TasView.FirstSelectedIndex < Emulator.Frame; var rollBackFrame = TasView.FirstSelectedIndex.Value; if (rollBackFrame >= CurrentTasMovie.InputLogLength) { // Cannot delete non-existant frames RefreshDialog(); return; } CurrentTasMovie.RemoveFrames(TasView.SelectedRows.ToArray()); SetSplicer(); if (needsToRollback) { GoToLastEmulatedFrameIfNecessary(rollBackFrame); if (wasPaused) { DoAutoRestore(); } else { GlobalWin.MainForm.UnpauseEmulator(); } } else { RefreshDialog(); } } } private void CloneMenuItem_Click(object sender, EventArgs e) { if (TasView.AnyRowsSelected) { var wasPaused = GlobalWin.MainForm.EmulatorPaused; var framesToInsert = TasView.SelectedRows.ToList(); var insertionFrame = Math.Min(TasView.LastSelectedIndex.Value + 1, CurrentTasMovie.InputLogLength); var needsToRollback = TasView.FirstSelectedIndex < Emulator.Frame; var inputLog = framesToInsert .Select(frame => CurrentTasMovie.GetInputLogEntry(frame)) .ToList(); CurrentTasMovie.InsertInput(insertionFrame, inputLog); if (needsToRollback) { GoToLastEmulatedFrameIfNecessary(insertionFrame); if (wasPaused) { DoAutoRestore(); } else { GlobalWin.MainForm.UnpauseEmulator(); } } else { RefreshDialog(); } } } private void InsertFrameMenuItem_Click(object sender, EventArgs e) { var wasPaused = GlobalWin.MainForm.EmulatorPaused; var insertionFrame = TasView.AnyRowsSelected ? TasView.FirstSelectedIndex.Value : 0; var needsToRollback = TasView.FirstSelectedIndex < Emulator.Frame; CurrentTasMovie.InsertEmptyFrame(insertionFrame); if (needsToRollback) { GoToLastEmulatedFrameIfNecessary(insertionFrame); if (wasPaused) { DoAutoRestore(); } else { GlobalWin.MainForm.UnpauseEmulator(); } } else { RefreshDialog(); } } private void InsertNumFramesMenuItem_Click(object sender, EventArgs e) { bool wasPaused = GlobalWin.MainForm.EmulatorPaused; int insertionFrame = TasView.AnyRowsSelected ? TasView.FirstSelectedIndex.Value : 0; bool needsToRollback = TasView.FirstSelectedIndex < Emulator.Frame; FramesPrompt framesPrompt = new FramesPrompt(); DialogResult result = framesPrompt.ShowDialog(); if (result == DialogResult.OK) { CurrentTasMovie.InsertEmptyFrame(insertionFrame, framesPrompt.Frames); } if (needsToRollback) { GoToLastEmulatedFrameIfNecessary(insertionFrame); if (wasPaused) { DoAutoRestore(); } else { GlobalWin.MainForm.UnpauseEmulator(); } } else { RefreshDialog(); } } private void TruncateMenuItem_Click(object sender, EventArgs e) { if (TasView.AnyRowsSelected) { var rollbackFrame = TasView.LastSelectedIndex.Value; var needsToRollback = TasView.FirstSelectedIndex < Emulator.Frame; CurrentTasMovie.Truncate(rollbackFrame); MarkerControl.MarkerInputRoll.TruncateSelection(CurrentTasMovie.Markers.Count - 1); if (needsToRollback) { GoToFrame(rollbackFrame); } else { RefreshDialog(); } } } private void SetMarkersMenuItem_Click(object sender, EventArgs e) { if (TasView.SelectedRows.Count() > 50) { var result = MessageBox.Show("Are you sure you want to add more than 50 markers?", "Add markers", MessageBoxButtons.OKCancel, MessageBoxIcon.Question); if (result != DialogResult.OK) return; } foreach (var index in TasView.SelectedRows) { MarkerControl.AddMarker(false, index); } } private void SetMarkerWithTextMenuItem_Click(object sender, EventArgs e) { MarkerControl.AddMarker(true, TasView.SelectedRows.FirstOrDefault()); } private void RemoveMarkersMenuItem_Click(object sender, EventArgs e) { IEnumerable markers = CurrentTasMovie.Markers.Where(m => TasView.SelectedRows.Contains(m.Frame)); foreach (TasMovieMarker m in markers.ToList()) { CurrentTasMovie.Markers.Remove(m); } RefreshDialog(); } private void ClearGreenzoneMenuItem_Click(object sender, EventArgs e) { CurrentTasMovie.ClearGreenzone(); RefreshDialog(); } private void StateHistoryIntegrityCheckMenuItem_Click(object sender, EventArgs e) { if (!Emulator.DeterministicEmulation) { if (MessageBox.Show("The emulator is not deterministic. It might fail even if the difference isn't enough to cause a desync.\nContinue with check?", "Not Deterministic", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.No) return; } GoToFrame(0); int lastState = 0; int goToFrame = CurrentTasMovie.TasStateManager.LastEmulatedFrame; do { GlobalWin.MainForm.FrameAdvance(); if (CurrentTasMovie.TasStateManager.HasState(Emulator.Frame)) { byte[] state = (byte[])StatableEmulator.SaveStateBinary().Clone(); // Why is this cloning it? byte[] greenzone = CurrentTasMovie.TasStateManager[Emulator.Frame].Value; if (!state.SequenceEqual(greenzone)) { MessageBox.Show("Bad data between frames " + lastState + " and " + Emulator.Frame); return; } lastState = Emulator.Frame; } } while (Global.Emulator.Frame < goToFrame); MessageBox.Show("Integrity Check passed"); } #endregion #region Config private void SetMaxUndoLevelsMenuItem_Click(object sender, EventArgs e) { using (var prompt = new InputPrompt { TextInputType = InputPrompt.InputType.Unsigned, Message = "Number of Undo Levels to keep", InitialValue = CurrentTasMovie.ChangeLog.MaxSteps.ToString() }) { DialogResult result = prompt.ShowDialog(); if (result == DialogResult.OK) { int val = int.Parse(prompt.PromptText); if (val > 0) CurrentTasMovie.ChangeLog.MaxSteps = val; } } } private void SetBranchCellHoverIntervalMenuItem_Click(object sender, EventArgs e) { using (var prompt = new InputPrompt { TextInputType = InputPrompt.InputType.Unsigned, Message = "ScreenshotPopUp Delay", InitialValue = Settings.BranchCellHoverInterval.ToString() }) { DialogResult result = prompt.ShowDialog(); if (result == DialogResult.OK) { int val = int.Parse(prompt.PromptText); if (val > 0) { Settings.BranchCellHoverInterval = val; BookMarkControl.HoverInterval = val; } } } } private void SetSeekingCutoffIntervalMenuItem_Click(object sender, EventArgs e) { using (var prompt = new InputPrompt { TextInputType = InputPrompt.InputType.Unsigned, Message = "Seeking Cutoff Interval", InitialValue = Settings.SeekingCutoffInterval.ToString() }) { DialogResult result = prompt.ShowDialog(); if (result == DialogResult.OK) { int val = int.Parse(prompt.PromptText); if (val > 0) { Settings.SeekingCutoffInterval = val; TasView.SeekingCutoffInterval = val; } } } } private void ConfigSubMenu_DropDownOpened(object sender, EventArgs e) { DrawInputByDraggingMenuItem.Checked = Settings.DrawInput; AutopauseAtEndOfMovieMenuItem.Checked = Settings.AutoPause; EmptyNewMarkerNotesMenuItem.Checked = Settings.EmptyMarkers; } private void DrawInputByDraggingMenuItem_Click(object sender, EventArgs e) { TasView.InputPaintingMode = Settings.DrawInput ^= true; } private void applyPatternToPaintedInputToolStripMenuItem_CheckedChanged(object sender, EventArgs e) { onlyOnAutoFireColumnsToolStripMenuItem.Enabled = applyPatternToPaintedInputToolStripMenuItem.Checked; } private void BindMarkersToInputMenuItem_Click(object sender, EventArgs e) { CurrentTasMovie.BindMarkersToInput = BindMarkersToInputMenuItem.Checked; } private void EmptyNewMarkerNotesMenuItem_Click(object sender, EventArgs e) { Settings.EmptyMarkers ^= true; } private void AutopauseAtEndMenuItem_Click(object sender, EventArgs e) { Settings.AutoPause ^= true; } private void autoHoldToolStripMenuItem_CheckedChanged(object sender, EventArgs e) { if (autoHoldToolStripMenuItem.Checked) { autoFireToolStripMenuItem.Checked = false; customPatternToolStripMenuItem.Checked = false; if (!keepSetPatternsToolStripMenuItem.Checked) UpdateAutoFire(); } } private void autoFireToolStripMenuItem_CheckedChanged(object sender, EventArgs e) { if (autoFireToolStripMenuItem.Checked) { autoHoldToolStripMenuItem.Checked = false; customPatternToolStripMenuItem.Checked = false; if (!keepSetPatternsToolStripMenuItem.Checked) UpdateAutoFire(); } } private void customPatternToolStripMenuItem_CheckedChanged(object sender, EventArgs e) { if (customPatternToolStripMenuItem.Checked) { autoHoldToolStripMenuItem.Checked = false; autoFireToolStripMenuItem.Checked = false; if (!keepSetPatternsToolStripMenuItem.Checked) UpdateAutoFire(); } } private void setCustomsToolStripMenuItem_Click(object sender, EventArgs e) { // Exceptions in PatternsForm are not caught by the debugger, I have no idea why. // Exceptions in UndoForm are caught, which makes it weirder. PatternsForm pForm = new PatternsForm(this); pForm.Owner = this; pForm.Show(); } #endregion #region Metadata private void HeaderMenuItem_Click(object sender, EventArgs e) { new MovieHeaderEditor(CurrentTasMovie) { Owner = GlobalWin.MainForm, Location = this.ChildPointToScreen(TasView) }.Show(); UpdateChangesIndicator(); } private void StateHistorySettingsMenuItem_Click(object sender, EventArgs e) { new StateHistorySettingsForm(CurrentTasMovie.TasStateManager.Settings) { Owner = GlobalWin.MainForm, Location = this.ChildPointToScreen(TasView), Statable = this.StatableEmulator }.ShowDialog(); CurrentTasMovie.TasStateManager.LimitStateCount(); UpdateChangesIndicator(); } private void CommentsMenuItem_Click(object sender, EventArgs e) { var form = new EditCommentsForm(); form.GetMovie(CurrentTasMovie); form.ForceReadWrite = true; form.Show(); } private void SubtitlesMenuItem_Click(object sender, EventArgs e) { var form = new EditSubtitlesForm { ReadOnly = false }; form.GetMovie(Global.MovieSession.Movie); form.ShowDialog(); } private void DefaultStateSettingsMenuItem_Click(object sender, EventArgs e) { new DefaultGreenzoneSettings { Location = this.ChildPointToScreen(TasView) }.ShowDialog(); } #endregion #region Settings Menu private void SettingsSubMenu_DropDownOpened(object sender, EventArgs e) { RotateMenuItem.ShortcutKeyDisplayString = TasView.RotateHotkeyStr; } private void HideLagFramesSubMenu_DropDownOpened(object sender, EventArgs e) { HideLagFrames0.Checked = TasView.LagFramesToHide == 0; HideLagFrames1.Checked = TasView.LagFramesToHide == 1; HideLagFrames2.Checked = TasView.LagFramesToHide == 2; HideLagFrames3.Checked = TasView.LagFramesToHide == 3; hideWasLagFramesToolStripMenuItem.Checked = TasView.HideWasLagFrames; } private void RotateMenuItem_Click(object sender, EventArgs e) { TasView.HorizontalOrientation ^= true; CurrentTasMovie.FlagChanges(); } private void HideLagFramesX_Click(object sender, EventArgs e) { TasView.LagFramesToHide = (int)(sender as ToolStripMenuItem).Tag; MaybeFollowCursor(); RefreshDialog(); } private void hideWasLagFramesToolStripMenuItem_Click(object sender, EventArgs e) { TasView.HideWasLagFrames ^= true; } private void alwaysScrollToolStripMenuItem_Click(object sender, EventArgs e) { TasView.AlwaysScroll = Settings.FollowCursorAlwaysScroll = alwaysScrollToolStripMenuItem.Checked; } private void scrollToViewToolStripMenuItem_Click(object sender, EventArgs e) { TasView.ScrollMethod = Settings.FollowCursorScrollMethod = "near"; } private void scrollToTopToolStripMenuItem_Click(object sender, EventArgs e) { TasView.ScrollMethod = Settings.FollowCursorScrollMethod = "top"; } private void scrollToBottomToolStripMenuItem_Click(object sender, EventArgs e) { TasView.ScrollMethod = Settings.FollowCursorScrollMethod = "bottom"; } private void scrollToCenterToolStripMenuItem_Click(object sender, EventArgs e) { TasView.ScrollMethod = Settings.FollowCursorScrollMethod = "center"; } private void iconsToolStripMenuItem_DropDownOpened(object sender, EventArgs e) { denoteStatesWithIconsToolStripMenuItem.Checked = Settings.denoteStatesWithIcons; denoteStatesWithBGColorToolStripMenuItem.Checked = Settings.denoteStatesWithBGColor; denoteMarkersWithIconsToolStripMenuItem.Checked = Settings.denoteMarkersWithIcons; denoteMarkersWithBGColorToolStripMenuItem.Checked = Settings.denoteMarkersWithBGColor; } private void denoteStatesWithIconsToolStripMenuItem_Click(object sender, EventArgs e) { TasView.denoteStatesWithIcons = Settings.denoteStatesWithIcons = denoteStatesWithIconsToolStripMenuItem.Checked; RefreshDialog(); } private void denoteStatesWithBGColorToolStripMenuItem_Click(object sender, EventArgs e) { TasView.denoteStatesWithBGColor = Settings.denoteStatesWithBGColor = denoteStatesWithBGColorToolStripMenuItem.Checked; RefreshDialog(); } private void denoteMarkersWithIconsToolStripMenuItem_Click(object sender, EventArgs e) { TasView.denoteMarkersWithIcons = Settings.denoteMarkersWithIcons = denoteMarkersWithIconsToolStripMenuItem.Checked; RefreshDialog(); } private void denoteMarkersWithBGColorToolStripMenuItem_Click(object sender, EventArgs e) { TasView.denoteMarkersWithBGColor = Settings.denoteMarkersWithBGColor = denoteMarkersWithBGColorToolStripMenuItem.Checked; RefreshDialog(); } private void followCursorToolStripMenuItem_DropDownOpened(object sender, EventArgs e) { alwaysScrollToolStripMenuItem.Checked = Settings.FollowCursorAlwaysScroll; scrollToViewToolStripMenuItem.Checked = false; scrollToTopToolStripMenuItem.Checked = false; scrollToBottomToolStripMenuItem.Checked = false; scrollToCenterToolStripMenuItem.Checked = false; if (TasView.ScrollMethod == "near") scrollToViewToolStripMenuItem.Checked = true; else if (TasView.ScrollMethod == "top") scrollToTopToolStripMenuItem.Checked = true; else if (TasView.ScrollMethod == "bottom") scrollToBottomToolStripMenuItem.Checked = true; else scrollToCenterToolStripMenuItem.Checked = true; } private void wheelScrollSpeedToolStripMenuItem_Click(object sender, EventArgs e) { InputPrompt inputpromt = new InputPrompt(); inputpromt.TextInputType = InputPrompt.InputType.Unsigned; inputpromt.Message = "Frames per tick:"; inputpromt.InitialValue = TasView.ScrollSpeed.ToString(); if (inputpromt.ShowDialog() == System.Windows.Forms.DialogResult.OK) { TasView.ScrollSpeed = int.Parse(inputpromt.PromptText); Settings.ScrollSpeed = TasView.ScrollSpeed; } } #endregion #region Columns private void SetUpToolStripColumns() { ColumnsSubMenu.DropDownItems.Clear(); var columns = TasView.AllColumns .Where(x => !string.IsNullOrWhiteSpace(x.Text)) .Where(x => x.Name != "FrameColumn"); ToolStripMenuItem[] playerMenus = new ToolStripMenuItem[Global.Emulator.ControllerDefinition.PlayerCount + 1]; playerMenus[0] = ColumnsSubMenu; for (int i = 1; i < playerMenus.Length; i++) { playerMenus[i] = new ToolStripMenuItem("Player " + i); } int player = 0; foreach (InputRoll.RollColumn column in columns) { ToolStripMenuItem menuItem = new ToolStripMenuItem { Text = column.Text + " (" + column.Name + ")", Checked = column.Visible, CheckOnClick = true, Tag = column.Name }; menuItem.CheckedChanged += (o, ev) => { ToolStripMenuItem sender = o as ToolStripMenuItem; TasView.AllColumns.Find(c => c.Name == (string)sender.Tag).Visible = sender.Checked; TasView.AllColumns.ColumnsChanged(); CurrentTasMovie.FlagChanges(); RefreshTasView(); ColumnsSubMenu.ShowDropDown(); (sender.OwnerItem as ToolStripMenuItem).ShowDropDown(); }; if (column.Name.StartsWith("P") && column.Name.Length > 1 && char.IsNumber(column.Name, 1)) { player = int.Parse(column.Name[1].ToString()); } else { player = 0; } playerMenus[player].DropDownItems.Add(menuItem); } for (int i = 1; i < playerMenus.Length; i++) ColumnsSubMenu.DropDownItems.Add(playerMenus[i]); ColumnsSubMenu.DropDownItems.Add(new ToolStripSeparator()); for (int i = 1; i < playerMenus.Length; i++) { ToolStripMenuItem item = new ToolStripMenuItem("Show Player " + i); item.CheckOnClick = true; item.Checked = true; int dummyInt = i; ToolStripMenuItem dummyObject = playerMenus[i]; item.CheckedChanged += (o, ev) => { ToolStripMenuItem sender = o as ToolStripMenuItem; foreach (ToolStripMenuItem menuItem in dummyObject.DropDownItems) { TasView.AllColumns.Find(c => c.Name == (string)menuItem.Tag).Visible = sender.Checked; } CurrentTasMovie.FlagChanges(); RefreshTasView(); }; ColumnsSubMenu.DropDownItems.Add(item); } ColumnsSubMenu.DropDownItems.Add(new ToolStripSeparator()); var defaults = new ToolStripMenuItem { Name = "RestoreDefaultColumnConfiguration", Text = "Restore defaults" }; defaults.Click += (o, ev) => { TasView.AllColumns.Clear(); SetUpColumns(); RefreshTasView(); CurrentTasMovie.FlagChanges(); }; ColumnsSubMenu.DropDownItems.Add(defaults); } #endregion #region Context Menu private void RightClickMenu_Opened(object sender, EventArgs e) { SetMarkersContextMenuItem.Enabled = SelectBetweenMarkersContextMenuItem.Enabled = RemoveMarkersContextMenuItem.Enabled = DeselectContextMenuItem.Enabled = ClearContextMenuItem.Enabled = DeleteFramesContextMenuItem.Enabled = CloneContextMenuItem.Enabled = InsertFrameContextMenuItem.Enabled = InsertNumFramesContextMenuItem.Enabled = TruncateContextMenuItem.Enabled = TasView.AnyRowsSelected; StartNewProjectFromNowMenuItem.Visible = TasView.SelectedRows.Count() == 1 && TasView.SelectedRows.Contains(Emulator.Frame) && !CurrentTasMovie.StartsFromSaveRam; StartANewProjectFromSaveRamMenuItem.Visible = TasView.SelectedRows.Count() == 1 && SaveRamEmulator != null && !CurrentTasMovie.StartsFromSavestate; StartFromNowSeparator.Visible =StartNewProjectFromNowMenuItem.Visible || StartANewProjectFromSaveRamMenuItem.Visible; RemoveMarkersContextMenuItem.Enabled = CurrentTasMovie.Markers.Any(m => TasView.SelectedRows.Contains(m.Frame)); // Disable the option to remove markers if no markers are selected (FCEUX does this). CancelSeekContextMenuItem.Enabled = GlobalWin.MainForm.PauseOnFrame.HasValue; BranchContextMenuItem.Visible = TasView.CurrentCell.RowIndex == Emulator.Frame; } private void CancelSeekContextMenuItem_Click(object sender, EventArgs e) { GlobalWin.MainForm.PauseOnFrame = null; RefreshTasView(); } private void BranchContextMenuItem_Click(object sender, EventArgs e) { BookMarkControl.Branch(); } private void StartNewProjectFromNowMenuItem_Click(object sender, EventArgs e) { if (AskSaveChanges()) { int index = Emulator.Frame; TasMovie newProject = CurrentTasMovie.ConvertToSavestateAnchoredMovie( index, (byte[])StatableEmulator.SaveStateBinary().Clone()); GlobalWin.MainForm.PauseEmulator(); LoadFile(new FileInfo(newProject.Filename), true); } } private void StartANewProjectFromSaveRamMenuItem_Click(object sender, EventArgs e) { if (AskSaveChanges()) { int index = TasView.SelectedRows.First(); GoToFrame(index); TasMovie newProject = CurrentTasMovie.ConvertToSaveRamAnchoredMovie( SaveRamEmulator.CloneSaveRam()); GlobalWin.MainForm.PauseEmulator(); LoadFile(new FileInfo(newProject.Filename), true); } } #endregion } }