| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- using Newtonsoft.Json;
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Text.RegularExpressions;
- using System.Threading.Tasks;
- using System.Windows.Forms;
-
- namespace Funscripta
- {
- public class FunScript
- {
- [JsonIgnore]
- public static int HistoryLimit { get; set; } = 100;
-
- public class HistoryEntry
- {
- public enum HistoryAction
- {
- Create, Update, Delete
- }
-
- public HistoryAction Action { get; set; }
- public long Timestamp { get; set; }
- public int? PositionBefore { get; set; }
- public int? PositionAfter { get; set; }
- }
-
- [JsonIgnore]
- public List<HistoryEntry> History { get; set; } = new List<HistoryEntry>();
- [JsonIgnore]
- public List<HistoryEntry> UndoHistory { get; set; } = new List<HistoryEntry>();
-
- [JsonProperty( "version" )]
- public string Version { get; set; } = "1.0";
- [JsonProperty( "actions" )]
- public LinkedList<Action> Actions { get; private set; } = new LinkedList<Action>();
- [JsonProperty( "inverted" )]
- public Boolean Inverted { get; set; } = false;
- [JsonProperty( "range" )]
- public int Range { get; set; } = 100;
-
- [JsonIgnore]
- public bool CanUndo => History.Count > 0;
- [JsonIgnore]
- public bool CanRedo => UndoHistory.Count > 0;
-
- internal FunScript()
- {
- AddAction( 0, 0 );
- }
-
- public Action Find( long timestamp )
- {
- var distance = long.MaxValue;
- Action _action = null;
- foreach( var action in Actions )
- {
- var dist = timestamp - action.Timestamp;
- if ( dist > -1 && dist < distance )
- {
- distance = dist;
- _action = action;
- }
- }
- if ( _action == null )
- {
- Actions.AddFirst( new Action( 0, 0 ) );
- return Find( 0 );
- }
- return _action;
- }
-
- public void AddAction( long timestamp, int position )
- {
- var a = Find( timestamp );
- if ( a.Timestamp == timestamp && a.Position != position )
- {
- HistoryAdd( HistoryEntry.HistoryAction.Update, a.Timestamp, a.Position, position );
- a.Position = position;
- }
- else if ( a.Position == position ) return;
- else
- {
- var _a = Actions.Find( a );
- Actions.AddAfter( _a, new Action( timestamp, position ) );
- HistoryAdd( HistoryEntry.HistoryAction.Create, timestamp, null, position );
- }
- }
-
- public void RemoveAction( long timestamp )
- {
- var a = Find( timestamp );
- if ( a.Timestamp != 0 )
- {
- Actions.Remove( Actions.Find( a ) );
- HistoryAdd( HistoryEntry.HistoryAction.Delete, a.Timestamp, a.Position, null );
- }
- }
-
- private void HistoryAdd( HistoryEntry.HistoryAction action, long timestamp, int? posBefore, int? posAfter )
- {
- History.Add( new HistoryEntry()
- {
- Action = action,
- Timestamp = timestamp,
- PositionBefore = posBefore,
- PositionAfter = posAfter
- }
- );
- if ( History.Count > HistoryLimit ) History.RemoveAt( 0 );
- UndoHistory.Clear();
- }
-
- private void UndoHistoryAdd( HistoryEntry historyEntry )
- {
- UndoHistory.Add( historyEntry );
- }
-
- public void Undo()
- {
- if ( !CanUndo ) return;
- var e = History.Last();
- History.Remove( e );
- switch( e.Action )
- {
- case HistoryEntry.HistoryAction.Create:
- Actions.Remove( Find( e.Timestamp ) );
- break;
- case HistoryEntry.HistoryAction.Update:
- Find( e.Timestamp ).Position = e.PositionBefore.Value;
- break;
- case HistoryEntry.HistoryAction.Delete:
- Actions.AddAfter( Actions.Find( Find( e.Timestamp ) ), new Action( e.Timestamp, e.PositionBefore.Value ) );
- break;
- }
- UndoHistoryAdd( e );
- }
-
- public void Redo()
- {
- if ( !CanRedo ) return;
- var e = UndoHistory.Last();
- UndoHistory.Remove( e );
- switch ( e.Action )
- {
- case HistoryEntry.HistoryAction.Create:
- Actions.AddAfter( Actions.Find( Find( e.Timestamp ) ), new Action( e.Timestamp, e.PositionAfter.Value ) );
- break;
- case HistoryEntry.HistoryAction.Update:
- Find( e.Timestamp ).Position = e.PositionAfter.Value;
- break;
- case HistoryEntry.HistoryAction.Delete:
- Actions.Remove( Find( e.Timestamp ) );
- break;
- }
- History.Add( e );
- }
-
- public static FunScript LoadFile( string file )
- {
- var fi = new FileInfo( file );
- switch( fi.Extension.Substring( 1 ).ToLower().Trim() )
- {
- default:
- throw new ArgumentException( $"Files of type { fi.Extension } can't be parsed.", "file" );
- case "funscript":
- return JsonConvert.DeserializeObject<FunScript>( File.ReadAllText( file ) );
- case "csv":
- var fs = new FunScript();
- foreach( var line in File.ReadAllLines( file ) ) {
- if ( line.StartsWith( "#" ) ) continue;
- var match = Regex.Match( line, @"([0-9\.]+),([0-9\.]+)(?:,.*)?", RegexOptions.Multiline );
- if ( match.Success )
- {
- try
- {
- fs.Actions.AddLast( new Action( long.Parse( match.Groups[ 1 ].Value ), int.Parse( match.Groups[ 2 ].Value ) ) );
- } catch ( Exception ex )
- {
- var i = 0;
- }
- }
- }
- return fs;
- }
- }
-
- public void SaveFile( string file )
- {
- var fi = new FileInfo( file );
- switch ( fi.Extension.Substring( 1 ).ToLower().Trim() )
- {
- default:
- throw new ArgumentException( $"Files of type { fi.Extension } can't be saved.", "file" );
- case "funscript":
- File.WriteAllText( file, JsonConvert.SerializeObject( this ) );
- break;
- case "csv":
- var lines = new LinkedList<string>();
- lines.AddLast( "#Compiled using Dragons Funscripta Tool" );
- foreach ( var action in Actions )
- {
- lines.AddLast( $"{ action.Timestamp },{ action.RelativePosition( Range, Inverted ) }" );
- }
- File.WriteAllLines( file, lines );
- break;
- }
- }
-
- public class Action
- {
- [JsonProperty( "pos" )]
- public int Position { get; set; }
- [JsonProperty( "at" )]
- public long Timestamp { get; private set; }
-
- public int RelativePosition( int range, bool inverted = false )
- {
- var pos = Position;
- if ( inverted ) pos = range - pos;
- return ( pos * 100 ) / range;
- }
-
- public Action( long timestamp, int position )
- {
- Position = position;
- Timestamp = timestamp;
- }
- }
- }
- }
|