Преглед на файлове

Initial commit

tags/First-Release
DragonSkills99 преди 5 години
родител
ревизия
0ab68f6f73

+ 25
- 0
Funscripta.sln Целия файл

@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30104.148
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Funscripta", "Funscripta\Funscripta.csproj", "{FA566A7A-A69B-4136-A0CC-4D6FBEB69DB5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FA566A7A-A69B-4136-A0CC-4D6FBEB69DB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FA566A7A-A69B-4136-A0CC-4D6FBEB69DB5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FA566A7A-A69B-4136-A0CC-4D6FBEB69DB5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FA566A7A-A69B-4136-A0CC-4D6FBEB69DB5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A0C8A1EE-D09E-4A3F-9744-1EDE6F13AF9E}
EndGlobalSection
EndGlobal

+ 18
- 0
Funscripta/App.config Целия файл

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="Funscripta.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<userSettings>
<Funscripta.Properties.Settings>
<setting name="FramesPerStep" serializeAs="String">
<value>1</value>
</setting>
</Funscripta.Properties.Settings>
</userSettings>
</configuration>

+ 441
- 0
Funscripta/Form1.Designer.cs Целия файл

@@ -0,0 +1,441 @@
namespace Funscripta
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose( bool disposing )
{
if ( disposing && ( components != null ) )
{
components.Dispose();
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.openFile = new System.Windows.Forms.ToolStripMenuItem();
this.openVideo = new System.Windows.Forms.ToolStripMenuItem();
this.saveFile = new System.Windows.Forms.ToolStripMenuItem();
this.saveFileAs = new System.Windows.Forms.ToolStripMenuItem();
this.newToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.mediaToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.playPause = new System.Windows.Forms.ToolStripMenuItem();
this.forward = new System.Windows.Forms.ToolStripMenuItem();
this.backward = new System.Windows.Forms.ToolStripMenuItem();
this.videoPanel = new System.Windows.Forms.Panel();
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.frames = new System.Windows.Forms.ToolStripStatusLabel();
this.framesPerSecond = new System.Windows.Forms.ToolStripStatusLabel();
this.currentFrame = new System.Windows.Forms.ToolStripStatusLabel();
this.toolStripSplitButton1 = new System.Windows.Forms.ToolStripSplitButton();
this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem();
this.framesPerStep = new System.Windows.Forms.ToolStripTextBox();
this.idleState = new System.Windows.Forms.ToolStripStatusLabel();
this.toolStripDropDownButton1 = new System.Windows.Forms.ToolStripDropDownButton();
this.removeNode = new System.Windows.Forms.ToolStripDropDownButton();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
this.position = new System.Windows.Forms.TrackBar();
this.viewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.unpackManagerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.trackBar1 = new System.Windows.Forms.TrackBar();
this.track1 = new Funscripta.Track();
this.menuStrip1.SuspendLayout();
this.videoPanel.SuspendLayout();
this.statusStrip1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.position)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit();
this.SuspendLayout();
//
// menuStrip1
//
this.menuStrip1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(55)))), ((int)(((byte)(55)))), ((int)(((byte)(55)))));
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.fileToolStripMenuItem,
this.mediaToolStripMenuItem,
this.viewToolStripMenuItem});
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
this.menuStrip1.Name = "menuStrip1";
this.menuStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.Professional;
this.menuStrip1.Size = new System.Drawing.Size(800, 24);
this.menuStrip1.TabIndex = 0;
this.menuStrip1.Text = "menuStrip1";
//
// fileToolStripMenuItem
//
this.fileToolStripMenuItem.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(55)))), ((int)(((byte)(55)))), ((int)(((byte)(55)))));
this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.openFile,
this.openVideo,
this.saveFile,
this.saveFileAs,
this.newToolStripMenuItem});
this.fileToolStripMenuItem.ForeColor = System.Drawing.Color.White;
this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
this.fileToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift)
| System.Windows.Forms.Keys.O)));
this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
this.fileToolStripMenuItem.Text = "File";
//
// openFile
//
this.openFile.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(55)))), ((int)(((byte)(55)))), ((int)(((byte)(55)))));
this.openFile.ForeColor = System.Drawing.Color.White;
this.openFile.Name = "openFile";
this.openFile.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O)));
this.openFile.Size = new System.Drawing.Size(211, 22);
this.openFile.Text = "Open";
this.openFile.Click += new System.EventHandler(this.openFile_Click);
//
// openVideo
//
this.openVideo.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(55)))), ((int)(((byte)(55)))), ((int)(((byte)(55)))));
this.openVideo.ForeColor = System.Drawing.Color.White;
this.openVideo.Name = "openVideo";
this.openVideo.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift)
| System.Windows.Forms.Keys.O)));
this.openVideo.Size = new System.Drawing.Size(211, 22);
this.openVideo.Text = "Open Video";
this.openVideo.Click += new System.EventHandler(this.openVideo_Click);
//
// saveFile
//
this.saveFile.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(55)))), ((int)(((byte)(55)))), ((int)(((byte)(55)))));
this.saveFile.ForeColor = System.Drawing.Color.White;
this.saveFile.Name = "saveFile";
this.saveFile.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S)));
this.saveFile.Size = new System.Drawing.Size(211, 22);
this.saveFile.Text = "Save";
this.saveFile.Click += new System.EventHandler(this.saveFile_Click);
//
// saveFileAs
//
this.saveFileAs.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(55)))), ((int)(((byte)(55)))), ((int)(((byte)(55)))));
this.saveFileAs.ForeColor = System.Drawing.Color.White;
this.saveFileAs.Name = "saveFileAs";
this.saveFileAs.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift)
| System.Windows.Forms.Keys.S)));
this.saveFileAs.Size = new System.Drawing.Size(211, 22);
this.saveFileAs.Text = "Save as...";
this.saveFileAs.Click += new System.EventHandler(this.saveFileAs_Click);
//
// newToolStripMenuItem
//
this.newToolStripMenuItem.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(55)))), ((int)(((byte)(55)))), ((int)(((byte)(55)))));
this.newToolStripMenuItem.ForeColor = System.Drawing.Color.White;
this.newToolStripMenuItem.Name = "newToolStripMenuItem";
this.newToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.N)));
this.newToolStripMenuItem.Size = new System.Drawing.Size(211, 22);
this.newToolStripMenuItem.Text = "New";
this.newToolStripMenuItem.Click += new System.EventHandler(this.newToolStripMenuItem_Click);
//
// mediaToolStripMenuItem
//
this.mediaToolStripMenuItem.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(55)))), ((int)(((byte)(55)))), ((int)(((byte)(55)))));
this.mediaToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.playPause,
this.forward,
this.backward});
this.mediaToolStripMenuItem.ForeColor = System.Drawing.Color.White;
this.mediaToolStripMenuItem.Name = "mediaToolStripMenuItem";
this.mediaToolStripMenuItem.Size = new System.Drawing.Size(52, 20);
this.mediaToolStripMenuItem.Text = "Media";
//
// playPause
//
this.playPause.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(55)))), ((int)(((byte)(55)))), ((int)(((byte)(55)))));
this.playPause.ForeColor = System.Drawing.Color.White;
this.playPause.Name = "playPause";
this.playPause.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Space)));
this.playPause.Size = new System.Drawing.Size(197, 22);
this.playPause.Text = "Play/Pause";
this.playPause.Click += new System.EventHandler(this.playPause_Click);
//
// forward
//
this.forward.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(55)))), ((int)(((byte)(55)))), ((int)(((byte)(55)))));
this.forward.ForeColor = System.Drawing.Color.White;
this.forward.Name = "forward";
this.forward.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Right)));
this.forward.Size = new System.Drawing.Size(197, 22);
this.forward.Text = "Forward";
this.forward.Click += new System.EventHandler(this.forward_Click);
//
// backward
//
this.backward.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(55)))), ((int)(((byte)(55)))), ((int)(((byte)(55)))));
this.backward.ForeColor = System.Drawing.Color.White;
this.backward.Name = "backward";
this.backward.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Left)));
this.backward.Size = new System.Drawing.Size(197, 22);
this.backward.Text = "Backward";
this.backward.Click += new System.EventHandler(this.backward_Click);
//
// videoPanel
//
this.videoPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.videoPanel.AutoScroll = true;
this.videoPanel.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.videoPanel.Controls.Add(this.pictureBox1);
this.videoPanel.Location = new System.Drawing.Point(12, 27);
this.videoPanel.Name = "videoPanel";
this.videoPanel.Size = new System.Drawing.Size(725, 408);
this.videoPanel.TabIndex = 1;
//
// statusStrip1
//
this.statusStrip1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(55)))), ((int)(((byte)(55)))), ((int)(((byte)(55)))));
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.frames,
this.framesPerSecond,
this.currentFrame,
this.toolStripSplitButton1,
this.idleState,
this.toolStripDropDownButton1,
this.removeNode});
this.statusStrip1.Location = new System.Drawing.Point(0, 541);
this.statusStrip1.Name = "statusStrip1";
this.statusStrip1.Size = new System.Drawing.Size(800, 22);
this.statusStrip1.TabIndex = 2;
this.statusStrip1.Text = "statusStrip1";
//
// frames
//
this.frames.Name = "frames";
this.frames.Size = new System.Drawing.Size(57, 17);
this.frames.Text = "Frames: 0";
//
// framesPerSecond
//
this.framesPerSecond.Name = "framesPerSecond";
this.framesPerSecond.Size = new System.Drawing.Size(38, 17);
this.framesPerSecond.Text = "FPS: 0";
//
// currentFrame
//
this.currentFrame.Name = "currentFrame";
this.currentFrame.Size = new System.Drawing.Size(95, 17);
this.currentFrame.Text = "Current Frame: 0";
//
// toolStripSplitButton1
//
this.toolStripSplitButton1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(55)))), ((int)(((byte)(55)))), ((int)(((byte)(55)))));
this.toolStripSplitButton1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
this.toolStripSplitButton1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripMenuItem2,
this.framesPerStep});
this.toolStripSplitButton1.Image = ((System.Drawing.Image)(resources.GetObject("toolStripSplitButton1.Image")));
this.toolStripSplitButton1.ImageTransparentColor = System.Drawing.Color.Magenta;
this.toolStripSplitButton1.Name = "toolStripSplitButton1";
this.toolStripSplitButton1.Size = new System.Drawing.Size(65, 20);
this.toolStripSplitButton1.Text = "Settings";
//
// toolStripMenuItem2
//
this.toolStripMenuItem2.BackColor = System.Drawing.Color.White;
this.toolStripMenuItem2.Name = "toolStripMenuItem2";
this.toolStripMenuItem2.Size = new System.Drawing.Size(160, 22);
this.toolStripMenuItem2.Text = "Frames per Step";
//
// framesPerStep
//
this.framesPerStep.BackColor = System.Drawing.Color.White;
this.framesPerStep.Font = new System.Drawing.Font("Segoe UI", 9F);
this.framesPerStep.Name = "framesPerStep";
this.framesPerStep.Size = new System.Drawing.Size(100, 23);
this.framesPerStep.Text = "1";
this.framesPerStep.TextChanged += new System.EventHandler(this.framesPerStep_TextChanged);
//
// idleState
//
this.idleState.Name = "idleState";
this.idleState.Size = new System.Drawing.Size(26, 17);
this.idleState.Text = "Idle";
//
// toolStripDropDownButton1
//
this.toolStripDropDownButton1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
this.toolStripDropDownButton1.Image = ((System.Drawing.Image)(resources.GetObject("toolStripDropDownButton1.Image")));
this.toolStripDropDownButton1.ImageTransparentColor = System.Drawing.Color.Magenta;
this.toolStripDropDownButton1.Name = "toolStripDropDownButton1";
this.toolStripDropDownButton1.ShowDropDownArrow = false;
this.toolStripDropDownButton1.Size = new System.Drawing.Size(120, 20);
this.toolStripDropDownButton1.Text = "Clear Unpacked Files";
//
// removeNode
//
this.removeNode.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
this.removeNode.Image = ((System.Drawing.Image)(resources.GetObject("removeNode.Image")));
this.removeNode.ImageTransparentColor = System.Drawing.Color.Magenta;
this.removeNode.Name = "removeNode";
this.removeNode.ShowDropDownArrow = false;
this.removeNode.Size = new System.Drawing.Size(86, 20);
this.removeNode.Text = "Remove Node";
this.removeNode.Click += new System.EventHandler(this.removeNode_Click);
//
// timer1
//
this.timer1.Interval = 1000;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
//
// backgroundWorker1
//
this.backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker1_DoWork);
//
// position
//
this.position.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.position.Location = new System.Drawing.Point(12, 441);
this.position.Maximum = 100;
this.position.Name = "position";
this.position.Size = new System.Drawing.Size(776, 45);
this.position.TabIndex = 4;
this.position.Scroll += new System.EventHandler(this.position_Scroll);
this.position.ValueChanged += new System.EventHandler(this.position_ValueChanged);
//
// viewToolStripMenuItem
//
this.viewToolStripMenuItem.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(55)))), ((int)(((byte)(55)))), ((int)(((byte)(55)))));
this.viewToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.unpackManagerToolStripMenuItem});
this.viewToolStripMenuItem.ForeColor = System.Drawing.Color.White;
this.viewToolStripMenuItem.Name = "viewToolStripMenuItem";
this.viewToolStripMenuItem.Size = new System.Drawing.Size(44, 20);
this.viewToolStripMenuItem.Text = "View";
//
// unpackManagerToolStripMenuItem
//
this.unpackManagerToolStripMenuItem.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(55)))), ((int)(((byte)(55)))), ((int)(((byte)(55)))));
this.unpackManagerToolStripMenuItem.ForeColor = System.Drawing.Color.White;
this.unpackManagerToolStripMenuItem.Name = "unpackManagerToolStripMenuItem";
this.unpackManagerToolStripMenuItem.Size = new System.Drawing.Size(166, 22);
this.unpackManagerToolStripMenuItem.Text = "Unpack-Manager";
this.unpackManagerToolStripMenuItem.Click += new System.EventHandler(this.unpackManagerToolStripMenuItem_Click);
//
// pictureBox1
//
this.pictureBox1.Location = new System.Drawing.Point(0, 0);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(725, 408);
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pictureBox1.TabIndex = 0;
this.pictureBox1.TabStop = false;
//
// trackBar1
//
this.trackBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.trackBar1.Location = new System.Drawing.Point(743, 27);
this.trackBar1.Maximum = 500;
this.trackBar1.Minimum = 100;
this.trackBar1.Name = "trackBar1";
this.trackBar1.Orientation = System.Windows.Forms.Orientation.Vertical;
this.trackBar1.Size = new System.Drawing.Size(45, 408);
this.trackBar1.TabIndex = 1;
this.trackBar1.Value = 500;
this.trackBar1.Scroll += new System.EventHandler(this.trackBar1_Scroll);
//
// track1
//
this.track1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.track1.CurrentFrame = ((long)(0));
this.track1.FrameRate = ((long)(60));
this.track1.FunScript = null;
this.track1.Location = new System.Drawing.Point(12, 492);
this.track1.MaxFrames = ((long)(1));
this.track1.Name = "track1";
this.track1.Size = new System.Drawing.Size(776, 46);
this.track1.TabIndex = 3;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(55)))), ((int)(((byte)(55)))), ((int)(((byte)(55)))));
this.ClientSize = new System.Drawing.Size(800, 563);
this.Controls.Add(this.trackBar1);
this.Controls.Add(this.position);
this.Controls.Add(this.track1);
this.Controls.Add(this.statusStrip1);
this.Controls.Add(this.videoPanel);
this.Controls.Add(this.menuStrip1);
this.ForeColor = System.Drawing.Color.White;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.KeyPreview = true;
this.MainMenuStrip = this.menuStrip1;
this.Name = "Form1";
this.Text = "Funscripta";
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
this.videoPanel.ResumeLayout(false);
this.statusStrip1.ResumeLayout(false);
this.statusStrip1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.position)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();

}

