public void GoToFrame(int frame, bool fromLua = false, bool fromRewinding = false) { // If seeking to a frame before or at the end of the movie, use StartAtNearestFrameAndEmulate // Otherwise, load the latest state (if not already there) and seek while recording. WasRecording = CurrentTasMovie.IsRecording() || WasRecording; if (frame <= CurrentTasMovie.InputLogLength) { // Get as close as we can then emulate there StartAtNearestFrameAndEmulate(frame, fromLua, fromRewinding); MaybeFollowCursor(); } else // Emulate to a future frame { if (frame == Emulator.Frame + 1) // We are at the end of the movie and advancing one frame, therefore we are recording, simply emulate a frame { bool wasPaused = MainForm.EmulatorPaused; MainForm.FrameAdvance(); if (!wasPaused) { MainForm.UnpauseEmulator(); } } else { TastudioPlayMode(); var lastState = GetPriorStateForFramebuffer(frame); if (lastState.Key > Emulator.Frame) { LoadState(lastState); } StartSeeking(frame); } } }
private bool AutoAdjustInput() { TasMovieRecord lagLog = CurrentTasMovie[Emulator.Frame - 1]; // Minus one because get frame is +1; bool isLag = Emulator.AsInputPollable().IsLagFrame; if (lagLog.WasLagged.HasValue) { if (lagLog.WasLagged.Value && !isLag) { // Deleting this frame requires rewinding a frame. CurrentTasMovie.ChangeLog.AddInputBind(Emulator.Frame - 1, true, "Bind Input; Delete " + (Emulator.Frame - 1)); bool wasRecording = CurrentTasMovie.ChangeLog.IsRecording; CurrentTasMovie.ChangeLog.IsRecording = false; CurrentTasMovie.RemoveFrame(Emulator.Frame - 1); CurrentTasMovie.RemoveLagHistory(Emulator.Frame); // Removes from WasLag CurrentTasMovie.ChangeLog.IsRecording = wasRecording; GoToFrame(Emulator.Frame - 1); return(true); } else if (!lagLog.WasLagged.Value && isLag) { // (it shouldn't need to rewind, since the inserted input wasn't polled) CurrentTasMovie.ChangeLog.AddInputBind(Emulator.Frame - 1, false, "Bind Input; Insert " + (Emulator.Frame - 1)); bool wasRecording = CurrentTasMovie.ChangeLog.IsRecording; CurrentTasMovie.ChangeLog.IsRecording = false; CurrentTasMovie.InsertInput(Emulator.Frame - 1, CurrentTasMovie.GetInputLogEntry(Emulator.Frame - 2)); CurrentTasMovie.InsertLagHistory(Emulator.Frame, true); CurrentTasMovie.ChangeLog.IsRecording = wasRecording; return(true); } } return(false); }
private void TasView_QueryItemText(int index, InputRoll.RollColumn column, out string text) { var overrideText = GetTextOverride(index, column); if (overrideText != null) { text = overrideText; return; } try { text = string.Empty; var columnName = column.Name; if (columnName == MarkerColumnName) { // Do nothing } else if (columnName == FrameColumnName) { text = (index).ToString().PadLeft(CurrentTasMovie.InputLogLength.ToString().Length, '0'); } else { if (index < CurrentTasMovie.InputLogLength) { text = CurrentTasMovie.DisplayValue(index, columnName); } } } catch (Exception ex) { text = string.Empty; MessageBox.Show("oops\n" + ex); } }
private void TasView_MouseMove(object sender, MouseEventArgs e) { // For float editing int increment = (_floatEditYPos - e.Y) / 3; if (_floatEditYPos == -1) { return; } float value = _floatPaintState + increment; Emulation.Common.ControllerDefinition.FloatRange range = Global.MovieSession.MovieControllerAdapter.Type.FloatRanges [Global.MovieSession.MovieControllerAdapter.Type.FloatControls.IndexOf(_floatEditColumn)]; // Range for N64 Y axis has max -128 and min 127. That should probably be fixed in ControllerDefinition.cs. // SuuperW: I really don't think changing it would break anything, but adelikat isn't so sure. float rMax = range.Max; float rMin = range.Min; if (rMax < rMin) { rMax = range.Min; rMin = range.Max; } if (value > rMax) { value = rMax; } else if (value < rMin) { value = rMin; } CurrentTasMovie.SetFloatState(_floatEditRow, _floatEditColumn, value); RefreshDialog(); }
private void SaveAsTas(object sender, EventArgs e) { _autosaveTimer.Stop(); GlobalWin.Sound.StopSound(); ClearLeftMouseStates(); 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; MessageStatusLabel.Text = "Saving..."; this.Cursor = Cursors.WaitCursor; Update(); CurrentTasMovie.Save(); Settings.RecentTas.Add(CurrentTasMovie.Filename); SetTextProperty(); MessageStatusLabel.Text = Path.GetFileName(CurrentTasMovie.Filename) + " saved."; this.Cursor = Cursors.Default; } // keep insisting if (Settings.AutosaveInterval > 0) { _autosaveTimer.Start(); } GlobalWin.Sound.StartSound(); }
public bool AskSaveChanges() { if (_suppressAskSave) { return(true); } if (CurrentTasMovie != null && CurrentTasMovie.Changes) { GlobalWin.Sound.StopSound(); var result = MessageBox.Show( "Save Changes?", "Tastudio", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button3); GlobalWin.Sound.StartSound(); if (result == DialogResult.Yes) { _exiting = true; // Asking to save changes should only ever be called when closing something SaveTas(null, null); } else if (result == DialogResult.No) { CurrentTasMovie.ClearChanges(); return(true); } else if (result == DialogResult.Cancel) { return(false); } } return(true); }
private void StartNewTasMovie() { if (AskSaveChanges()) { Global.MovieSession.Movie = new TasMovie(false, _seekBackgroundWorker); var stateManager = ((TasMovie)Global.MovieSession.Movie).TasStateManager; stateManager.MountWriteAccess(); stateManager.InvalidateCallback = GreenzoneInvalidated; CurrentTasMovie.PropertyChanged += TasMovie_OnPropertyChanged; CurrentTasMovie.Filename = DefaultTasProjName(); // TODO don't do this, take over any mainform actions that can crash without a filename CurrentTasMovie.PopulateWithDefaultHeaderValues(); SetTasMovieCallbacks(); CurrentTasMovie.ClearChanges(); // Don't ask to save changes here. HandleMovieLoadStuff(); CurrentTasMovie.TasStateManager.Capture(); // Capture frame 0 always. // clear all selections TasView.DeselectAll(); BookMarkControl.Restart(); MarkerControl.Restart(); SetUpColumns(); RefreshDialog(); } }
private void TasView_ColumnClick(object sender, InputRoll.ColumnClickEventArgs e) { if (TasView.SelectedRows.Any()) { var columnName = e.Column.Name; if (columnName == FrameColumnName) { CurrentTasMovie.Markers.Add(TasView.LastSelectedIndex.Value, ""); RefreshDialog(); } else if (columnName != MarkerColumnName) // TODO: what about float? { foreach (var index in TasView.SelectedRows) { CurrentTasMovie.ToggleBoolState(index, columnName); _triggerAutoRestore = true; _triggerAutoRestoreFromFrame = TasView.SelectedRows.Min(); } RefreshDialog(); } } }
private void InsertNumFramesMenuItem_Click(object sender, EventArgs e) { bool wasPaused = 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); DoAutoRestore(); } else { RefreshDialog(); } }
private void TasView_PointedCellChanged(object sender, InputRoll.CellEventArgs e) { // TODO: think about nullability // For now return if a null because this happens OnEnter which doesn't have any of the below behaviors yet? // Most of these are stupid but I got annoyed at null crashes if (e.OldCell == null || e.OldCell.Column == null || e.OldCell.RowIndex == null || e.NewCell == null || e.NewCell.RowIndex == null || e.NewCell.Column == null) { return; } // skip rerecord counting on drawing entirely, mouse down is enough // avoid introducing another global bool wasCountingRerecords = Global.MovieSession.Movie.IsCountingRerecords; int startVal, endVal; int frame = e.NewCell.RowIndex.Value; if (e.OldCell.RowIndex.Value < e.NewCell.RowIndex.Value) { startVal = e.OldCell.RowIndex.Value; endVal = e.NewCell.RowIndex.Value; } else { startVal = e.NewCell.RowIndex.Value; endVal = e.OldCell.RowIndex.Value; } if (_startCursorDrag) { if (e.NewCell.RowIndex.HasValue) { GoToFrame(e.NewCell.RowIndex.Value); } } else if (_startSelectionDrag) { if (e.OldCell.RowIndex.HasValue && e.NewCell.RowIndex.HasValue) { for (var i = startVal; i <= endVal; i++) { TasView.SelectRow(i, _selectionDragState); } } } else if (_rightClickFrame != -1) { if (frame > CurrentTasMovie.InputLogLength - _rightClickInput.Length) { frame = CurrentTasMovie.InputLogLength - _rightClickInput.Length; } if (_rightClickShift) { if (_rightClickControl) // Insert { // If going backwards, delete! bool shouldInsert = true; if (startVal < _rightClickFrame) { // Cloning to a previous frame makes no sense. startVal = _rightClickFrame - 1; } if (startVal < _rightClickLastFrame) { shouldInsert = false; } if (shouldInsert) { for (int i = startVal + 1; i <= endVal; i++) { CurrentTasMovie.InsertInput(i, _rightClickInput[(i - _rightClickFrame).Mod(_rightClickInput.Length)]); } } else { CurrentTasMovie.RemoveFrames(startVal + 1, endVal + 1); } _rightClickLastFrame = frame; } else // Overwrite { for (int i = startVal; i <= endVal; i++) { CurrentTasMovie.SetFrame(i, _rightClickInput[(i - _rightClickFrame).Mod(_rightClickInput.Length)]); } } } else { if (_rightClickControl) { for (int i = 0; i < _rightClickInput.Length; i++) // Re-set initial range, just to verify it's still there. { CurrentTasMovie.SetFrame(_rightClickFrame + i, _rightClickInput[i]); } if (_rightClickOverInput != null) // Restore overwritten input from previous movement { for (int i = 0; i < _rightClickOverInput.Length; i++) { CurrentTasMovie.SetFrame(_rightClickLastFrame + i, _rightClickOverInput[i]); } } else { _rightClickOverInput = new string[_rightClickInput.Length]; } _rightClickLastFrame = frame; // Set new restore log CurrentTasMovie.GetLogEntries().CopyTo(frame, _rightClickOverInput, 0, _rightClickOverInput.Length); for (int i = 0; i < _rightClickInput.Length; i++) // Place copied input { CurrentTasMovie.SetFrame(frame + i, _rightClickInput[i]); } } else if (_rightClickAlt) { int shiftBy = _rightClickFrame - frame; string[] shiftInput = new string[Math.Abs(shiftBy)]; int shiftFrom = frame; if (shiftBy < 0) { shiftFrom = _rightClickFrame + _rightClickInput.Length; } CurrentTasMovie.GetLogEntries().CopyTo(shiftFrom, shiftInput, 0, shiftInput.Length); int shiftTo = shiftFrom + (_rightClickInput.Length * Math.Sign(shiftBy)); for (int i = 0; i < shiftInput.Length; i++) { CurrentTasMovie.SetFrame(shiftTo + i, shiftInput[i]); } for (int i = 0; i < _rightClickInput.Length; i++) { CurrentTasMovie.SetFrame(frame + i, _rightClickInput[i]); } _rightClickFrame = frame; } } if (_rightClickAlt || _rightClickControl || _rightClickShift) { JumpToGreenzone(); _triggerAutoRestore = true; _supressContextMenu = true; } } // Left-click else if (TasView.IsPaintDown && e.NewCell.RowIndex.HasValue && !string.IsNullOrEmpty(_startBoolDrawColumn)) { Global.MovieSession.Movie.IsCountingRerecords = false; if (e.OldCell.RowIndex.HasValue && e.NewCell.RowIndex.HasValue) { for (int i = startVal; i <= endVal; i++) // Inclusive on both ends (drawing up or down) { bool setVal = _boolPaintState; if (_patternPaint && _boolPaintState) { if (CurrentTasMovie[frame].Lagged.HasValue && CurrentTasMovie[frame].Lagged.Value) { setVal = CurrentTasMovie.BoolIsPressed(i - 1, _startBoolDrawColumn); } else { setVal = BoolPatterns[controllerType.BoolButtons.IndexOf(_startBoolDrawColumn)].GetNextValue(); } } CurrentTasMovie.SetBoolState(i, _startBoolDrawColumn, setVal); // Notice it uses new row, old column, you can only paint across a single column JumpToGreenzone(); } } } else if (TasView.IsPaintDown && e.NewCell.RowIndex.HasValue && !string.IsNullOrEmpty(_startFloatDrawColumn)) { Global.MovieSession.Movie.IsCountingRerecords = false; if (e.OldCell.RowIndex.HasValue && e.NewCell.RowIndex.HasValue) { for (int i = startVal; i <= endVal; i++) // Inclusive on both ends (drawing up or down) { float setVal = _floatPaintState; if (_patternPaint) { if (CurrentTasMovie[frame].Lagged.HasValue && CurrentTasMovie[frame].Lagged.Value) { setVal = CurrentTasMovie.GetFloatState(i - 1, _startFloatDrawColumn); } else { setVal = FloatPatterns[controllerType.FloatControls.IndexOf(_startFloatDrawColumn)].GetNextValue(); } } CurrentTasMovie.SetFloatState(i, _startFloatDrawColumn, setVal); // Notice it uses new row, old column, you can only paint across a single column JumpToGreenzone(); } } } Global.MovieSession.Movie.IsCountingRerecords = wasCountingRerecords; if (mouseButtonHeld) { TasView.MakeIndexVisible(TasView.CurrentCell.RowIndex.Value); // todo: limit scrolling speed } RefreshTasView(); }
private void Tastudio_Load(object sender, EventArgs e) { if (!InitializeOnLoad()) { Close(); DialogResult = DialogResult.Cancel; return; } SetColumnsFromCurrentStickies(); if (VersionInfo.DeveloperBuild) { RightClickMenu.Items.AddRange(TasView.GenerateContextMenuItems().ToArray()); RightClickMenu.Items .OfType <ToolStripMenuItem>() .First(t => t.Name == "RotateMenuItem") .Click += (o, ov) => { CurrentTasMovie.FlagChanges(); }; } TasView.InputPaintingMode = Settings.DrawInput; TasView.ScrollSpeed = Settings.ScrollSpeed; TasView.AlwaysScroll = Settings.FollowCursorAlwaysScroll; TasView.ScrollMethod = Settings.FollowCursorScrollMethod; TasView.SeekingCutoffInterval = Settings.SeekingCutoffInterval; BookMarkControl.HoverInterval = Settings.BranchCellHoverInterval; _autosaveTimer = new Timer(components); _autosaveTimer.Tick += AutosaveTimerEventProcessor; if (Settings.AutosaveInterval > 0) { _autosaveTimer.Interval = (int)Settings.AutosaveInterval; _autosaveTimer.Start(); } // Remembering Split container logic int defaultMainSplitDistance = MainVertialSplit.SplitterDistance; int defaultBranchMarkerSplitDistance = BranchesMarkersSplit.SplitterDistance; ToolStripMenuItem restoreDefaults = TASMenu.Items .OfType <ToolStripMenuItem>() .Single(t => t.Name == "SettingsSubMenu") .DropDownItems .OfType <ToolStripMenuItem>() .Single(t => t.Text == "Restore &Defaults"); restoreDefaults.Click += (o, ev) => { MainVertialSplit.SplitterDistance = defaultMainSplitDistance; BranchesMarkersSplit.SplitterDistance = defaultBranchMarkerSplitDistance; }; if (Settings.MainVerticalSplitDistance > 0) { try { MainVertialSplit.SplitterDistance = Settings.MainVerticalSplitDistance; } catch (Exception) { MainVertialSplit.SplitterDistance = defaultMainSplitDistance; } } if (Settings.BranchMarkerSplitDistance > 0) { try { BranchesMarkersSplit.SplitterDistance = Settings.BranchMarkerSplitDistance; } catch (Exception) { BranchesMarkersSplit.SplitterDistance = defaultBranchMarkerSplitDistance; } } RefreshDialog(); _initialized = true; }
private void ClearGreenzoneMenuItem_Click(object sender, EventArgs e) { CurrentTasMovie.ClearGreenzone(); RefreshDialog(); }
private void TasView_KeyDown(object sender, KeyEventArgs e) { if (e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.Left) // Ctrl + Left { GoToPreviousMarker(); } else if (e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.Right) // Ctrl + Left { GoToNextMarker(); } else if (e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.Up) // Ctrl + Up { GoToPreviousFrame(); } else if (e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.Down) // Ctrl + Down { GoToNextFrame(); } else if (e.Control && !e.Alt && e.Shift && e.KeyCode == Keys.R) // Ctrl + Shift + R { TasView.HorizontalOrientation ^= true; } // SuuperW: Float Editing if (_floatEditRow != -1) { float value = CurrentTasMovie.GetFloatState(_floatEditRow, _floatEditColumn); float prev = value; string prevTyped = _floatTypedValue; Emulation.Common.ControllerDefinition.FloatRange range = Global.MovieSession.MovieControllerAdapter.Type.FloatRanges [Global.MovieSession.MovieControllerAdapter.Type.FloatControls.IndexOf(_floatEditColumn)]; // Range for N64 Y axis has max -128 and min 127. That should probably be fixed ControllerDefinition.cs, but I'll put a quick fix here anyway. float rMax = range.Max; float rMin = range.Min; if (rMax < rMin) { rMax = range.Min; rMin = range.Max; } if (e.KeyCode == Keys.Right) { value = rMax; } else if (e.KeyCode == Keys.Left) { value = rMin; } else if (e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9) { _floatTypedValue += e.KeyCode - Keys.D0; } else if (e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9) { _floatTypedValue += e.KeyCode - Keys.NumPad0; } else if (e.KeyCode == Keys.OemMinus) { if (_floatTypedValue.StartsWith("-")) { _floatTypedValue = _floatTypedValue.Substring(1); } else { _floatTypedValue = "-" + _floatTypedValue; } } else if (e.KeyCode == Keys.Back) { if (_floatTypedValue == "") // Very first key press is backspace? { _floatTypedValue = value.ToString(); } _floatTypedValue = _floatTypedValue.Substring(0, _floatTypedValue.Length - 1); if (_floatTypedValue == "" || _floatTypedValue == "-") { value = 0f; } else { value = Convert.ToSingle(_floatTypedValue); } } else if (e.KeyCode == Keys.Escape) { if (_floatEditYPos != -1) // Cancel change from dragging cursor { _floatEditYPos = -1; CurrentTasMovie.SetFloatState(_floatEditRow, _floatEditColumn, _floatPaintState); } _floatEditRow = -1; } else { float changeBy = 0; if (e.KeyCode == Keys.Up) { changeBy = 1; // We're assuming for now that ALL float controls should contain integers. } else if (e.KeyCode == Keys.Down) { changeBy = -1; } if (e.Shift) { changeBy *= 10; } value += changeBy; if (changeBy != 0) { _floatTypedValue = value.ToString(); } } if (_floatEditRow == -1) { CurrentTasMovie.ChangeLog.EndBatch(); } else { if (_floatTypedValue == "") { if (prevTyped != "") { value = 0f; CurrentTasMovie.SetFloatState(_floatEditRow, _floatEditColumn, value); } } else { value = Convert.ToSingle(_floatTypedValue); if (value > rMax) { value = rMax; } else if (value < rMin) { value = rMin; } CurrentTasMovie.SetFloatState(_floatEditRow, _floatEditColumn, value); } if (value != prev) // Auto-restore { _triggerAutoRestore = true; _triggerAutoRestoreFromFrame = _floatEditRow; DoTriggeredAutoRestoreIfNeeded(); } } } RefreshDialog(); }
private void TasView_MouseDown(object sender, MouseEventArgs e) { // Clicking with left while right is held or vice versa does weird stuff if (mouseButtonHeld) { return; } if (e.Button == MouseButtons.Middle) { TogglePause(); return; } // SuuperW: Moved these. if (TasView.CurrentCell == null || !TasView.CurrentCell.RowIndex.HasValue || TasView.CurrentCell.Column == null) { return; } int frame = TasView.CurrentCell.RowIndex.Value; string buttonName = TasView.CurrentCell.Column.Name; if (e.Button == MouseButtons.Left) { _leftButtonHeld = true; // SuuperW: Exit float editing mode, or re-enter mouse editing if (_floatEditRow != -1) { if (_floatEditColumn != buttonName || _floatEditRow != frame) { _floatEditRow = -1; RefreshTasView(); } else { _floatEditYPos = e.Y; _floatPaintState = CurrentTasMovie.GetFloatState(frame, buttonName); _triggerAutoRestore = true; _triggerAutoRestoreFromFrame = TasView.CurrentCell.RowIndex.Value; return; } } if (TasView.CurrentCell.Column.Name == MarkerColumnName) { _startMarkerDrag = true; GoToFrame(TasView.CurrentCell.RowIndex.Value); } else if (TasView.CurrentCell.Column.Name == FrameColumnName) { _startFrameDrag = true; _frameDragState = TasView.SelectedRows.Contains(frame); } else // User changed input { if (Global.MovieSession.MovieControllerAdapter.Type.BoolButtons.Contains(buttonName)) { CurrentTasMovie.ChangeLog.BeginNewBatch("Paint Bool"); CurrentTasMovie.ToggleBoolState(TasView.CurrentCell.RowIndex.Value, buttonName); _triggerAutoRestore = true; _triggerAutoRestoreFromFrame = TasView.CurrentCell.RowIndex.Value; RefreshDialog(); _startBoolDrawColumn = buttonName; _boolPaintState = CurrentTasMovie.BoolIsPressed(frame, buttonName); if (applyPatternToPaintedInputToolStripMenuItem.Checked && (!onlyOnAutoFireColumnsToolStripMenuItem.Checked || TasView.CurrentCell.Column.Emphasis)) { BoolPatterns[controllerType.BoolButtons.IndexOf(buttonName)].Reset(); BoolPatterns[controllerType.BoolButtons.IndexOf(buttonName)].GetNextValue(); _patternPaint = true; } else { _patternPaint = false; } } else { if (frame >= CurrentTasMovie.InputLogLength) { CurrentTasMovie.SetFloatState(frame, buttonName, 0); RefreshDialog(); } _triggerAutoRestoreFromFrame = TasView.CurrentCell.RowIndex.Value; _floatPaintState = CurrentTasMovie.GetFloatState(frame, buttonName); if (applyPatternToPaintedInputToolStripMenuItem.Checked && (!onlyOnAutoFireColumnsToolStripMenuItem.Checked || TasView.CurrentCell.Column.Emphasis)) { FloatPatterns[controllerType.FloatControls.IndexOf(buttonName)].Reset(); CurrentTasMovie.SetFloatState(frame, buttonName, FloatPatterns[controllerType.FloatControls.IndexOf(buttonName)].GetNextValue()); _patternPaint = true; } else { _patternPaint = false; } if (e.Clicks != 2) { CurrentTasMovie.ChangeLog.BeginNewBatch("Paint Float"); _startFloatDrawColumn = buttonName; } else // Double-click enters float editing mode { if (_floatEditColumn == buttonName && _floatEditRow == frame) { _floatEditRow = -1; } else { CurrentTasMovie.ChangeLog.BeginNewBatch("Float Edit: " + frame); _floatEditColumn = buttonName; _floatEditRow = frame; _floatTypedValue = ""; _floatEditYPos = e.Y; _triggerAutoRestore = true; _triggerAutoRestoreFromFrame = frame; } RefreshDialog(); } } } } else if (e.Button == System.Windows.Forms.MouseButtons.Right) { if (TasView.CurrentCell.Column.Name == FrameColumnName && frame < CurrentTasMovie.InputLogLength) { _rightClickControl = (Control.ModifierKeys | Keys.Control) == Control.ModifierKeys; _rightClickShift = (Control.ModifierKeys | Keys.Shift) == Control.ModifierKeys; if (TasView.SelectedRows.Contains(frame)) { _rightClickInput = new string[TasView.SelectedRows.Count()]; _rightClickFrame = TasView.FirstSelectedIndex.Value; CurrentTasMovie.GetLogEntries().CopyTo(_rightClickFrame, _rightClickInput, 0, TasView.SelectedRows.Count()); if (_rightClickControl && _rightClickShift) { _rightClickFrame += _rightClickInput.Length; } } else { _rightClickInput = new string[1]; _rightClickInput[0] = CurrentTasMovie.GetLogEntries()[frame]; _rightClickFrame = frame; } _rightClickLastFrame = -1; _triggerAutoRestoreFromFrame = TasView.CurrentCell.RowIndex.Value; // TODO: Turn off ChangeLog.IsRecording and handle the GeneralUndo here. CurrentTasMovie.ChangeLog.BeginNewBatch("Right-Click Edit"); } } }
// SuuperW: I changed this to public so that it could be used by MarkerControl.cs public void GoToFrame(int frame) { // If past greenzone, emulate and capture states // If past greenzone AND movie, record input and capture states // If in greenzone, loadstate // If near a greenzone item, load and emulate // Do capturing and recording as needed if (frame < CurrentTasMovie.InputLogLength) { if (frame < Emulator.Frame) // We are rewinding { int goToFrame = frame == 0 ? 0 : frame - 1; if (CurrentTasMovie[goToFrame].HasState) // Go back 1 frame and emulate to get the display (we don't store that) { CurrentTasMovie.SwitchToPlay(); LoadState(CurrentTasMovie.TasStateManager[goToFrame]); // STATE ACCESS if (frame > 0) // We can't emulate up to frame 0! { bool wasPaused = GlobalWin.MainForm.EmulatorPaused; GlobalWin.MainForm.FrameAdvance(); if (!wasPaused) { GlobalWin.MainForm.UnpauseEmulator(); } } GlobalWin.DisplayManager.NeedsToPaint = true; SetVisibleIndex(frame); } else // Get as close as we can then emulate there { StartAtNearestFrameAndEmulate(frame); return; } } else // We are going foward { if (frame == Emulator.Frame + 1) // Just emulate a frame we only have 1 to go! { bool wasPaused = GlobalWin.MainForm.EmulatorPaused; GlobalWin.MainForm.FrameAdvance(); if (!wasPaused) { GlobalWin.MainForm.UnpauseEmulator(); } } else { var goToFrame = frame == 0 ? 0 : frame - 1; if (CurrentTasMovie[goToFrame].HasState) // Can we go directly there? { CurrentTasMovie.SwitchToPlay(); LoadState(CurrentTasMovie.TasStateManager[goToFrame]); // STATE ACCESS Emulator.FrameAdvance(true); GlobalWin.DisplayManager.NeedsToPaint = true; SetVisibleIndex(frame); } else { StartAtNearestFrameAndEmulate(frame); return; } } } } else // Emulate to a future frame { if (frame == Emulator.Frame + 1) // We are at the end of the movie and advancing one frame, therefore we are recording, simply emulate a frame { bool wasPaused = GlobalWin.MainForm.EmulatorPaused; GlobalWin.MainForm.FrameAdvance(); if (!wasPaused) { GlobalWin.MainForm.UnpauseEmulator(); } } else { // TODO: get the last greenzone frame and go there CurrentTasMovie.SwitchToPlay(); // no reason to loadstate when we can emulate a frame instead if (frame - Emulator.Frame != 1) { LoadState(CurrentTasMovie.TasStateManager[CurrentTasMovie.TasStateManager.LastEmulatedFrame]); // STATE ACCESS } if (frame != Emulator.Frame) // If we aren't already at our destination, seek { GlobalWin.MainForm.UnpauseEmulator(); if (Settings.AutoPause && frame < CurrentTasMovie.InputLogLength) { GlobalWin.MainForm.PauseOnFrame = CurrentTasMovie.InputLogLength; } else { GlobalWin.MainForm.PauseOnFrame = frame; } } } } RefreshDialog(); UpdateOtherTools(); }
private void TasView_MouseDown(object sender, MouseEventArgs e) { // Clicking with left while right is held or vice versa does weird stuff if (mouseButtonHeld) { return; } if (e.Button == MouseButtons.Middle) { if (Mainform.EmulatorPaused) { TasMovieRecord record = CurrentTasMovie[LastPositionFrame]; if (!record.Lagged.HasValue && LastPositionFrame > Global.Emulator.Frame) { StartSeeking(LastPositionFrame); } else { Mainform.UnpauseEmulator(); } } else { Mainform.PauseEmulator(); } return; } // SuuperW: Moved these. if (TasView.CurrentCell == null || !TasView.CurrentCell.RowIndex.HasValue || TasView.CurrentCell.Column == null) { return; } int frame = TasView.CurrentCell.RowIndex.Value; string buttonName = TasView.CurrentCell.Column.Name; if (e.Button == MouseButtons.Left) { bool wasHeld = _leftButtonHeld; _leftButtonHeld = true; // SuuperW: Exit float editing mode, or re-enter mouse editing if (_floatEditRow != -1) { if (_floatEditColumn != buttonName || _floatEditRow != frame) { floatEditRow = -1; RefreshTasView(); } else { _floatEditYPos = e.Y; _floatPaintState = CurrentTasMovie.GetFloatState(frame, buttonName); _triggerAutoRestore = true; JumpToGreenzone(); return; } } if (TasView.CurrentCell.Column.Name == CursorColumnName) { _startCursorDrag = true; GoToFrame(TasView.CurrentCell.RowIndex.Value); } else if (TasView.CurrentCell.Column.Name == FrameColumnName) { if (Control.ModifierKeys == Keys.Alt && CurrentTasMovie.Markers.IsMarker(frame)) { // TODO TasView.DragCurrentCell(); } else { _startSelectionDrag = true; _selectionDragState = TasView.SelectedRows.Contains(frame); } } else // User changed input { bool wasPaused = Mainform.EmulatorPaused; if (Emulator.Frame > frame || CurrentTasMovie.LastValidFrame > frame) { if (wasPaused && !Mainform.IsSeeking && !CurrentTasMovie.LastPositionStable) { LastPositionFrame = Emulator.Frame; CurrentTasMovie.LastPositionStable = true; // until new frame is emulated } } if (Global.MovieSession.MovieControllerAdapter.Type.BoolButtons.Contains(buttonName)) { CurrentTasMovie.ChangeLog.BeginNewBatch("Paint Bool " + buttonName + " from frame " + frame); CurrentTasMovie.ToggleBoolState(TasView.CurrentCell.RowIndex.Value, buttonName); _triggerAutoRestore = true; JumpToGreenzone(); RefreshDialog(); _startBoolDrawColumn = buttonName; _boolPaintState = CurrentTasMovie.BoolIsPressed(frame, buttonName); if (applyPatternToPaintedInputToolStripMenuItem.Checked && (!onlyOnAutoFireColumnsToolStripMenuItem.Checked || TasView.CurrentCell.Column.Emphasis)) { BoolPatterns[controllerType.BoolButtons.IndexOf(buttonName)].Reset(); BoolPatterns[controllerType.BoolButtons.IndexOf(buttonName)].GetNextValue(); _patternPaint = true; } else { _patternPaint = false; } if (!Settings.AutoRestoreOnMouseUpOnly) { DoTriggeredAutoRestoreIfNeeded(); } } else { if (frame >= CurrentTasMovie.InputLogLength) { CurrentTasMovie.SetFloatState(frame, buttonName, 0); RefreshDialog(); } JumpToGreenzone(); _floatPaintState = CurrentTasMovie.GetFloatState(frame, buttonName); if (applyPatternToPaintedInputToolStripMenuItem.Checked && (!onlyOnAutoFireColumnsToolStripMenuItem.Checked || TasView.CurrentCell.Column.Emphasis)) { FloatPatterns[controllerType.FloatControls.IndexOf(buttonName)].Reset(); CurrentTasMovie.SetFloatState(frame, buttonName, FloatPatterns[controllerType.FloatControls.IndexOf(buttonName)].GetNextValue()); _patternPaint = true; } else { _patternPaint = false; } if (e.Clicks != 2) { CurrentTasMovie.ChangeLog.BeginNewBatch("Paint Float " + buttonName + " from frame " + frame); _startFloatDrawColumn = buttonName; } else // Double-click enters float editing mode { if (_floatEditColumn == buttonName && _floatEditRow == frame) { floatEditRow = -1; } else { CurrentTasMovie.ChangeLog.BeginNewBatch("Float Edit: " + frame); _floatEditColumn = buttonName; floatEditRow = frame; _floatTypedValue = ""; _floatEditYPos = e.Y; _triggerAutoRestore = true; JumpToGreenzone(); } RefreshDialog(); } } // taseditor behavior if (!wasPaused) { Mainform.UnpauseEmulator(); } } } else if (e.Button == System.Windows.Forms.MouseButtons.Right) { if (TasView.CurrentCell.Column.Name == FrameColumnName && frame < CurrentTasMovie.InputLogLength) { _rightClickControl = (Control.ModifierKeys | Keys.Control) == Control.ModifierKeys; _rightClickShift = (Control.ModifierKeys | Keys.Shift) == Control.ModifierKeys; _rightClickAlt = (Control.ModifierKeys | Keys.Alt) == Control.ModifierKeys; if (TasView.SelectedRows.Contains(frame)) { _rightClickInput = new string[TasView.SelectedRows.Count()]; _rightClickFrame = TasView.FirstSelectedIndex.Value; CurrentTasMovie.GetLogEntries().CopyTo(_rightClickFrame, _rightClickInput, 0, TasView.SelectedRows.Count()); if (_rightClickControl && _rightClickShift) { _rightClickFrame += _rightClickInput.Length; } } else { _rightClickInput = new string[1]; _rightClickInput[0] = CurrentTasMovie.GetLogEntries()[frame]; _rightClickFrame = frame; } _rightClickLastFrame = -1; if (_rightClickAlt || _rightClickControl || _rightClickShift) { JumpToGreenzone(); // TODO: Turn off ChangeLog.IsRecording and handle the GeneralUndo here. string undoStepName = "Right-Click Edit:"; if (_rightClickShift) { undoStepName += " Extend Input"; if (_rightClickControl) { undoStepName += ", Insert"; } } else { if (_rightClickControl) { undoStepName += " Copy"; } else // _rightClickAlt { undoStepName += " Move"; } } CurrentTasMovie.ChangeLog.BeginNewBatch(undoStepName); } } } }
private void TasView_ColumnReordered(object sender, InputRoll.ColumnReorderedEventArgs e) { CurrentTasMovie.FlagChanges(); }
private void Tastudio_Load(object sender, EventArgs e) { if (!InitializeOnLoad()) { Close(); DialogResult = DialogResult.Cancel; return; } // Set the screenshot to "1x" resolution of the core // cores like n64 and psx are going to still have sizes too big for the control, so cap them int width = VideoProvider.BufferWidth; int height = VideoProvider.BufferHeight; if (width > 320) { double ratio = 320.0 / (double)width; width = 320; height = (int)((double)(height) * ratio); } ScreenshotControl.DrawingHeight = height; ScreenshotControl.Size = new Size(width, ScreenshotControl.DrawingHeight + ScreenshotControl.UserPadding); ScreenshotControl.Visible = false; Controls.Add(ScreenshotControl); ScreenshotControl.BringToFront(); SetColumnsFromCurrentStickies(); if (VersionInfo.DeveloperBuild) { RightClickMenu.Items.AddRange(TasView.GenerateContextMenuItems().ToArray()); RightClickMenu.Items .OfType <ToolStripMenuItem>() .First(t => t.Name == "RotateMenuItem") .Click += (o, ov) => { CurrentTasMovie.FlagChanges(); }; } TasView.InputPaintingMode = Settings.DrawInput; TasView.ScrollSpeed = Settings.ScrollSpeed; TasView.AlwaysScroll = Settings.FollowCursorAlwaysScroll; TasView.ScrollMethod = Settings.FollowCursorScrollMethod; TasView.SeekingCutoffInterval = Settings.SeekingCutoffInterval; BookMarkControl.HoverInterval = Settings.BranchCellHoverInterval; _autosaveTimer.Tick += AutosaveTimerEventProcessor; if (Settings.AutosaveInterval > 0) { _autosaveTimer.Interval = (int)Settings.AutosaveInterval; _autosaveTimer.Start(); } // Remembering Split container logic int defaultMainSplitDistance = MainVertialSplit.SplitterDistance; int defaultBranchMarkerSplitDistance = BranchesMarkersSplit.SplitterDistance; ToolStripMenuItem restoreDefaults = TASMenu.Items .OfType <ToolStripMenuItem>() .Single(t => t.Name == "SettingsSubMenu") .DropDownItems .OfType <ToolStripMenuItem>() .Single(t => t.Text == "Restore &Defaults"); restoreDefaults.Click += (o, ev) => { MainVertialSplit.SplitterDistance = defaultMainSplitDistance; BranchesMarkersSplit.SplitterDistance = defaultBranchMarkerSplitDistance; }; if (Settings.MainVerticalSplitDistance > 0) { MainVertialSplit.SplitterDistance = Settings.MainVerticalSplitDistance; } if (Settings.BranchMarkerSplitDistance > 0) { BranchesMarkersSplit.SplitterDistance = Settings.BranchMarkerSplitDistance; } //////////////// RefreshDialog(); _initialized = true; }
private void TasView_PointedCellChanged(object sender, InputRoll.CellEventArgs e) { // TODO: think about nullability // For now return if a null because this happens OnEnter which doesn't have any of the below behaviors yet? // Most of these are stupid but I got annoyed at null crashes if (e.OldCell == null || e.OldCell.Column == null || e.OldCell.RowIndex == null || e.NewCell == null || e.NewCell.RowIndex == null || e.NewCell.Column == null) { return; } int startVal, endVal; int frame = e.NewCell.RowIndex.Value; if (e.OldCell.RowIndex.Value < e.NewCell.RowIndex.Value) { startVal = e.OldCell.RowIndex.Value; endVal = e.NewCell.RowIndex.Value; } else { startVal = e.NewCell.RowIndex.Value; endVal = e.OldCell.RowIndex.Value; } if (_startMarkerDrag) { if (e.NewCell.RowIndex.HasValue) { GoToFrame(e.NewCell.RowIndex.Value); } } else if (_startFrameDrag) { if (e.OldCell.RowIndex.HasValue && e.NewCell.RowIndex.HasValue) { for (var i = startVal; i <= endVal; i++) { TasView.SelectRow(i, _frameDragState); } RefreshTasView(); } } else if (_rightClickFrame != -1) { _triggerAutoRestore = true; _supressContextMenu = true; if (frame > CurrentTasMovie.InputLogLength - _rightClickInput.Length) { frame = CurrentTasMovie.InputLogLength - _rightClickInput.Length; } if (_rightClickShift) { if (_rightClickControl) // Insert { // If going backwards, delete! bool shouldInsert = true; if (startVal < _rightClickFrame) { // Cloning to a previous frame makes no sense. startVal = _rightClickFrame - 1; } if (startVal < _rightClickLastFrame) { shouldInsert = false; } if (shouldInsert) { for (int i = startVal + 1; i <= endVal; i++) { CurrentTasMovie.InsertInput(i, _rightClickInput[(i - _rightClickFrame) % _rightClickInput.Length]); } } else { CurrentTasMovie.RemoveFrames(startVal + 1, endVal + 1); } _rightClickLastFrame = frame; } else // Overwrite { for (int i = startVal; i <= endVal; i++) { CurrentTasMovie.SetFrame(i, _rightClickInput[(_rightClickFrame - i) % _rightClickInput.Length]); } if (startVal < _triggerAutoRestoreFromFrame) { _triggerAutoRestoreFromFrame = startVal; } } } else { if (_rightClickControl) { for (int i = 0; i < _rightClickInput.Length; i++) // Re-set initial range, just to verify it's still there. { CurrentTasMovie.SetFrame(_rightClickFrame + i, _rightClickInput[i]); } if (_rightClickOverInput != null) // Restore overwritten input from previous movement { for (int i = 0; i < _rightClickOverInput.Length; i++) { CurrentTasMovie.SetFrame(_rightClickLastFrame + i, _rightClickOverInput[i]); } } else { _rightClickOverInput = new string[_rightClickInput.Length]; } _rightClickLastFrame = frame; // Set new restore log CurrentTasMovie.GetLogEntries().CopyTo(frame, _rightClickOverInput, 0, _rightClickOverInput.Length); for (int i = 0; i < _rightClickInput.Length; i++) // Place copied input { CurrentTasMovie.SetFrame(frame + i, _rightClickInput[i]); } } else { int shiftBy = _rightClickFrame - frame; string[] shiftInput = new string[Math.Abs(shiftBy)]; int shiftFrom = frame; if (shiftBy < 0) { shiftFrom = _rightClickFrame + _rightClickInput.Length; } CurrentTasMovie.GetLogEntries().CopyTo(shiftFrom, shiftInput, 0, shiftInput.Length); int shiftTo = shiftFrom + (_rightClickInput.Length * Math.Sign(shiftBy)); for (int i = 0; i < shiftInput.Length; i++) { CurrentTasMovie.SetFrame(shiftTo + i, shiftInput[i]); } for (int i = 0; i < _rightClickInput.Length; i++) { CurrentTasMovie.SetFrame(frame + i, _rightClickInput[i]); } _rightClickFrame = frame; } if (frame < _triggerAutoRestoreFromFrame) { _triggerAutoRestoreFromFrame = frame; } } RefreshTasView(); } else if (TasView.IsPaintDown && e.NewCell.RowIndex.HasValue && !string.IsNullOrEmpty(_startBoolDrawColumn)) { if (e.OldCell.RowIndex.HasValue && e.NewCell.RowIndex.HasValue) { for (var i = startVal + 1; i <= endVal; i++) // SuuperW: <= so that it will edit the cell you are hovering over. (Inclusive) { bool setVal = _boolPaintState; if (_patternPaint && _boolPaintState) { if (CurrentTasMovie[frame].Lagged.HasValue && CurrentTasMovie[frame].Lagged.Value) { setVal = CurrentTasMovie.BoolIsPressed(i - 1, _startBoolDrawColumn); } else { setVal = BoolPatterns[controllerType.BoolButtons.IndexOf(_startBoolDrawColumn)].GetNextValue(); } } CurrentTasMovie.SetBoolState(i, _startBoolDrawColumn, setVal); // Notice it uses new row, old column, you can only paint across a single column if (TasView.CurrentCell.RowIndex.Value < _triggerAutoRestoreFromFrame) { _triggerAutoRestoreFromFrame = TasView.CurrentCell.RowIndex.Value; } } RefreshTasView(); } } else if (TasView.IsPaintDown && e.NewCell.RowIndex.HasValue && !string.IsNullOrEmpty(_startFloatDrawColumn)) { if (e.OldCell.RowIndex.HasValue && e.NewCell.RowIndex.HasValue) { for (var i = startVal + 1; i <= endVal; i++) // SuuperW: <= so that it will edit the cell you are hovering over. (Inclusive) { float setVal = _floatPaintState; if (_patternPaint) { if (CurrentTasMovie[frame].Lagged.HasValue && CurrentTasMovie[frame].Lagged.Value) { setVal = CurrentTasMovie.GetFloatState(i - 1, _startFloatDrawColumn); } else { setVal = FloatPatterns[controllerType.FloatControls.IndexOf(_startFloatDrawColumn)].GetNextValue(); } } CurrentTasMovie.SetFloatState(i, _startFloatDrawColumn, setVal); // Notice it uses new row, old column, you can only paint across a single column if (TasView.CurrentCell.RowIndex.Value < _triggerAutoRestoreFromFrame) { _triggerAutoRestoreFromFrame = TasView.CurrentCell.RowIndex.Value; } } RefreshTasView(); } } }
private void RotateMenuItem_Click(object sender, EventArgs e) { TasView.HorizontalOrientation ^= true; CurrentTasMovie.FlagChanges(); }
private void Tastudio_Load(object sender, EventArgs e) { if (!InitializeOnLoad()) { Close(); DialogResult = DialogResult.Cancel; return; } SetColumnsFromCurrentStickies(); if (TasView.Rotatable) { RightClickMenu.Items.AddRange(TasView.GenerateContextMenuItems() .ToArray()); RightClickMenu.Items .OfType <ToolStripMenuItem>() .First(t => t.Name == "RotateMenuItem") .Click += (o, ov) => { CurrentTasMovie.FlagChanges(); }; } TasView.ScrollSpeed = Settings.ScrollSpeed; TasView.AlwaysScroll = Settings.FollowCursorAlwaysScroll; TasView.ScrollMethod = Settings.FollowCursorScrollMethod; TasView.SeekingCutoffInterval = Settings.SeekingCutoffInterval; BookMarkControl.HoverInterval = Settings.BranchCellHoverInterval; _autosaveTimer = new Timer(components); _autosaveTimer.Tick += AutosaveTimerEventProcessor; if (Settings.AutosaveInterval > 0) { _autosaveTimer.Interval = (int)Settings.AutosaveInterval; _autosaveTimer.Start(); } // Remembering Split container logic if (Settings.MainVerticalSplitDistance > 0) { try { MainVertialSplit.SplitterDistance = Settings.MainVerticalSplitDistance; } catch (Exception) { MainVertialSplit.SplitterDistance = _defaultMainSplitDistance; } } if (Settings.BranchMarkerSplitDistance > 0) { try { BranchesMarkersSplit.SplitterDistance = Settings.BranchMarkerSplitDistance; } catch (Exception) { BranchesMarkersSplit.SplitterDistance = _defaultBranchMarkerSplitDistance; } } TasView.Font = TasViewFont; CurrentTasMovie.BindMarkersToInput = Settings.BindMarkersToInput; RefreshDialog(); _initialized = true; }
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); }