2013-12-01 04:00:02 +00:00
using System ;
using System.Collections.Generic ;
2015-07-25 15:08:23 +00:00
using System.Drawing ;
2013-12-01 04:00:02 +00:00
using System.IO ;
2013-12-05 19:18:20 +00:00
using System.Linq ;
2013-12-01 04:00:02 +00:00
using System.Windows.Forms ;
2014-08-23 18:02:02 +00:00
using System.ComponentModel ;
2013-12-01 20:55:52 +00:00
2014-11-30 16:42:58 +00:00
using BizHawk.Emulation.Common ;
2014-12-05 00:52:16 +00:00
using BizHawk.Emulation.Common.IEmulatorExtensions ;
2014-11-30 16:42:58 +00:00
2013-12-01 04:00:02 +00:00
using BizHawk.Client.Common ;
2014-07-06 21:20:43 +00:00
using BizHawk.Client.Common.MovieConversionExtensions ;
2014-07-27 15:22:30 +00:00
using BizHawk.Client.EmuHawk.WinFormExtensions ;
2014-07-28 01:51:11 +00:00
using BizHawk.Client.EmuHawk.ToolExtensions ;
2013-12-01 04:00:02 +00:00
namespace BizHawk.Client.EmuHawk
{
2016-01-31 01:24:30 +00:00
public partial class TAStudio : ToolFormBase , IToolFormAutoConfig , IControlMainform
2013-12-01 04:00:02 +00:00
{
2013-12-14 14:40:33 +00:00
// TODO: UI flow that conveniently allows to start from savestate
2015-07-13 19:02:21 +00:00
private const string CursorColumnName = "CursorColumn" ;
2013-12-07 17:29:47 +00:00
private const string FrameColumnName = "FrameColumn" ;
2013-12-06 15:47:23 +00:00
2014-02-01 15:44:51 +00:00
private readonly List < TasClipboardEntry > _tasClipboard = new List < TasClipboardEntry > ( ) ;
2015-02-24 06:47:32 +00:00
private BackgroundWorker _saveBackgroundWorker ;
2015-12-12 20:59:55 +00:00
private BackgroundWorker _seekBackgroundWorker ;
2015-01-03 02:29:55 +00:00
2014-07-14 00:35:33 +00:00
private MovieEndAction _originalEndAction ; // The movie end behavior selected by the user (that is overridden by TAStudio)
2014-07-09 21:56:27 +00:00
private Dictionary < string , string > GenerateColumnNames ( )
2014-07-06 22:13:12 +00:00
{
2014-07-09 21:56:27 +00:00
var lg = Global . MovieSession . LogGeneratorInstance ( ) ;
lg . SetSource ( Global . MovieSession . MovieControllerAdapter ) ;
return ( lg as Bk2LogEntryGenerator ) . Map ( ) ;
2014-07-06 22:13:12 +00:00
}
2013-12-01 04:00:02 +00:00
2016-04-24 10:48:49 +00:00
private UndoHistoryForm _undoForm ;
private Timer _autosaveTimer = new Timer ( ) ;
2015-03-04 19:03:00 +00:00
2015-07-25 12:40:17 +00:00
public ScreenshotPopupControl ScreenshotControl = new ScreenshotPopupControl
2015-07-25 15:08:23 +00:00
{
2015-07-25 16:01:26 +00:00
Size = new Size ( 256 , 240 ) ,
2015-07-25 15:08:23 +00:00
} ;
2015-07-25 12:40:17 +00:00
2015-07-30 20:14:14 +00:00
public string statesPath
{
get { return PathManager . MakeAbsolutePath ( Global . Config . PathEntries [ "Global" , "TAStudio states" ] . Path , null ) ; }
}
2015-12-05 17:32:56 +00:00
public bool IsInMenuLoop { get ; private set ; }
2015-01-01 18:24:35 +00:00
[ConfigPersist]
public TAStudioSettings Settings { get ; set ; }
public class TAStudioSettings
{
public TAStudioSettings ( )
{
RecentTas = new RecentFiles ( 8 ) ;
DrawInput = true ;
AutoPause = true ;
FollowCursor = true ;
2016-04-17 20:29:25 +00:00
ScrollSpeed = 6 ;
2015-07-26 01:01:02 +00:00
FollowCursorAlwaysScroll = false ;
FollowCursorScrollMethod = "near" ;
2015-11-30 20:44:31 +00:00
BranchCellHoverInterval = 1 ;
2016-04-17 18:02:21 +00:00
SeekingCutoffInterval = 2 ; // unused, relying on VisibleRows is smarter
2016-07-10 19:25:02 +00:00
AutoRestoreOnMouseUpOnly = false ; // default to taseditor way, must be harmless since we suspend rerecord counting while drawing
2016-04-24 10:48:49 +00:00
AutosaveInterval = 120000 ;
AutosaveAsBk2 = false ;
2016-06-12 13:41:27 +00:00
AutosaveAsBackupFile = false ;
BackupPerFileSave = false ;
2016-11-12 14:52:53 +00:00
SingleClickFloatEdit = false ;
2015-08-30 16:45:14 +00:00
// default to taseditor fashion
2016-11-17 17:25:06 +00:00
DenoteStatesWithIcons = false ;
DenoteStatesWithBGColor = true ;
DenoteMarkersWithIcons = false ;
DenoteMarkersWithBGColor = true ;
2015-01-01 18:24:35 +00:00
}
public RecentFiles RecentTas { get ; set ; }
public bool DrawInput { get ; set ; }
public bool AutoPause { get ; set ; }
public bool AutoRestoreLastPosition { get ; set ; }
public bool FollowCursor { get ; set ; }
public bool EmptyMarkers { get ; set ; }
2015-07-25 08:20:16 +00:00
public int ScrollSpeed { get ; set ; }
2015-07-25 08:33:23 +00:00
public bool FollowCursorAlwaysScroll { get ; set ; }
2015-08-30 16:45:14 +00:00
public string FollowCursorScrollMethod { get ; set ; }
2015-11-30 20:44:31 +00:00
public int BranchCellHoverInterval { get ; set ; }
2016-01-27 13:18:20 +00:00
public int SeekingCutoffInterval { get ; set ; }
2016-06-13 15:29:29 +00:00
public bool AutoRestoreOnMouseUpOnly { get ; set ; }
2016-06-10 13:05:12 +00:00
public uint AutosaveInterval { get ; set ; }
2016-04-24 10:48:49 +00:00
public bool AutosaveAsBk2 { get ; set ; }
2016-06-12 13:41:27 +00:00
public bool AutosaveAsBackupFile { get ; set ; }
public bool BackupPerFileSave { get ; set ; }
2016-11-12 14:52:53 +00:00
public bool SingleClickFloatEdit { get ; set ; }
2016-11-17 17:25:06 +00:00
public bool DenoteStatesWithIcons { get ; set ; }
public bool DenoteStatesWithBGColor { get ; set ; }
public bool DenoteMarkersWithIcons { get ; set ; }
public bool DenoteMarkersWithBGColor { get ; set ; }
2015-07-26 00:19:47 +00:00
public int MainVerticalSplitDistance { get ; set ; }
public int BranchMarkerSplitDistance { get ; set ; }
2015-01-01 18:24:35 +00:00
}
2014-10-20 19:04:59 +00:00
public TasMovie CurrentTasMovie
{
get { return Global . MovieSession . Movie as TasMovie ; }
}
2016-08-29 16:38:36 +00:00
public MainForm Mainform
{
get { return GlobalWin . MainForm ; }
}
2016-11-21 17:03:56 +00:00
/// <summary>
/// Separates "restore last position" logic from seeking caused by navigation.
/// TASEditor never kills LastPositionFrame, and it only pauses on it,
/// if it hasn't been greenzoned beforehand and middle mouse button was pressed.
/// </summary>
public int LastPositionFrame { get ; set ; }
2016-08-27 22:08:43 +00:00
2015-03-16 20:42:14 +00:00
#region "Initializing"
2013-12-01 04:00:02 +00:00
public TAStudio ( )
{
2016-02-06 02:57:40 +00:00
Settings = new TAStudioSettings ( ) ;
2013-12-01 04:00:02 +00:00
InitializeComponent ( ) ;
2015-07-26 01:31:06 +00:00
2015-02-24 06:47:32 +00:00
// TODO: show this at all times or hide it when saving is done?
this . SavingProgressBar . Visible = false ;
2015-03-02 23:43:52 +00:00
InitializeSaveWorker ( ) ;
2015-12-12 20:59:55 +00:00
InitializeSeekWorker ( ) ;
2015-03-02 23:43:52 +00:00
WantsToControlStopMovie = true ;
2016-06-11 14:38:53 +00:00
WantsToControlRestartMovie = true ;
2015-03-02 23:43:52 +00:00
TasPlaybackBox . Tastudio = this ;
MarkerControl . Tastudio = this ;
2015-07-18 20:13:38 +00:00
BookMarkControl . Tastudio = this ;
2015-03-02 23:43:52 +00:00
MarkerControl . Emulator = this . Emulator ;
TasView . QueryItemText + = TasView_QueryItemText ;
TasView . QueryItemBkColor + = TasView_QueryItemBkColor ;
2015-03-19 19:55:38 +00:00
TasView . QueryRowBkColor + = TasView_QueryRowBkColor ;
2015-03-02 23:43:52 +00:00
TasView . QueryItemIcon + = TasView_QueryItemIcon ;
TasView . QueryFrameLag + = TasView_QueryFrameLag ;
TasView . PointedCellChanged + = TasView_PointedCellChanged ;
TasView . MultiSelect = true ;
TasView . MaxCharactersInHorizontal = 1 ;
2016-11-21 17:03:56 +00:00
LastPositionFrame = - 1 ;
2016-04-24 10:48:49 +00:00
}
private void AutosaveTimerEventProcessor ( object sender , EventArgs e )
{
2016-06-10 13:05:12 +00:00
if ( CurrentTasMovie = = null )
2016-04-24 10:48:49 +00:00
return ;
2016-06-10 13:05:12 +00:00
if ( ! CurrentTasMovie . Changes | | Settings . AutosaveInterval = = 0 )
return ;
2016-06-12 13:41:27 +00:00
if ( Settings . AutosaveAsBackupFile )
2016-04-24 10:48:49 +00:00
{
2016-06-12 13:41:27 +00:00
if ( Settings . AutosaveAsBk2 )
SaveBk2BackupMenuItem_Click ( sender , e ) ;
else
SaveBackupMenuItem_Click ( sender , e ) ;
2016-04-24 10:48:49 +00:00
}
else
{
2016-06-12 13:41:27 +00:00
if ( Settings . AutosaveAsBk2 )
ToBk2MenuItem_Click ( sender , e ) ;
else
SaveTas ( sender , e ) ;
2016-04-24 10:48:49 +00:00
}
2015-03-02 23:43:52 +00:00
}
private void InitializeSaveWorker ( )
{
if ( _saveBackgroundWorker ! = null )
{
_saveBackgroundWorker . Dispose ( ) ;
_saveBackgroundWorker = null ; // Idk if this line is even useful.
}
2015-02-24 06:47:32 +00:00
_saveBackgroundWorker = new BackgroundWorker ( ) ;
_saveBackgroundWorker . WorkerReportsProgress = true ;
_saveBackgroundWorker . DoWork + = ( s , e ) = >
{
this . Invoke ( ( ) = > this . MessageStatusLabel . Text = "Saving " + Path . GetFileName ( CurrentTasMovie . Filename ) + "..." ) ;
this . Invoke ( ( ) = > this . SavingProgressBar . Visible = true ) ;
CurrentTasMovie . Save ( ) ;
} ;
_saveBackgroundWorker . ProgressChanged + = ( s , e ) = >
{
SavingProgressBar . Value = e . ProgressPercentage ;
} ;
_saveBackgroundWorker . RunWorkerCompleted + = ( s , e ) = >
{
this . Invoke ( ( ) = > this . MessageStatusLabel . Text = Path . GetFileName ( CurrentTasMovie . Filename ) + " saved." ) ;
this . Invoke ( ( ) = > this . SavingProgressBar . Visible = false ) ;
2015-03-02 23:43:52 +00:00
InitializeSaveWorker ( ) ; // Required, or it will error when trying to report progress again.
2015-02-24 06:47:32 +00:00
} ;
2015-01-03 02:29:55 +00:00
2015-03-02 23:43:52 +00:00
if ( CurrentTasMovie ! = null ) // Again required. TasMovie has a separate reference.
CurrentTasMovie . NewBGWorker ( _saveBackgroundWorker ) ;
2013-12-01 04:00:02 +00:00
}
2015-12-12 20:59:55 +00:00
private void InitializeSeekWorker ( )
{
if ( _seekBackgroundWorker ! = null )
{
_seekBackgroundWorker . Dispose ( ) ;
_seekBackgroundWorker = null ; // Idk if this line is even useful.
}
_seekBackgroundWorker = new BackgroundWorker ( ) ;
_seekBackgroundWorker . WorkerReportsProgress = true ;
_seekBackgroundWorker . WorkerSupportsCancellation = true ;
_seekBackgroundWorker . DoWork + = ( s , e ) = >
{
this . Invoke ( ( ) = > this . MessageStatusLabel . Text = "Seeking..." ) ;
this . Invoke ( ( ) = > this . SavingProgressBar . Visible = true ) ;
for ( ; ; )
{
2016-10-29 13:57:40 +00:00
if ( _seekBackgroundWorker . CancellationPending | | ! this . IsHandleCreated )
2015-12-12 20:59:55 +00:00
{
e . Cancel = true ;
break ;
}
2016-01-27 12:44:42 +00:00
2016-12-04 18:30:51 +00:00
int diff = Emulator . Frame - _seekStartFrame . Value ;
2016-08-29 16:38:36 +00:00
int unit = Mainform . PauseOnFrame . Value - _seekStartFrame . Value ;
2016-01-27 12:44:42 +00:00
double progress = 0 ;
if ( diff ! = 0 & & unit ! = 0 )
progress = ( double ) 100d / unit * diff ;
2015-12-26 10:16:14 +00:00
if ( progress < 0 )
progress = 0 ;
2016-01-27 12:44:42 +00:00
2015-12-12 20:59:55 +00:00
_seekBackgroundWorker . ReportProgress ( ( int ) progress ) ;
System . Threading . Thread . Sleep ( 1 ) ;
}
} ;
_seekBackgroundWorker . ProgressChanged + = ( s , e ) = >
{
2016-01-27 12:44:42 +00:00
this . Invoke ( ( ) = > this . SavingProgressBar . Value = e . ProgressPercentage ) ;
2015-12-12 20:59:55 +00:00
} ;
_seekBackgroundWorker . RunWorkerCompleted + = ( s , e ) = >
{
this . Invoke ( ( ) = > this . SavingProgressBar . Visible = false ) ;
this . Invoke ( ( ) = > this . MessageStatusLabel . Text = "" ) ;
InitializeSeekWorker ( ) ; // Required, or it will error when trying to report progress again.
} ;
}
2015-03-20 16:53:42 +00:00
private bool _initialized = false ;
2015-03-16 20:42:14 +00:00
private void Tastudio_Load ( object sender , EventArgs e )
2014-10-17 17:40:11 +00:00
{
2015-03-16 20:42:14 +00:00
if ( ! InitializeOnLoad ( ) )
{
Close ( ) ;
2015-09-05 21:05:14 +00:00
DialogResult = DialogResult . Cancel ;
2015-03-16 20:42:14 +00:00
return ;
}
2016-12-04 15:20:22 +00:00
// 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 ( ) ;
2015-03-16 20:42:14 +00:00
SetColumnsFromCurrentStickies ( ) ;
if ( VersionInfo . DeveloperBuild )
{
RightClickMenu . Items . AddRange ( TasView . GenerateContextMenuItems ( ) . ToArray ( ) ) ;
RightClickMenu . Items
. OfType < ToolStripMenuItem > ( )
. First ( t = > t . Name = = "RotateMenuItem" )
. Click + = ( o , ov ) = >
{
CurrentTasMovie . FlagChanges ( ) ;
} ;
}
2015-07-25 08:20:16 +00:00
TasView . InputPaintingMode = Settings . DrawInput ;
TasView . ScrollSpeed = Settings . ScrollSpeed ;
2015-07-25 08:33:23 +00:00
TasView . AlwaysScroll = Settings . FollowCursorAlwaysScroll ;
2015-11-30 20:44:31 +00:00
TasView . ScrollMethod = Settings . FollowCursorScrollMethod ;
2016-01-27 13:18:20 +00:00
TasView . SeekingCutoffInterval = Settings . SeekingCutoffInterval ;
2015-11-30 20:44:31 +00:00
BookMarkControl . HoverInterval = Settings . BranchCellHoverInterval ;
2015-08-30 16:45:14 +00:00
2016-06-10 13:05:12 +00:00
_autosaveTimer . Tick + = AutosaveTimerEventProcessor ;
if ( Settings . AutosaveInterval > 0 )
{
_autosaveTimer . Interval = ( int ) Settings . AutosaveInterval ;
_autosaveTimer . Start ( ) ;
}
2015-07-25 08:20:16 +00:00
2015-07-26 00:19:47 +00:00
// 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 ;
}
////////////////
2015-03-16 20:42:14 +00:00
RefreshDialog ( ) ;
2015-03-20 16:53:42 +00:00
_initialized = true ;
2014-10-17 17:40:11 +00:00
}
2015-03-16 20:42:14 +00:00
private bool InitializeOnLoad ( )
2014-07-08 15:15:35 +00:00
{
2015-03-16 20:42:14 +00:00
// Start Scenario 1: A regular movie is active
if ( Global . MovieSession . Movie . IsActive & & ! ( Global . MovieSession . Movie is TasMovie ) )
{
var result = MessageBox . Show ( "In order to use Tastudio, a new project must be created from the current movie\nThe current movie will be saved and closed, and a new project file will be created\nProceed?" , "Convert movie" , MessageBoxButtons . OKCancel , MessageBoxIcon . Question ) ;
if ( result = = DialogResult . OK )
{
ConvertCurrentMovieToTasproj ( ) ;
StartNewMovieWrapper ( false ) ;
}
else
{
return false ;
}
}
// Start Scenario 2: A tasproj is already active
else if ( Global . MovieSession . Movie . IsActive & & Global . MovieSession . Movie is TasMovie )
{
// Nothing to do
}
// Start Scenario 3: No movie, but user wants to autload their last project
else if ( Settings . RecentTas . AutoLoad & & ! string . IsNullOrEmpty ( Settings . RecentTas . MostRecent ) )
{
2015-03-22 16:55:34 +00:00
bool result = LoadFile ( new FileInfo ( Settings . RecentTas . MostRecent ) ) ;
2015-03-16 20:42:14 +00:00
if ( ! result )
{
TasView . AllColumns . Clear ( ) ;
2015-03-22 16:55:34 +00:00
StartNewTasMovie ( ) ;
2015-03-16 20:42:14 +00:00
}
}
// Start Scenario 4: No movie, default behavior of engaging tastudio with a new default project
else
{
2015-03-22 16:55:34 +00:00
StartNewTasMovie ( ) ;
2015-03-16 20:42:14 +00:00
}
EngageTastudio ( ) ;
return true ;
}
2015-12-07 17:04:30 +00:00
private void SetTasMovieCallbacks ( TasMovie movie = null )
2015-03-16 20:42:14 +00:00
{
2015-12-07 17:04:30 +00:00
if ( movie = = null )
movie = CurrentTasMovie ;
movie . ClientSettingsForSave = ClientSettingsForSave ;
movie . GetClientSettingsOnLoad = GetClientSettingsOnLoad ;
2015-03-16 20:42:14 +00:00
}
2015-07-12 16:45:30 +00:00
2015-03-16 20:42:14 +00:00
private string ClientSettingsForSave ( )
{
return TasView . UserSettingsSerialized ( ) ;
}
2015-07-12 16:45:30 +00:00
2015-03-16 20:42:14 +00:00
private void GetClientSettingsOnLoad ( string settingsJson )
{
TasView . LoadSettingsSerialized ( settingsJson ) ;
}
private void SetUpColumns ( )
{
TasView . AllColumns . Clear ( ) ;
2015-07-13 17:37:12 +00:00
AddColumn ( CursorColumnName , string . Empty , 18 ) ;
2015-03-16 20:42:14 +00:00
AddColumn ( FrameColumnName , "Frame#" , 68 ) ;
var columnNames = GenerateColumnNames ( ) ;
2016-11-19 16:31:04 +00:00
InputRoll . RollColumn . InputType type ;
int digits = 1 ;
2015-03-16 20:42:14 +00:00
foreach ( var kvp in columnNames )
{
2016-11-19 16:31:04 +00:00
if ( Global . MovieSession . MovieControllerAdapter . Type . FloatControls . Contains ( kvp . Key ) )
{
Emulation . Common . ControllerDefinition . FloatRange range = Global . MovieSession . MovieControllerAdapter . Type . FloatRanges
[Global.MovieSession.MovieControllerAdapter.Type.FloatControls.IndexOf(kvp.Key)] ;
type = InputRoll . RollColumn . InputType . Float ;
digits = Math . Max ( kvp . Value . Length , range . MaxDigits ( ) ) ;
}
else
{
type = InputRoll . RollColumn . InputType . Boolean ;
digits = kvp . Value . Length ;
}
AddColumn ( kvp . Key , kvp . Value , ( digits * 6 ) + 14 , type ) ;
2015-03-16 20:42:14 +00:00
}
2015-09-02 21:53:02 +00:00
var columnsToHide = TasView . AllColumns
2016-04-23 18:42:02 +00:00
. Where ( c = >
// todo: make a proper user editable list?
c . Name = = "Power" | |
c . Name = = "Reset" | |
c . Name . StartsWith ( "Tilt" ) | |
2016-07-26 17:46:15 +00:00
c . Name = = "Light Sensor" | |
c . Name = = "Open" | |
c . Name = = "Close" | |
c . Name = = "Disc Select"
2016-04-23 18:42:02 +00:00
) ;
2015-09-02 21:53:02 +00:00
foreach ( var column in columnsToHide )
{
column . Visible = false ;
}
2016-09-25 22:55:34 +00:00
TasView . AllColumns . ColumnsChanged ( ) ;
2015-09-02 21:53:02 +00:00
2015-03-16 20:42:14 +00:00
// Patterns
int bStart = 0 ;
int fStart = 0 ;
if ( BoolPatterns = = null )
{
BoolPatterns = new AutoPatternBool [ controllerType . BoolButtons . Count + 2 ] ;
FloatPatterns = new AutoPatternFloat [ controllerType . FloatControls . Count + 2 ] ;
}
else
{
bStart = BoolPatterns . Length - 2 ;
fStart = FloatPatterns . Length - 2 ;
Array . Resize ( ref BoolPatterns , controllerType . BoolButtons . Count + 2 ) ;
Array . Resize ( ref FloatPatterns , controllerType . FloatControls . Count + 2 ) ;
}
for ( int i = bStart ; i < BoolPatterns . Length - 2 ; i + + )
BoolPatterns [ i ] = new AutoPatternBool ( 1 , 1 ) ;
2016-11-14 19:39:58 +00:00
2015-03-16 20:42:14 +00:00
BoolPatterns [ BoolPatterns . Length - 2 ] = new AutoPatternBool ( 1 , 0 ) ;
BoolPatterns [ BoolPatterns . Length - 1 ] = new AutoPatternBool (
Global . Config . AutofireOn , Global . Config . AutofireOff ) ;
for ( int i = fStart ; i < FloatPatterns . Length - 2 ; i + + )
FloatPatterns [ i ] = new AutoPatternFloat ( new float [ ] { 1f } ) ;
FloatPatterns [ FloatPatterns . Length - 2 ] = new AutoPatternFloat ( new float [ ] { 1f } ) ;
FloatPatterns [ FloatPatterns . Length - 1 ] = new AutoPatternFloat (
1f , Global . Config . AutofireOn , 0f , Global . Config . AutofireOff ) ;
SetUpToolStripColumns ( ) ;
}
2016-11-19 16:31:04 +00:00
public void AddColumn ( string columnName , string columnText , int columnWidth , InputRoll . RollColumn . InputType columnType = InputRoll . RollColumn . InputType . Boolean )
2015-03-16 20:42:14 +00:00
{
if ( TasView . AllColumns [ columnName ] = = null )
{
var column = new InputRoll . RollColumn
{
Name = columnName ,
Text = columnText ,
2016-11-19 16:31:04 +00:00
Width = columnWidth ,
Type = columnType
2015-03-16 20:42:14 +00:00
} ;
TasView . AllColumns . Add ( column ) ;
}
2014-07-08 15:15:35 +00:00
}
private void EngageTastudio ( )
2013-12-10 16:37:41 +00:00
{
2016-08-29 16:38:36 +00:00
Mainform . PauseOnFrame = null ;
2013-12-10 16:37:41 +00:00
GlobalWin . OSD . AddMessage ( "TAStudio engaged" ) ;
2014-10-14 18:09:30 +00:00
SetTasMovieCallbacks ( ) ;
2014-09-16 23:26:17 +00:00
SetTextProperty ( ) ;
2016-08-29 16:38:36 +00:00
Mainform . PauseEmulator ( ) ;
Mainform . RelinquishControl ( this ) ;
2014-07-14 00:35:33 +00:00
_originalEndAction = Global . Config . MovieEndAction ;
2016-08-29 16:38:36 +00:00
Mainform . ClearRewindData ( ) ;
2014-07-14 00:35:33 +00:00
Global . Config . MovieEndAction = MovieEndAction . Record ;
2016-08-29 16:38:36 +00:00
Mainform . SetMainformMovieInfo ( ) ;
2015-03-19 19:55:38 +00:00
Global . MovieSession . ReadOnly = true ;
2014-07-08 15:15:35 +00:00
}
2014-07-08 13:46:59 +00:00
2015-03-16 20:42:14 +00:00
#endregion
2015-03-22 16:55:34 +00:00
#region "Loading"
2015-03-16 20:42:14 +00:00
private void ConvertCurrentMovieToTasproj ( )
2014-07-08 15:15:35 +00:00
{
2015-03-16 20:42:14 +00:00
Global . MovieSession . Movie . Save ( ) ;
Global . MovieSession . Movie = Global . MovieSession . Movie . ToTasMovie ( ) ;
Global . MovieSession . Movie . Save ( ) ;
Global . MovieSession . Movie . SwitchToRecord ( ) ;
Settings . RecentTas . Add ( Global . MovieSession . Movie . Filename ) ;
2014-07-08 15:15:35 +00:00
}
2014-07-08 13:46:59 +00:00
2015-12-08 20:38:00 +00:00
private bool LoadFile ( FileInfo file , bool startsFromSavestate = false )
2014-07-08 15:15:35 +00:00
{
2015-03-22 16:55:34 +00:00
if ( ! file . Exists )
{
Settings . RecentTas . HandleLoadError ( file . FullName ) ;
return false ;
}
2015-12-08 20:38:00 +00:00
TasMovie newMovie = new TasMovie ( startsFromSavestate , _saveBackgroundWorker ) ;
2015-08-17 14:13:44 +00:00
newMovie . TasStateManager . InvalidateCallback = GreenzoneInvalidated ;
newMovie . Filename = file . FullName ;
2015-06-27 11:48:05 +00:00
2015-08-17 14:13:44 +00:00
if ( ! HandleMovieLoadStuff ( newMovie ) )
2015-03-22 16:55:34 +00:00
return false ;
2015-11-22 14:17:01 +00:00
2016-02-05 20:35:07 +00:00
Settings . RecentTas . Add ( newMovie . Filename ) ; // only add if it did load
2015-12-08 20:38:00 +00:00
if ( startsFromSavestate )
GoToFrame ( 0 ) ;
else
GoToFrame ( CurrentTasMovie . Session . CurrentFrame ) ;
2016-02-05 20:35:07 +00:00
2016-11-14 21:21:26 +00:00
if ( TasView . AllColumns . Count = = 0 | | file . Extension ! = "." + TasMovie . Extension )
2016-11-14 19:39:58 +00:00
SetUpColumns ( ) ;
else
SetUpToolStripColumns ( ) ;
2015-12-09 16:57:45 +00:00
CurrentTasMovie . PropertyChanged + = new PropertyChangedEventHandler ( this . TasMovie_OnPropertyChanged ) ;
2015-11-22 14:17:01 +00:00
CurrentTasMovie . CurrentBranch = CurrentTasMovie . Session . CurrentBranch ;
2015-10-05 16:08:21 +00:00
// clear all selections
TasView . DeselectAll ( ) ;
BookMarkControl . Restart ( ) ;
MarkerControl . Restart ( ) ;
2015-03-22 16:55:34 +00:00
RefreshDialog ( ) ;
return true ;
2014-07-08 15:15:35 +00:00
}
2014-07-10 19:51:36 +00:00
private void StartNewTasMovie ( )
2013-12-10 16:37:41 +00:00
{
2014-08-19 19:24:17 +00:00
if ( AskSaveChanges ( ) )
2013-12-10 16:37:41 +00:00
{
2015-03-22 16:55:34 +00:00
Global . MovieSession . Movie = new TasMovie ( false , _saveBackgroundWorker ) ;
2015-08-05 21:36:44 +00:00
var stateManager = ( Global . MovieSession . Movie as TasMovie ) . TasStateManager ;
stateManager . MountWriteAccess ( ) ;
stateManager . InvalidateCallback = GreenzoneInvalidated ;
2015-03-22 16:55:34 +00:00
CurrentTasMovie . PropertyChanged + = new PropertyChangedEventHandler ( this . TasMovie_OnPropertyChanged ) ;
CurrentTasMovie . Filename = DefaultTasProjName ( ) ; // TODO don't do this, take over any mainform actions that can crash without a filename
CurrentTasMovie . PopulateWithDefaultHeaderValues ( ) ;
2015-03-23 20:15:35 +00:00
SetTasMovieCallbacks ( ) ;
2015-03-22 16:55:34 +00:00
CurrentTasMovie . ClearChanges ( ) ; // Don't ask to save changes here.
HandleMovieLoadStuff ( ) ;
2015-07-14 03:05:50 +00:00
CurrentTasMovie . TasStateManager . Capture ( ) ; // Capture frame 0 always.
2015-09-13 08:44:15 +00:00
// clear all selections
TasView . DeselectAll ( ) ;
2015-09-06 18:56:12 +00:00
BookMarkControl . Restart ( ) ;
MarkerControl . Restart ( ) ;
2016-11-18 21:48:54 +00:00
SetUpColumns ( ) ;
2014-07-09 22:44:20 +00:00
RefreshDialog ( ) ;
2013-12-10 16:37:41 +00:00
}
}
2015-03-22 16:55:34 +00:00
private bool HandleMovieLoadStuff ( TasMovie movie = null )
2015-03-16 20:42:14 +00:00
{
2015-08-17 14:13:44 +00:00
bool result ;
2015-12-07 17:04:30 +00:00
WantsToControlStopMovie = false ;
2015-08-17 14:13:44 +00:00
if ( movie = = null )
{
movie = CurrentTasMovie ;
result = StartNewMovieWrapper ( movie . InputLogLength = = 0 , movie ) ;
}
else
2016-02-05 20:35:07 +00:00
{
if ( movie . Filename . EndsWith ( TasMovie . Extension ) )
{
}
else if ( movie . Filename . EndsWith ( ".bkm" ) | | movie . Filename . EndsWith ( ".bk2" ) ) // was loaded using "All Files" filter. todo: proper extention iteration
{
var result1 = MessageBox . Show ( "This is a regular movie, a new project must be created from it, in order to use in TAStudio\nProceed?" , "Convert movie" , MessageBoxButtons . OKCancel , MessageBoxIcon . Question ) ;
if ( result1 = = DialogResult . OK )
{
ConvertCurrentMovieToTasproj ( ) ;
}
else
{
return false ;
}
}
else
{
MessageBox . Show ( "This is not a BizHawk movie!" , "Movie load error" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
return false ;
}
2015-08-17 14:13:44 +00:00
result = StartNewMovieWrapper ( false , movie ) ;
2016-02-05 20:35:07 +00:00
}
2015-12-07 17:04:30 +00:00
2015-03-22 16:55:34 +00:00
if ( ! result )
return false ;
2015-12-07 17:04:30 +00:00
2015-03-22 16:55:34 +00:00
WantsToControlStopMovie = true ;
2015-03-16 20:42:14 +00:00
2015-03-23 20:15:35 +00:00
CurrentTasMovie . ChangeLog . ClearLog ( ) ;
2015-03-22 16:55:34 +00:00
CurrentTasMovie . ClearChanges ( ) ;
2015-03-16 20:42:14 +00:00
2015-03-22 16:55:34 +00:00
SetTextProperty ( ) ;
MessageStatusLabel . Text = Path . GetFileName ( CurrentTasMovie . Filename ) + " loaded." ;
2015-03-16 20:42:14 +00:00
2015-03-22 16:55:34 +00:00
return true ;
}
2016-08-03 19:29:27 +00:00
2015-03-22 16:55:34 +00:00
private bool StartNewMovieWrapper ( bool record , IMovie movie = null )
{
_initializing = true ;
if ( movie = = null )
movie = CurrentTasMovie ;
2015-12-07 17:04:30 +00:00
SetTasMovieCallbacks ( movie as TasMovie ) ;
2016-08-29 16:38:36 +00:00
bool result = Mainform . StartNewMovie ( movie , record ) ;
2016-08-06 19:28:25 +00:00
TastudioPlayMode ( ) ;
2015-03-22 16:55:34 +00:00
_initializing = false ;
2015-03-16 20:42:14 +00:00
2015-03-22 16:55:34 +00:00
return result ;
2015-03-16 20:42:14 +00:00
}
2014-10-18 15:50:12 +00:00
private void DummyLoadProject ( string path )
{
2015-03-22 16:55:34 +00:00
if ( AskSaveChanges ( ) )
LoadFile ( new FileInfo ( path ) ) ;
2014-10-18 15:50:12 +00:00
}
2016-08-03 19:29:27 +00:00
2015-03-11 16:14:02 +00:00
private void DummyLoadMacro ( string path )
{
2015-07-26 03:42:50 +00:00
if ( ! TasView . AnyRowsSelected )
2015-03-11 16:14:02 +00:00
return ;
MovieZone loadZone = new MovieZone ( path ) ;
if ( loadZone ! = null )
{
loadZone . Start = TasView . FirstSelectedIndex . Value ;
loadZone . PlaceZone ( CurrentTasMovie ) ;
}
}
2015-03-16 20:42:14 +00:00
private void SetColumnsFromCurrentStickies ( )
2014-10-14 18:09:30 +00:00
{
2015-03-16 20:42:14 +00:00
foreach ( var column in TasView . VisibleColumns )
{
if ( Global . StickyXORAdapter . IsSticky ( column . Name ) )
{
column . Emphasis = true ;
}
}
2014-10-14 18:09:30 +00:00
}
2015-03-16 20:42:14 +00:00
#endregion
2016-08-03 19:29:27 +00:00
private void TastudioPlayMode ( )
{
2016-08-06 19:28:25 +00:00
TasPlaybackBox . RecordingMode = false ;
2016-08-03 19:29:27 +00:00
}
private void TastudioRecordMode ( )
{
2016-08-06 19:28:25 +00:00
TasPlaybackBox . RecordingMode = true ;
2016-08-03 19:29:27 +00:00
}
private void TastudioStopMovie ( )
2015-03-16 20:42:14 +00:00
{
Global . MovieSession . StopMovie ( false ) ;
2016-08-29 16:38:36 +00:00
Mainform . SetMainformMovieInfo ( ) ;
2015-03-16 20:42:14 +00:00
}
private void DisengageTastudio ( )
{
2016-08-29 16:38:36 +00:00
Mainform . PauseOnFrame = null ;
2015-03-16 20:42:14 +00:00
GlobalWin . OSD . AddMessage ( "TAStudio disengaged" ) ;
Global . MovieSession . Movie = MovieService . DefaultInstance ;
2016-08-29 16:38:36 +00:00
Mainform . TakeBackControl ( ) ;
2015-03-16 20:42:14 +00:00
Global . Config . MovieEndAction = _originalEndAction ;
2016-08-29 16:38:36 +00:00
Mainform . SetMainformMovieInfo ( ) ;
2015-03-16 20:42:14 +00:00
// Do not keep TAStudio's disk save states.
2015-08-14 02:51:51 +00:00
//if (Directory.Exists(statesPath)) Directory.Delete(statesPath, true);
//TODO - do we need to dispose something here instead?
2015-03-16 20:42:14 +00:00
}
/// <summary>
/// Used when starting a new project
/// </summary>
private static string DefaultTasProjName ( )
{
return Path . Combine (
PathManager . MakeAbsolutePath ( Global . Config . PathEntries . MoviesPathFragment , null ) ,
TasMovie . DefaultProjectName + "." + TasMovie . Extension ) ;
}
/// <summary>
/// Used for things like SaveFile dialogs to suggest a name to the user
/// </summary>
/// <returns></returns>
private static string SuggestedTasProjName ( )
{
return Path . Combine (
PathManager . MakeAbsolutePath ( Global . Config . PathEntries . MoviesPathFragment , null ) ,
PathManager . FilesystemSafeName ( Global . Game ) + "." + TasMovie . Extension ) ;
2014-10-14 18:09:30 +00:00
}
2014-09-16 23:26:17 +00:00
private void SetTextProperty ( )
2014-09-16 23:25:08 +00:00
{
var text = "TAStudio" ;
2014-10-20 19:04:59 +00:00
if ( CurrentTasMovie ! = null )
2014-09-16 23:25:08 +00:00
{
2014-10-20 19:04:59 +00:00
text + = " - " + CurrentTasMovie . Name + ( CurrentTasMovie . Changes ? "*" : "" ) ;
2014-09-16 23:25:08 +00:00
}
2015-01-06 16:35:22 +00:00
if ( this . InvokeRequired )
{
this . Invoke ( ( ) = > Text = text ) ;
}
else
{
Text = text ;
}
2014-09-16 23:25:08 +00:00
}
2015-07-26 19:54:11 +00:00
public void RefreshDialog ( bool refreshTasView = true )
2014-07-08 15:15:35 +00:00
{
2015-07-26 19:54:11 +00:00
if ( refreshTasView )
RefreshTasView ( ) ;
2015-03-03 06:56:45 +00:00
if ( MarkerControl ! = null )
MarkerControl . UpdateValues ( ) ;
2015-03-04 19:03:00 +00:00
2015-10-04 10:39:14 +00:00
if ( BookMarkControl ! = null )
BookMarkControl . UpdateValues ( ) ;
2016-04-24 10:48:49 +00:00
if ( _undoForm ! = null & & ! _undoForm . IsDisposed )
_undoForm . UpdateValues ( ) ;
2015-03-03 06:56:45 +00:00
}
private void RefreshTasView ( )
{
2014-10-20 19:04:59 +00:00
CurrentTasMovie . UseInputCache = true ;
2015-03-16 20:42:14 +00:00
if ( TasView . RowCount ! = CurrentTasMovie . InputLogLength + 1 )
TasView . RowCount = CurrentTasMovie . InputLogLength + 1 ;
2014-08-23 15:19:48 +00:00
TasView . Refresh ( ) ;
2014-08-23 16:00:56 +00:00
2015-03-03 18:22:54 +00:00
CurrentTasMovie . FlushInputCache ( ) ;
2014-10-20 19:04:59 +00:00
CurrentTasMovie . UseInputCache = false ;
2014-08-29 02:58:52 +00:00
2016-12-04 18:30:51 +00:00
lastRefresh = Emulator . Frame ;
2014-07-08 15:15:35 +00:00
}
2014-10-17 20:10:21 +00:00
private void DoAutoRestore ( )
2014-09-27 14:37:02 +00:00
{
2016-11-21 20:59:12 +00:00
if ( Settings . AutoRestoreLastPosition & & LastPositionFrame ! = - 1 )
2014-09-27 14:37:02 +00:00
{
2016-11-21 20:59:12 +00:00
if ( LastPositionFrame > Emulator . Frame ) // Don't unpause if we are already on the desired frame, else runaway seek
2014-09-22 23:24:34 +00:00
{
2016-11-21 20:59:12 +00:00
StartSeeking ( LastPositionFrame ) ;
2014-07-16 23:04:56 +00:00
}
2014-07-13 15:26:50 +00:00
}
2015-07-15 19:26:56 +00:00
else
{
tastudio: fix editing while unpaused + left button held scenario.
now it replicates taseditor:
- editing input while unpaused, if autorestore is off, resumes emulation and ignores seek frame. if you keep holding the LMB, and follow cursor is on, it will keep scrolling, drawing and emulating
- editing input while unpaused, if autoresotre is on, fires autorestore and then just pauses on the seek frame
what's different from taseditor:
- with autorestore and follow cursor on, if you hold the button, and seek frame is below the view, it will keep scrolling down, drawing new input and emulating. taseditor does *not* follow cursor while seeking.
this all doesn't necessarily make sense, but we need people to figure out what is best for work.
2016-07-11 18:38:58 +00:00
if ( _autoRestorePaused . HasValue & & ! _autoRestorePaused . Value )
{
// this happens when we're holding the left button while unpaused - view scrolls down, new input gets drawn, seek pauses
2016-08-29 16:38:36 +00:00
Mainform . UnpauseEmulator ( ) ;
tastudio: fix editing while unpaused + left button held scenario.
now it replicates taseditor:
- editing input while unpaused, if autorestore is off, resumes emulation and ignores seek frame. if you keep holding the LMB, and follow cursor is on, it will keep scrolling, drawing and emulating
- editing input while unpaused, if autoresotre is on, fires autorestore and then just pauses on the seek frame
what's different from taseditor:
- with autorestore and follow cursor on, if you hold the button, and seek frame is below the view, it will keep scrolling down, drawing new input and emulating. taseditor does *not* follow cursor while seeking.
this all doesn't necessarily make sense, but we need people to figure out what is best for work.
2016-07-11 18:38:58 +00:00
}
2015-07-15 19:26:56 +00:00
_autoRestorePaused = null ;
}
2016-11-21 20:59:12 +00:00
//_autoRestoreFrame = null;
2014-07-13 15:26:50 +00:00
}
2014-08-31 16:51:19 +00:00
private void StartAtNearestFrameAndEmulate ( int frame )
{
2015-07-13 19:02:21 +00:00
if ( frame = = Emulator . Frame )
return ;
2016-08-03 19:29:27 +00:00
_wasRecording = CurrentTasMovie . IsRecording | | _wasRecording ;
TastudioPlayMode ( ) ;
2014-10-26 23:26:43 +00:00
KeyValuePair < int , byte [ ] > closestState = CurrentTasMovie . TasStateManager . GetStateClosestToFrame ( frame ) ;
2015-07-13 19:02:21 +00:00
if ( closestState . Value ! = null & & ( frame < Emulator . Frame | | closestState . Key > Emulator . Frame ) )
2014-08-31 16:51:19 +00:00
{
2014-10-26 23:37:42 +00:00
LoadState ( closestState ) ;
2014-08-31 16:51:19 +00:00
}
2015-07-14 03:05:50 +00:00
// frame == Emualtor.Frame when frame == 0
if ( frame > Emulator . Frame )
2015-07-13 19:02:21 +00:00
{
2016-08-29 16:38:36 +00:00
if ( Mainform . EmulatorPaused | | Mainform . IsSeeking ) // make seek frame keep up with emulation on fast scrolls
2015-07-14 03:05:50 +00:00
{
2015-12-12 20:59:55 +00:00
StartSeeking ( frame ) ;
2015-07-14 03:05:50 +00:00
}
2015-07-13 19:02:21 +00:00
}
2014-08-31 16:51:19 +00:00
}
2015-07-19 14:37:53 +00:00
public void LoadState ( KeyValuePair < int , byte [ ] > state )
2014-09-27 15:19:07 +00:00
{
2014-12-14 01:20:19 +00:00
StatableEmulator . LoadStateBinary ( new BinaryReader ( new MemoryStream ( state . Value . ToArray ( ) ) ) ) ;
2014-10-26 23:37:42 +00:00
if ( state . Key = = 0 & & CurrentTasMovie . StartsFromSavestate )
{
2014-12-14 01:20:19 +00:00
Emulator . ResetCounters ( ) ;
2014-10-26 23:37:42 +00:00
}
2014-09-27 15:19:07 +00:00
_hackyDontUpdate = true ;
GlobalWin . Tools . UpdateBefore ( ) ;
GlobalWin . Tools . UpdateAfter ( ) ;
_hackyDontUpdate = false ;
}
2015-12-07 17:04:30 +00:00
public void AddBranchExternal ( )
{
BookMarkControl . AddBranchExternal ( ) ;
}
public void RemoveBranchExtrenal ( )
{
BookMarkControl . RemoveBranchExtrenal ( ) ;
}
2014-10-11 17:43:24 +00:00
private void UpdateOtherTools ( ) // a hack probably, surely there is a better way to do this
{
_hackyDontUpdate = true ;
GlobalWin . Tools . UpdateBefore ( ) ;
GlobalWin . Tools . UpdateAfter ( ) ;
_hackyDontUpdate = false ;
2013-12-15 04:45:46 +00:00
}
2014-07-17 19:00:28 +00:00
public void TogglePause ( )
{
2016-08-29 16:38:36 +00:00
Mainform . TogglePause ( ) ;
2014-07-17 19:00:28 +00:00
}
2013-12-19 03:45:11 +00:00
private void SetSplicer ( )
{
// TODO: columns selected
// TODO: clipboard
2014-08-30 18:42:14 +00:00
var list = TasView . SelectedRows ;
2014-08-23 18:02:02 +00:00
string message = "Selected: " ;
2013-12-19 03:45:11 +00:00
2014-10-13 18:28:29 +00:00
if ( list . Any ( ) )
2013-12-19 03:45:11 +00:00
{
2014-10-13 18:28:29 +00:00
message + = list . Count ( ) + " rows 0 col, Clipboard: " ;
2013-12-19 03:45:11 +00:00
}
else
{
2014-10-13 18:28:29 +00:00
message + = list . Count ( ) + " none, Clipboard: " ;
2013-12-19 03:45:11 +00:00
}
2015-02-24 06:47:32 +00:00
message + = _tasClipboard . Any ( ) ? _tasClipboard . Count + " rows 0 col" : "empty" ;
2013-12-19 03:45:11 +00:00
SplicerStatusLabel . Text = message ;
}
2014-07-11 02:31:43 +00:00
private void UpdateChangesIndicator ( )
{
// TODO
}
2014-10-21 01:31:41 +00:00
private void DoTriggeredAutoRestoreIfNeeded ( )
{
if ( _triggerAutoRestore )
{
DoAutoRestore ( ) ;
_triggerAutoRestore = false ;
2015-07-15 19:26:56 +00:00
_autoRestorePaused = null ;
2014-10-21 01:31:41 +00:00
}
}
2014-10-17 17:40:11 +00:00
#region Dialog Events
2014-08-21 22:53:03 +00:00
private void Tastudio_Closing ( object sender , FormClosingEventArgs e )
{
2015-03-20 16:53:42 +00:00
if ( ! _initialized )
return ;
2015-01-06 16:35:22 +00:00
_exiting = true ;
2016-08-04 15:53:01 +00:00
2014-08-21 22:53:03 +00:00
if ( AskSaveChanges ( ) )
{
2014-10-18 20:40:20 +00:00
WantsToControlStopMovie = false ;
2016-08-04 15:53:01 +00:00
TastudioStopMovie ( ) ;
2014-08-21 22:53:03 +00:00
DisengageTastudio ( ) ;
}
else
{
e . Cancel = true ;
2015-01-06 16:35:22 +00:00
_exiting = false ;
2014-08-21 22:53:03 +00:00
}
2015-03-04 19:03:00 +00:00
2016-04-24 10:48:49 +00:00
if ( _undoForm ! = null )
_undoForm . Close ( ) ;
2014-08-21 22:53:03 +00:00
}
2014-08-19 19:24:17 +00:00
2014-10-17 17:40:11 +00:00
/// <summary>
/// This method is called everytime the Changes property is toggled on a TasMovie instance.
/// </summary>
2014-08-23 18:02:02 +00:00
private void TasMovie_OnPropertyChanged ( object sender , PropertyChangedEventArgs e )
{
2014-09-16 23:26:17 +00:00
SetTextProperty ( ) ;
2014-08-23 18:02:02 +00:00
}
2016-01-31 01:24:30 +00:00
private void LuaConsole_DragEnter ( object sender , DragEventArgs e )
2014-10-21 13:12:12 +00:00
{
e . Effect = e . Data . GetDataPresent ( DataFormats . FileDrop ) ? DragDropEffects . Copy : DragDropEffects . None ;
}
private void TAStudio_DragDrop ( object sender , DragEventArgs e )
{
2015-03-23 21:16:13 +00:00
if ( ! AskSaveChanges ( ) )
return ;
2014-10-21 13:12:12 +00:00
var filePaths = ( string [ ] ) e . Data . GetData ( DataFormats . FileDrop ) ;
if ( Path . GetExtension ( filePaths [ 0 ] ) = = "." + TasMovie . Extension )
{
2015-03-22 16:55:34 +00:00
FileInfo file = new FileInfo ( filePaths [ 0 ] ) ;
2014-11-22 15:19:32 +00:00
if ( file . Exists )
2014-10-21 13:12:12 +00:00
{
2015-03-22 16:55:34 +00:00
LoadFile ( file ) ;
2014-10-21 13:12:12 +00:00
}
}
}
2014-10-22 22:43:42 +00:00
private void TAStudio_MouseLeave ( object sender , EventArgs e )
{
DoTriggeredAutoRestoreIfNeeded ( ) ;
}
2014-10-23 00:47:30 +00:00
protected override bool ProcessCmdKey ( ref Message msg , Keys keyData )
{
if ( keyData = = Keys . Tab | |
keyData = = ( Keys . Shift | Keys . Tab ) | |
keyData = = Keys . Space )
{
return true ;
}
2015-02-24 06:47:32 +00:00
2014-10-23 00:47:30 +00:00
return base . ProcessCmdKey ( ref msg , keyData ) ;
}
2014-02-01 15:44:51 +00:00
#endregion
2014-10-25 13:41:23 +00:00
2015-03-19 19:55:38 +00:00
private bool AutoAdjustInput ( )
2015-03-01 05:47:32 +00:00
{
2015-03-10 17:11:29 +00:00
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.
2016-12-04 18:30:51 +00:00
CurrentTasMovie . ChangeLog . AddInputBind ( Emulator . Frame - 1 , true , "Bind Input; Delete " + ( Emulator . Frame - 1 ) ) ;
2015-03-23 20:15:35 +00:00
bool wasRecording = CurrentTasMovie . ChangeLog . IsRecording ;
CurrentTasMovie . ChangeLog . IsRecording = false ;
2016-12-04 18:30:51 +00:00
CurrentTasMovie . RemoveFrame ( Emulator . Frame - 1 ) ;
CurrentTasMovie . RemoveLagHistory ( Emulator . Frame ) ; // Removes from WasLag
2015-03-23 20:15:35 +00:00
CurrentTasMovie . ChangeLog . IsRecording = wasRecording ;
2015-03-10 17:11:29 +00:00
GoToFrame ( Emulator . Frame - 1 ) ;
2015-03-19 19:55:38 +00:00
return true ;
2015-03-10 17:11:29 +00:00
}
else if ( ! lagLog . WasLagged . Value & & isLag )
{ // (it shouldn't need to rewind, since the inserted input wasn't polled)
2016-12-04 18:30:51 +00:00
CurrentTasMovie . ChangeLog . AddInputBind ( Emulator . Frame - 1 , false , "Bind Input; Insert " + ( Emulator . Frame - 1 ) ) ;
2015-03-23 20:15:35 +00:00
bool wasRecording = CurrentTasMovie . ChangeLog . IsRecording ;
CurrentTasMovie . ChangeLog . IsRecording = false ;
2016-12-04 18:30:51 +00:00
CurrentTasMovie . InsertInput ( Emulator . Frame - 1 , CurrentTasMovie . GetInputLogEntry ( Emulator . Frame - 2 ) ) ;
CurrentTasMovie . InsertLagHistory ( Emulator . Frame , true ) ;
2015-03-23 20:15:35 +00:00
CurrentTasMovie . ChangeLog . IsRecording = wasRecording ;
2015-03-19 19:55:38 +00:00
return true ;
2015-03-10 17:11:29 +00:00
}
}
2015-03-19 19:55:38 +00:00
return false ;
2015-03-01 05:47:32 +00:00
}
2015-03-10 17:11:29 +00:00
2015-03-14 16:38:07 +00:00
private void TAStudio_KeyDown ( object sender , KeyEventArgs e )
{
2016-06-13 12:43:28 +00:00
//if (e.KeyCode == Keys.F)
// TasPlaybackBox.FollowCursor ^= true;
2015-03-14 16:38:07 +00:00
}
2015-07-26 00:19:47 +00:00
private void MainVertialSplit_SplitterMoved ( object sender , SplitterEventArgs e )
{
Settings . MainVerticalSplitDistance = MainVertialSplit . SplitterDistance ;
}
private void BranchesMarkersSplit_SplitterMoved ( object sender , SplitterEventArgs e )
{
Settings . BranchMarkerSplitDistance = BranchesMarkersSplit . SplitterDistance ;
}
2015-07-27 23:25:15 +00:00
2015-07-29 00:03:03 +00:00
private void TasView_CellDropped ( object sender , InputRoll . CellEventArgs e )
{
if ( e . NewCell ! = null & & e . NewCell . RowIndex . HasValue & &
! CurrentTasMovie . Markers . IsMarker ( e . NewCell . RowIndex . Value ) )
{
var currentMarker = CurrentTasMovie . Markers . Single ( m = > m . Frame = = e . OldCell . RowIndex . Value ) ;
int newFrame = e . NewCell . RowIndex . Value ;
var newMarker = new TasMovieMarker ( newFrame , currentMarker . Message ) ;
CurrentTasMovie . Markers . Remove ( currentMarker ) ;
CurrentTasMovie . Markers . Add ( newMarker ) ;
RefreshDialog ( ) ;
}
}
2015-09-05 23:25:27 +00:00
private void NewFromSubMenu_DropDownOpened ( object sender , EventArgs e )
{
NewFromNowMenuItem . Enabled =
CurrentTasMovie . InputLogLength > 0
& & ! CurrentTasMovie . StartsFromSaveRam ;
NewFromCurrentSaveRamMenuItem . Enabled =
CurrentTasMovie . InputLogLength > 0
& & SaveRamEmulator ! = null ;
}
2015-12-05 17:32:56 +00:00
private void TASMenu_MenuActivate ( object sender , EventArgs e )
{
IsInMenuLoop = true ;
}
private void TASMenu_MenuDeactivate ( object sender , EventArgs e )
{
IsInMenuLoop = false ;
}
2016-01-31 03:17:31 +00:00
// Stupid designer
protected void DragEnterWrapper ( object sender , DragEventArgs e )
{
base . GenericDragEnter ( sender , e ) ;
}
2016-12-03 14:36:35 +00:00
private void TasPlaybackBox_Load ( object sender , EventArgs e )
{
}
2013-12-01 04:00:02 +00:00
}
}