#endregion

private System.Windows.Forms.MenuStrip menuStrip1;
private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem openFile;
private System.Windows.Forms.ToolStripMenuItem saveFile;
private System.Windows.Forms.ToolStripMenuItem saveFileAs;
private System.Windows.Forms.ToolStripMenuItem openVideo;
private System.Windows.Forms.Panel videoPanel;
private System.Windows.Forms.ToolStripMenuItem mediaToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem playPause;
private System.Windows.Forms.ToolStripMenuItem forward;
private System.Windows.Forms.ToolStripMenuItem backward;
private System.Windows.Forms.StatusStrip statusStrip1;
private System.Windows.Forms.ToolStripStatusLabel frames;
private System.Windows.Forms.Timer timer1;
private System.Windows.Forms.ToolStripStatusLabel framesPerSecond;
private System.Windows.Forms.ToolStripStatusLabel currentFrame;
private System.Windows.Forms.ToolStripSplitButton toolStripSplitButton1;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem2;
private System.Windows.Forms.ToolStripTextBox framesPerStep;
private Track track1;
private System.ComponentModel.BackgroundWorker backgroundWorker1;
private System.Windows.Forms.ToolStripStatusLabel idleState;
private System.Windows.Forms.ToolStripMenuItem newToolStripMenuItem;
private System.Windows.Forms.ToolStripDropDownButton removeNode;
private System.Windows.Forms.ToolStripDropDownButton toolStripDropDownButton1;
private System.Windows.Forms.TrackBar position;
private System.Windows.Forms.ToolStripMenuItem viewToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem unpackManagerToolStripMenuItem;
private System.Windows.Forms.TrackBar trackBar1;
private System.Windows.Forms.PictureBox pictureBox1;
}
}


+ 337
- 0
Funscripta/Form1.cs Целия файл

@@ -0,0 +1,337 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Accord;
using Accord.Video.FFMPEG;
using Ionic.Zip;
using Microsoft.DirectX.AudioVideoPlayback;

namespace Funscripta
{
public partial class Form1 : Form
{
private string FileName { get; set; }
private string RawName { get; set; }
private SaveFileDialog sfd = new SaveFileDialog();
private OpenFileDialog ofd = new OpenFileDialog();
private OpenFileDialog ofdv = new OpenFileDialog();

private VideoFileReader VFR { get; set; } = new VideoFileReader();
private ZipFile Zip { get; set; }
private long Frame { get; set; } = 0;

private DirectoryInfo libDirectory = new DirectoryInfo( Path.Combine( ".", "libvlc", IntPtr.Size == 4 ? "x86" : "x64" ) );
public Form1()
{
if ( !libDirectory.Exists ) libDirectory.Create();
InitializeComponent();
sfd.Filter = ofd.Filter = "Funscript|*.funscript|Comma Separated Values|*.csv";
ofdv.Filter = "Media Files|*.mpg;*.avi;*.mov;*.mp4;*.flv|All Files|*.*";
ofdv.DefaultExt = ".mp4";
framesPerStep.Text = Properties.Settings.Default.FramesPerStep.ToString();
track1.FunScript = new FunScript();
track1.FrameChanged += Track1_FrameChanged;
}

private void Track1_FrameChanged( long frame, Track.Action sender )
{
if ( sender == Track.Action.Click )
{
Frame = frame;
LoadFrame();
}
}

private void saveFileAs_Click( object sender, EventArgs e )
{
if ( sfd.ShowDialog() == DialogResult.OK )
{
FileName = sfd.FileName;
saveFile_Click( sender, e );
}
}

private void saveFile_Click( object sender, EventArgs e )
{
if ( FileName == null )
{
saveFileAs_Click( sender, e );
return;
}
track1.FunScript.SaveFile( FileName );
}

private void openFile_Click( object sender, EventArgs e )
{
if ( ofd.ShowDialog() == DialogResult.OK )
{
openFunScript( ofd.FileName );
}
}

private void openFunScript( string fileName )
{
FileName = fileName;
track1.FunScript = FunScript.LoadFile( FileName );
position.Maximum = track1.FunScript.Range;
}

private void openVideo_Click( object sender, EventArgs e )
{
if ( ofdv.ShowDialog() == DialogResult.OK )
{
try
{
var fi = new FileInfo( ofdv.FileName );
VFR.Open( ofdv.FileName );
lastFrame = -1;
Frame = 0;
LoadFrame();
frames.Text = $"Frames: { VFR.FrameCount }";
framesPerSecond.Text = $"FPS: { VFR.FrameRate.Value }";
track1.MaxFrames = VFR.FrameCount;
track1.FrameRate = ( long ) VFR.FrameRate.Value;
timer1.Start();
var fname = fi.FullName.Substring( 0, fi.FullName.Length - fi.Extension.Length );
if ( File.Exists( FileName = $"{ fname }.csv" ) || File.Exists( FileName = $"{ fname }.funscript" ) )
{
openFunScript( FileName );
}
RawName = $"{ fname }.raw";
if ( Zip != null )
{
Zip.Dispose();
Zip = null;
}
if ( File.Exists( $"{ fname }.rawc" ) ) Zip = new ZipFile( $"{ fname }.rawc" );
} catch ( Exception ex )
{
MessageBox.Show( ex.Message );
}
}
}

private void playPause_Click( object sender, EventArgs e )
{
//if ( VideoControl == null ) return;
//switch ( VideoControl.State )
//{
// case Vlc.DotNet.Core.Interops.Signatures.MediaStates.Buffering:
// case Vlc.DotNet.Core.Interops.Signatures.MediaStates.Playing:
// VideoControl.Pause();
// break;
// default:
// case Vlc.DotNet.Core.Interops.Signatures.MediaStates.Error:
// case Vlc.DotNet.Core.Interops.Signatures.MediaStates.Ended:
// VideoControl.SetMedia( VideoControl.GetCurrentMedia().Mrl );
// break;
// case Vlc.DotNet.Core.Interops.Signatures.MediaStates.Opening:
// case Vlc.DotNet.Core.Interops.Signatures.MediaStates.Paused:
// case Vlc.DotNet.Core.Interops.Signatures.MediaStates.Stopped:
// VideoControl.Play();
// break;
//}
}

private void forward_Click( object sender, EventArgs e )
{
Frame += Properties.Settings.Default.FramesPerStep;
LoadFrame();
}

private void backward_Click( object sender, EventArgs e )
{
Frame -= Properties.Settings.Default.FramesPerStep;
LoadFrame();
}

private void LoadFrame()
{
if ( !VFR.IsOpen )
{
Frame = 0;
return;
}
if ( Frame < 0 ) Frame = 0;
else if ( Frame >= VFR.FrameCount ) Frame = VFR.FrameCount - 1;
currentFrame.Text = $"Current Frame: { Frame }";
track1.CurrentFrame = Frame;
position.Value = track1.FunScript.Find( ( long ) track1.CurrentTimestamp ).Position;
}

private void Form1_KeyDown( object sender, KeyEventArgs e )
{
switch ( e.KeyCode )
{
case Keys.Space:
playPause_Click( sender, e );
break;
case Keys.Right:
forward_Click( sender, e );
break;
case Keys.Left:
backward_Click( sender, e );
break;
}
}

private long lastFrame = -1;
private void timer1_Tick( object sender, EventArgs e )
{
if ( !backgroundWorker1.IsBusy ) backgroundWorker1.RunWorkerAsync();
}

private void framesPerStep_TextChanged( object sender, EventArgs e )
{
if ( !Regex.IsMatch( framesPerStep.Text, "[0-9]+" ) )
{
framesPerStep.Text = Properties.Settings.Default.FramesPerStep.ToString();
}
var fps = int.Parse( framesPerStep.Text );
if ( Properties.Settings.Default.FramesPerStep != fps )
{
Properties.Settings.Default.FramesPerStep = fps;
Properties.Settings.Default.Save();
}
}

private Image GetFrame()
{
Image img = null;
var localName = $"{ RawName }/{ Frame + 1 }";
if ( Zip != null && Zip.ContainsEntry( ( Frame + 1 ).ToString() ) ) img = Image.FromStream( Zip[ ( Frame + 1 ).ToString() ].OpenReader() );
else if ( File.Exists( localName ) ) img = Image.FromFile( localName );
else if ( VFR.IsOpen ) img = VFR.ReadVideoFrame( ( int ) Frame );
return img;
}

private string FrameMode()
{
var localName = $"{ RawName }/{ Frame + 1 }";
if ( Zip != null && Zip.ContainsEntry( ( Frame + 1 ).ToString() ) ) return "zipped";
else if ( File.Exists( localName ) ) return "unpacked";
else return "slow";
}

private void backgroundWorker1_DoWork( object sender, DoWorkEventArgs e )
{

if ( lastFrame != Frame )
{
var frame = Frame;
lastFrame = Frame;
var t = new Task( () => {
idleState.Text = $"Busy ({ FrameMode() })";
if ( pictureBox1.Image != null )
{
pictureBox1.Image.Dispose();
pictureBox1.Image = null;
}
var frm = GetFrame();
if ( Frame == frame )
{
pictureBox1.Image = frm;
idleState.Text = "Idle";
}
} );
t.Start();
}
}

private void newToolStripMenuItem_Click( object sender, EventArgs e )
{
track1.FunScript = new FunScript();
}

private void unpack_Click( object sender, EventArgs e )
{
if ( string.IsNullOrWhiteSpace( RawName ) ) return;
var t = new Task( () => {
this.MayInvoke( () => Enabled = false );
idleState.Text = $"Unpacking ( 0 / { VFR.FrameCount } )";
if ( !Directory.Exists( RawName ) ) Directory.CreateDirectory( RawName );
SaveFrame( 0 );
for ( var i = 1; i < VFR.FrameCount; i++ )
{
SaveFrame( i );
idleState.Text = $"Unpacking ( { i } / { VFR.FrameCount } )";
}
this.MayInvoke( () => Enabled = true );
} );
t.Start();
}

private void SaveFrame( int index )
{
Bitmap bmp = index == 0 ? VFR.ReadVideoFrame( 0 ) : VFR.ReadVideoFrame();
bmp.Save( $"{ RawName }/{ index + 1 }", System.Drawing.Imaging.ImageFormat.Jpeg );
bmp.Dispose();
}

private void clearUnpacked_Click( object sender, EventArgs e )
{
if ( Directory.Exists( RawName ) ) Directory.Delete( RawName, true );
}

private void position_ValueChanged( object sender, EventArgs e )
{
}

private Task ScrollDelay;

private void position_Scroll( object sender, EventArgs e )
{
var val = position.Value;
ScrollDelay = new Task( () => {
System.Threading.Thread.Sleep( 100 );
if ( position.MayInvoke( () => position.Value ) != val ) return;
this.MayInvoke( PositionChanged );
} );
ScrollDelay.Start();
}



private void PositionChanged()
{
track1.FunScript.AddAction( ( long ) track1.CurrentTimestamp, position.Value );
track1.Refresh();
}

private void removeNode_Click( object sender, EventArgs e )
{
track1.FunScript.RemoveAction( ( long ) track1.CurrentTimestamp );
track1.Refresh();
position.Value = track1.FunScript.Find( ( long ) track1.CurrentTimestamp ).Position;
}

private void unpackManagerToolStripMenuItem_Click( object sender, EventArgs e )
{
foreach( var form in Application.OpenForms )
{
if ( form.GetType() == typeof( Unpack_Manager ) ) return;
}
( new Unpack_Manager() ).Show();
}

private void trackBar1_Scroll( object sender, EventArgs e )
{
var val = trackBar1.Maximum - trackBar1.Value + trackBar1.Minimum;
var mod = val / 100D;
pictureBox1.Width = ( int ) ( videoPanel.Width * mod );
pictureBox1.Height = ( int ) ( videoPanel.Height * mod );
videoPanel.HorizontalScroll.Enabled = mod > 1D;
videoPanel.VerticalScroll.Enabled = mod > 1D;
}
}
}

+ 238
- 0
Funscripta/Form1.resx Целия файл

@@ -0,0 +1,238 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>132, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="toolStripSplitButton1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
TgDQASA1MVpwzwAAAABJRU5ErkJggg==
</value>
</data>
<data name="toolStripDropDownButton1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
TgDQASA1MVpwzwAAAABJRU5ErkJggg==
</value>
</data>
<data name="removeNode.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
TgDQASA1MVpwzwAAAABJRU5ErkJggg==
</value>
</data>
<metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>248, 17</value>
</metadata>
<metadata name="backgroundWorker1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>335, 17</value>
</metadata>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
rkJggg==
</value>
</data>
</root>

+ 140
- 0
Funscripta/FunScript.cs Целия файл

@@ -0,0 +1,140 @@
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
{
[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;



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 )
{
if ( timestamp < 0 && Find( timestamp - 1 ).Position == position ) RemoveAction( timestamp );
else a.Position = position;
}
else if ( a.Position == position ) return;
else
{
var _a = Actions.Find( a );
Actions.AddAfter( _a, new Action( timestamp, position ) );
}
}

public void RemoveAction( long timestamp )
{
var a = Find( timestamp );
if ( a.Timestamp != 0 ) Actions.Remove( Actions.Find( a ) );
}

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 )
{
fs.Actions.AddLast( new Action( long.Parse( match.Groups[ 0 ].Value ), int.Parse( match.Groups[ 1 ].Value ) ) );
}
}
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;
}
}
}
}

+ 195
- 0
Funscripta/Funscripta.csproj Целия файл

@@ -0,0 +1,195 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{FA566A7A-A69B-4136-A0CC-4D6FBEB69DB5}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>Funscripta</RootNamespace>
<AssemblyName>Funscripta</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>vibrator.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="Accord, Version=3.8.2.0, Culture=neutral, PublicKeyToken=fa1a88e29555ccf7, processorArchitecture=MSIL">
<HintPath>..\packages\Accord.3.8.2-alpha\lib\net462\Accord.dll</HintPath>
</Reference>
<Reference Include="Accord.Video, Version=3.8.2.0, Culture=neutral, PublicKeyToken=fa1a88e29555ccf7, processorArchitecture=MSIL">
<HintPath>..\packages\Accord.Video.3.8.2-alpha\lib\net462\Accord.Video.dll</HintPath>
</Reference>
<Reference Include="Accord.Video.FFMPEG, Version=3.8.2.0, Culture=neutral, PublicKeyToken=fa1a88e29555ccf7, processorArchitecture=x86">
<HintPath>..\packages\Accord.Video.FFMPEG.3.8.2-alpha\lib\net462\Accord.Video.FFMPEG.dll</HintPath>
</Reference>
<Reference Include="Ionic.Zip, Version=1.9.1.8, Culture=neutral, PublicKeyToken=edbe51ad942a3f5c, processorArchitecture=MSIL">
<HintPath>..\packages\Ionic.Zip.1.9.1.8\lib\Ionic.Zip.dll</HintPath>
</Reference>
<Reference Include="Microsoft.DirectX.AudioVideoPlayback, Version=1.0.2902.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\Windows\assembly\GAC\Microsoft.DirectX.AudioVideoPlayback\1.0.2902.0__31bf3856ad364e35\Microsoft.DirectX.AudioVideoPlayback.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon>
</Compile>
<Compile Include="FunScript.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Track.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Track.Designer.cs">
<DependentUpon>Track.cs</DependentUpon>
</Compile>
<Compile Include="Unpack-Manager.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Unpack-Manager.Designer.cs">
<DependentUpon>Unpack-Manager.cs</DependentUpon>
</Compile>
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<EmbeddedResource Include="Track.resx">
<DependentUpon>Track.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Unpack-Manager.resx">
<DependentUpon>Unpack-Manager.cs</DependentUpon>
</EmbeddedResource>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<COMReference Include="DXTMSFTLib">
<Guid>{5E77EB03-937C-11D1-B047-00AA003B6061}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>1</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
<COMReference Include="DXTRANSLib">
<Guid>{54314D1D-35FE-11D1-81A1-0000F87557DB}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>1</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
<COMReference Include="stdole">
<Guid>{00020430-0000-0000-C000-000000000046}</Guid>
<VersionMajor>2</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>primary</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
</ItemGroup>
<ItemGroup>
<Content Include="vibrator.ico" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.7.2">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.7.2 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\Accord.3.8.2-alpha\build\Accord.targets" Condition="Exists('..\packages\Accord.3.8.2-alpha\build\Accord.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Accord.3.8.2-alpha\build\Accord.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Accord.3.8.2-alpha\build\Accord.targets'))" />
<Error Condition="!Exists('..\packages\Accord.Video.FFMPEG.3.8.2-alpha\build\Accord.Video.FFMPEG.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Accord.Video.FFMPEG.3.8.2-alpha\build\Accord.Video.FFMPEG.targets'))" />
</Target>
<Import Project="..\packages\Accord.Video.FFMPEG.3.8.2-alpha\build\Accord.Video.FFMPEG.targets" Condition="Exists('..\packages\Accord.Video.FFMPEG.3.8.2-alpha\build\Accord.Video.FFMPEG.targets')" />
</Project>

+ 45
- 0
Funscripta/Program.cs Целия файл

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Funscripta
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault( false );
Application.Run( new Form1() );
}

public static void MayInvoke( this Control c, Action a )
{
if ( c.InvokeRequired ) c.Invoke( a );
else a();
}

public static T MayInvoke<T>( this Control c, Func<T> a )
{
if ( c.InvokeRequired ) return ( T ) c.Invoke( a );
else return a();
}

public static double DecimalStrip( this double d, int decimals = 2 )
{
return ( ( float ) d ).DecimalStrip( decimals );
}
public static double DecimalStrip( this float f, int decimals = 2 )
{
var mod = Math.Pow( 10, decimals );
return Math.Round( f * mod ) / mod;
}
}
}

+ 36
- 0
Funscripta/Properties/AssemblyInfo.cs Целия файл

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle( "Funscripta" )]
[assembly: AssemblyDescription( "" )]
[assembly: AssemblyConfiguration( "" )]
[assembly: AssemblyCompany( "" )]
[assembly: AssemblyProduct( "Funscripta" )]
[assembly: AssemblyCopyright( "Copyright © 2020" )]
[assembly: AssemblyTrademark( "" )]
[assembly: AssemblyCulture( "" )]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible( false )]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid( "fa566a7a-a69b-4136-a0cc-4d6fbeb69db5" )]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion( "1.0.0.0" )]
[assembly: AssemblyFileVersion( "1.0.0.0" )]

+ 71
- 0
Funscripta/Properties/Resources.Designer.cs Целия файл

@@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace Funscripta.Properties
{


/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute( "System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0" )]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{

private static global::System.Resources.ResourceManager resourceMan;

private static global::System.Globalization.CultureInfo resourceCulture;

[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )]
internal Resources()
{
}

/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute( global::System.ComponentModel.EditorBrowsableState.Advanced )]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ( ( resourceMan == null ) )
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager( "Funscripta.Properties.Resources", typeof( Resources ).Assembly );
resourceMan = temp;
}
return resourceMan;
}
}

/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute( global::System.ComponentModel.EditorBrowsableState.Advanced )]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

+ 117
- 0
Funscripta/Properties/Resources.resx Целия файл

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

+ 38
- 0
Funscripta/Properties/Settings.Designer.cs Целия файл

@@ -0,0 +1,38 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace Funscripta.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.5.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("1")]
public int FramesPerStep {
get {
return ((int)(this["FramesPerStep"]));
}
set {
this["FramesPerStep"] = value;
}
}
}
}

+ 9
- 0
Funscripta/Properties/Settings.settings Целия файл

@@ -0,0 +1,9 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="Funscripta.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="FramesPerStep" Type="System.Int32" Scope="User">
<Value Profile="(Default)">1</Value>
</Setting>
</Settings>
</SettingsFile>

+ 47
- 0
Funscripta/Track.Designer.cs Целия файл

@@ -0,0 +1,47 @@
namespace Funscripta
{
partial class Track
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose( bool disposing )
{
if ( disposing && ( components != null ) )
{
components.Dispose();
}
base.Dispose( disposing );
}

#region Component Designer generated code

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// Track
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "Track";
this.Size = new System.Drawing.Size(588, 46);
this.Click += new System.EventHandler(this.Track_Click);
this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.Track_MouseClick);
this.ResumeLayout(false);

}

#endregion
}
}

+ 113
- 0
Funscripta/Track.cs Целия файл

@@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Funscripta
{
public partial class Track : UserControl
{
public enum Action
{
Script, Click
}

private FunScript _funScript = new FunScript();
public delegate void FrameChangedDelegate( long frame, Action sender );
public event FrameChangedDelegate FrameChanged;

public FunScript FunScript {
get => _funScript;
set
{
_funScript = value;
Refresh();
}
}
private long _maxFrames = 1;
public long MaxFrames {
get => _maxFrames;
set
{
_maxFrames = value < 1 ? 1 : value;
Refresh();
}
}
private long _currentFrame = 0;
public long CurrentFrame
{
get => _currentFrame;
set
{
_currentFrame = value < 0 ? 0 : ( value >= MaxFrames ? MaxFrames - 1 : value );
FrameChanged( _currentFrame, Action.Script );
Refresh();
}
}
private long _frameRate = 60;
public long FrameRate
{
get => _frameRate;
set
{
_frameRate = value < 1 ? 1 : value;
Refresh();
}
}
public Track()
{
InitializeComponent();
FrameChanged += ( l, s ) => { };
}

protected override void OnPaintBackground( PaintEventArgs e )
{
}

public float MaxMilliseconds => MaxFrames * 1000F / FrameRate;
public float CurrentTimestamp => MaxMilliseconds * ( CurrentFrame / ( float ) MaxFrames );

protected override void OnPaint( PaintEventArgs e )
{
e.Graphics.FillRectangle( new SolidBrush( Color.FromArgb( 40, 40, 40 ) ), new Rectangle( new Point( 0, 0 ), Size ) );

var h_area = Height - 6;
var w_area = Width - 6;

if ( FunScript != null )
foreach ( var action in FunScript.Actions )
{
var milliseconds = MaxMilliseconds;
var x = w_area * ( action.Timestamp / milliseconds );
var y = h_area - ( h_area * ( action.Position / ( float)FunScript.Range ) );
e.Graphics.FillEllipse( new SolidBrush( Color.Lime ), x, y, 5, 5 );
e.Graphics.DrawEllipse( new Pen( Color.DarkGreen ), x, y, 5, 5 );
}
var cursor = w_area * ( CurrentFrame / ( float ) MaxFrames );
e.Graphics.DrawLine( new Pen( Color.Red ), new PointF( cursor, 0 ), new PointF( cursor, Height ) );
}

private void Track_Click( object sender, EventArgs e )
{

}

private void Track_MouseClick( object sender, MouseEventArgs e )
{
if ( e.Button == MouseButtons.Left )
{
var frame = MaxFrames * ( e.X / ( Width - 6F ) );
if ( CurrentFrame != frame )
{
CurrentFrame = ( long ) frame;
FrameChanged( CurrentFrame, Action.Click );
}
}
}
}
}

+ 120
- 0
Funscripta/Track.resx Целия файл

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

+ 191
- 0
Funscripta/Unpack-Manager.Designer.cs Целия файл

@@ -0,0 +1,191 @@
namespace Funscripta
{
partial class Unpack_Manager
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose( bool disposing )
{
if ( disposing && ( components != null ) )
{
components.Dispose();
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Unpack_Manager));
this.maxActiveThreads = new System.Windows.Forms.NumericUpDown();
this.label1 = new System.Windows.Forms.Label();
this.listView1 = new System.Windows.Forms.ListView();
this.CName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.ProgressPerc = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.ProgressItems = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.speed = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.timeLeft = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
((System.ComponentModel.ISupportInitialize)(this.maxActiveThreads)).BeginInit();
this.SuspendLayout();
//
// maxActiveThreads
//
this.maxActiveThreads.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.maxActiveThreads.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(55)))), ((int)(((byte)(55)))), ((int)(((byte)(55)))));
this.maxActiveThreads.ForeColor = System.Drawing.Color.White;
this.maxActiveThreads.Location = new System.Drawing.Point(147, 12);
this.maxActiveThreads.Name = "maxActiveThreads";
this.maxActiveThreads.Size = new System.Drawing.Size(641, 20);
this.maxActiveThreads.TabIndex = 0;
this.maxActiveThreads.Value = new decimal(new int[] {
2,
0,
0,
0});
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 14);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(129, 13);
this.label1.TabIndex = 1;
this.label1.Text = "Max simultaneous threads";
//
// listView1
//
this.listView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.listView1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(55)))), ((int)(((byte)(55)))), ((int)(((byte)(55)))));
this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.CName,
this.ProgressPerc,
this.ProgressItems,
this.speed,
this.timeLeft});
this.listView1.ForeColor = System.Drawing.Color.White;
this.listView1.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
this.listView1.HideSelection = false;
this.listView1.Location = new System.Drawing.Point(12, 38);
this.listView1.Name = "listView1";
this.listView1.OwnerDraw = true;
this.listView1.Size = new System.Drawing.Size(776, 371);
this.listView1.TabIndex = 2;
this.listView1.UseCompatibleStateImageBehavior = false;
this.listView1.View = System.Windows.Forms.View.Details;
//
// CName
//
this.CName.Text = "Name";
this.CName.Width = 447;
//
// ProgressPerc
//
this.ProgressPerc.Text = "Progress (%)";
this.ProgressPerc.Width = 76;
//
// ProgressItems
//
this.ProgressItems.Text = "Progress (x/x)";
this.ProgressItems.Width = 106;
//
// speed
//
this.speed.Text = "Speed";
this.speed.Width = 64;
//
// timeLeft
//
this.timeLeft.Text = "Time left";
this.timeLeft.Width = 69;
//
// button1
//
this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.button1.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.button1.Location = new System.Drawing.Point(582, 415);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(206, 23);
this.button1.TabIndex = 3;
this.button1.Text = "Add Video";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// button2
//
this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.button2.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.button2.Location = new System.Drawing.Point(12, 415);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(206, 23);
this.button2.TabIndex = 4;
this.button2.Text = "Remove Selected";
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// timer1
//
this.timer1.Enabled = true;
this.timer1.Interval = 500;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
//
// backgroundWorker1
//
this.backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker1_DoWork);
//
// Unpack_Manager
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(55)))), ((int)(((byte)(55)))), ((int)(((byte)(55)))));
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Controls.Add(this.listView1);
this.Controls.Add(this.label1);
this.Controls.Add(this.maxActiveThreads);
this.ForeColor = System.Drawing.Color.White;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "Unpack_Manager";
this.Text = "Funscripta Unpack-Manager";
((System.ComponentModel.ISupportInitialize)(this.maxActiveThreads)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();

}

#endregion

private System.Windows.Forms.NumericUpDown maxActiveThreads;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.ListView listView1;
private System.Windows.Forms.ColumnHeader CName;
private System.Windows.Forms.ColumnHeader ProgressPerc;
private System.Windows.Forms.ColumnHeader ProgressItems;
private System.Windows.Forms.ColumnHeader speed;
private System.Windows.Forms.ColumnHeader timeLeft;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Timer timer1;
private System.ComponentModel.BackgroundWorker backgroundWorker1;
}
}

+ 337
- 0
Funscripta/Unpack-Manager.cs Целия файл

@@ -0,0 +1,337 @@
using Accord;
using Accord.Video.FFMPEG;
using Ionic.Zip;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Funscripta
{
public partial class Unpack_Manager : Form
{
private static List<PackThread> PackThreads { get; set; } = new List<PackThread>();
private OpenFileDialog ofd = new OpenFileDialog();
private List<string> Videos = new List<string>();


public Unpack_Manager()
{
InitializeComponent();
ofd.Filter = "Media Files|*.mpg;*.avi;*.mov;*.mp4;*.flv|All Files|*.*";
ofd.DefaultExt = ".mp4";
ofd.Multiselect = true;
listView1.DrawColumnHeader += listView1_DrawColumnHeader;
listView1.DrawItem += ListView1_DrawItem;
listView1.DrawSubItem += ListView1_DrawSubItem;
foreach ( var thread in PackThreads )
{
var lvi = new ListViewItem( thread.Video.Name );
thread.Item = lvi;
listView1.Items.Add( lvi );
Videos.Add( thread.Video.FullName );
}
}

private void ListView1_DrawSubItem( object sender, DrawListViewSubItemEventArgs e )
{
TextFormatFlags flags = TextFormatFlags.Left;

using ( StringFormat sf = new StringFormat() )
{
// Store the column text alignment, letting it default
// to Left if it has not been set to Center or Right.
switch ( e.Header.TextAlign )
{
case HorizontalAlignment.Center:
sf.Alignment = StringAlignment.Center;
flags = TextFormatFlags.HorizontalCenter;
break;
case HorizontalAlignment.Right:
sf.Alignment = StringAlignment.Far;
flags = TextFormatFlags.Right;
break;
}

// Draw the text and background for a subitem with a
// negative value.
double subItemValue;
if ( e.ColumnIndex > 0 && Double.TryParse(
e.SubItem.Text, NumberStyles.Currency,
NumberFormatInfo.CurrentInfo, out subItemValue ) &&
subItemValue < 0 )
{
// Unless the item is selected, draw the standard
// background to make it stand out from the gradient.
if ( ( e.ItemState & ListViewItemStates.Selected ) == 0 )
{
e.DrawBackground();
}

// Draw the subitem text in red to highlight it.
e.Graphics.DrawString( e.SubItem.Text,
listView1.Font, Brushes.Red, e.Bounds, sf );

return;
}

// Draw normal text for a subitem with a nonnegative
// or nonnumerical value.
e.DrawText( flags );
}
}

private void ListView1_DrawItem( object sender, DrawListViewItemEventArgs e )
{
if ( ( e.State & ListViewItemStates.Selected ) != 0 )
{
// Draw the background and focus rectangle for a selected item.
e.Graphics.FillRectangle( Brushes.DarkBlue, e.Bounds );
e.DrawFocusRectangle();
}
else
{
// Draw the background for an unselected item.
using ( LinearGradientBrush brush =
new LinearGradientBrush( e.Bounds, Color.DarkBlue,
Color.DarkGreen, LinearGradientMode.Horizontal ) )
{
e.Graphics.FillRectangle( brush, e.Bounds );
}
}

// Draw the item text for views other than the Details view.
if ( listView1.View != View.Details )
{
e.DrawText();
}
}

private void listView1_DrawColumnHeader( object sender, DrawListViewColumnHeaderEventArgs e )
{
var strFormat = new StringFormat();


if ( e.Header.TextAlign == HorizontalAlignment.Center )
strFormat.Alignment = StringAlignment.Center;
else if ( e.Header.TextAlign == HorizontalAlignment.Right )
strFormat.Alignment = StringAlignment.Far;

e.DrawBackground();
e.Graphics.FillRectangle( new SolidBrush( Color.FromArgb( 65, 65, 65 ) ), e.Bounds );
e.Graphics.DrawLine( new Pen( Color.White ), new PointF( e.Bounds.Width + e.Bounds.X - 1, 0 ), new PointF( e.Bounds.Width + e.Bounds.X - 1, e.Bounds.Height ) );
var headerFont = new Font( "Arial", 8, FontStyle.Bold );

e.Graphics.DrawString( e.Header.Text, headerFont, Brushes.White, e.Bounds, strFormat );
}
private void timer1_Tick( object sender, EventArgs e )
{
if ( !backgroundWorker1.IsBusy ) backgroundWorker1.RunWorkerAsync();
}

public class PackThread : IDisposable
{
private bool _frozen = true;

private Task Task { get; set; }
public bool Frozen { get => _frozen; set {
if ( Frozen == value || Done ) return;
if ( value ) Freezing = true;
if ( !value && Task.Status != TaskStatus.Running ) Task.Start();
_frozen = value;
} }
public bool Freezing { get; private set; }
public bool Done { get; private set; } = false;

public FileInfo Video { get; set; }
private DirectoryInfo Raw { get; set; }
private FileInfo RawCompressed { get; set; }
private VideoFileReader VFR { get; set; }
private ZipFile Zip { get; set; }
public ListViewItem Item { get; set; }

public int CurrentFrame { get; private set; }
public long MaxFrames => VFR.FrameCount;
public float Progress => ( ( float ) CurrentFrame ) / MaxFrames * 100;
public float ElementsPerSecond => ElementsPerSeconds.Count > 0 ? ElementsPerSeconds.Average() : 0;
private Buffer<float> ElementsPerSeconds { get; set; } = new Buffer<float>( 10 );
public string TimeLeft => ElementsPerSecond <= 0 ? "infinite" : TimeSpan.FromSeconds( ( MaxFrames - CurrentFrame ) / ElementsPerSecond ).ToString( @"hh\:mm\:ss" );

private static readonly DateTime Jan1st1970 = new DateTime( 1970, 1, 1, 0, 0, 0, DateTimeKind.Utc );

public static long CurrentTimeMillis()
{
return ( long ) ( DateTime.UtcNow - Jan1st1970 ).TotalMilliseconds;
}

public PackThread( FileInfo video )
{
Video = video;
var stripped = Video.FullName.Substring( 0, Video.FullName.Length - Video.Extension.Length );
Raw = new DirectoryInfo( $"{ stripped }.raw" );
RawCompressed = new FileInfo( $"{ stripped }.rawc" );
VFR = new VideoFileReader();
VFR.Open( video.FullName );
Zip = new ZipFile( RawCompressed.FullName );

Task = new Task( () => {
if ( !Raw.Exists ) Raw.Create();
while( true )
{
if ( Frozen )
{
Freezing = false;
return;
}
// Zip.Save( RawCompressed.FullName );
var timestamp = CurrentTimeMillis();
Bitmap bmp = VFR.ReadVideoFrame();
CurrentFrame++;
if ( bmp == null )
{
Zip.Save();
Done = true;
_frozen = true;
return;
}
//var ms = new MemoryStream();
bmp.Save( $"{ Raw.FullName }/{ CurrentFrame }", ImageFormat.Jpeg );
//Zip.AddEntry( CurrentFrame.ToString(), ms );
bmp.Dispose();
var dif = CurrentTimeMillis() - timestamp;
if ( dif != 0 )
{
//ElementsPerSecond = 1000F / dif;
ElementsPerSeconds.Add( 1000F / dif );
}
}
} );
}
public PackThread( string video ) : this( new FileInfo( video ) )
{
}

public void Dispose()
{
// VFR.Dispose();
Zip.Dispose();
}
}

private void backgroundWorker1_DoWork( object sender, DoWorkEventArgs e )
{
if ( PackThreads.Count <= 0 ) return;
var active = 0;
var maxActive = maxActiveThreads.Value;
try
{
foreach ( var thread in PackThreads )
{
listView1.MayInvoke( () => {
for ( var i = thread.Item.SubItems.Count; i < 5; i++ ) thread.Item.SubItems.Add( "" );
thread.Item.SubItems[ 1 ].Text = $"{ thread.Progress.DecimalStrip() } %";
thread.Item.SubItems[ 2 ].Text = $"{ thread.CurrentFrame } / { thread.MaxFrames }";
thread.Item.SubItems[ 3 ].Text = $"{ thread.ElementsPerSecond.DecimalStrip() } items/s";
} );
if ( thread.Done )
{
PackThreads.Remove( thread );
Videos.Remove( thread.Video.FullName );
listView1.MayInvoke( () => thread.Item.SubItems[ 4 ].Text = "Done" );
thread.Dispose();
}
else
{
if ( !thread.Frozen )
{
if ( active < maxActive ) active++;
else thread.Frozen = true;
}
listView1.MayInvoke( () => thread.Item.SubItems[ 4 ].Text = $"{ thread.TimeLeft }" );
}
}
if ( active < maxActive )
{
foreach ( var thread in PackThreads )
{
if ( thread.Frozen && active < maxActive )
{
thread.Frozen = false;
active++;
}
else if ( active >= maxActive ) break;
}
}
} catch ( Exception ex )
{

}
// listView1.MayInvoke( () => listView1.Refresh() );
}

private void button1_Click( object sender, EventArgs e )
{
if ( ofd.ShowDialog() == DialogResult.OK )
{
foreach( var file in ofd.FileNames )
{
var f = new FileInfo( file );
if ( Videos.Contains( f.FullName ) ) continue;
var thread = new PackThread( f );
var lvi = new ListViewItem( f.Name );
thread.Item = lvi;
PackThreads.Add( thread );
listView1.Items.Add( lvi );
Videos.Add( f.FullName );
}
}
}

private void button2_Click( object sender, EventArgs e )
{
foreach( ListViewItem lvi in listView1.SelectedItems )
{
var thread = Find( lvi );
if ( thread == null ) continue;
PackThreads.Remove( thread );
if ( !thread.Frozen ) thread.Frozen = true;
Videos.Remove( thread.Video.FullName );
thread.Dispose();
lvi.SubItems[ 4 ].Text = "Canceled";
}
}

private PackThread Find( ListViewItem lvi )
{
PackThread _thread = null;
foreach( var thread in PackThreads )
{
if ( thread.Item == lvi ) _thread = thread;
}
return _thread;
}

public class Buffer<T> : Queue<T>
{
private int? maxCapacity { get; set; }

public Buffer() { maxCapacity = null; }
public Buffer( int capacity ) { maxCapacity = capacity; }

public void Add( T newElement )
{
if ( this.Count == ( maxCapacity ?? -1 ) ) this.Dequeue(); // no limit if maxCapacity = null
this.Enqueue( newElement );
}
}
}
}

+ 187
- 0
Funscripta/Unpack-Manager.resx Целия файл

@@ -0,0 +1,187 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="backgroundWorker1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>104, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
rkJggg==
</value>
</data>
</root>

+ 8
- 0
Funscripta/packages.config Целия файл

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Accord" version="3.8.2-alpha" targetFramework="net472" />
<package id="Accord.Video" version="3.8.2-alpha" targetFramework="net472" />
<package id="Accord.Video.FFMPEG" version="3.8.2-alpha" targetFramework="net472" />
<package id="Ionic.Zip" version="1.9.1.8" targetFramework="net472" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net472" />
</packages>

Двоични данни
Funscripta/vibrator.ico Целия файл


Loading…
Отказ
Запис