Made it easy for amz to steal SSATool code by adding it to the SVN

Originally committed to SVN as r1345.
This commit is contained in:
Dan Donovan 2007-07-04 01:37:29 +00:00
parent d6e9c3f730
commit 872242a378
44 changed files with 22315 additions and 0 deletions

77
SSATool/AssemblyInfo.cs Normal file
View file

@ -0,0 +1,77 @@
/*
SSATool - A collection of utilities for Advanced Substation Alpha
Copyright (C) 2007 Dan Donovan
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; ONLY under version 2
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System.Reflection;
using System.Runtime.CompilerServices;
//
// 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("SSATool")]
[assembly: AssemblyDescription("A typesetting tool for Advanced Substation Alpha files.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SSATool")]
[assembly: AssemblyCopyright("Dan Donovan")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//
// 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 Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.3.6.0")]
//
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly signing.
//
// Use the attributes below to control which key is used for signing.
//
// Notes:
// (*) If no key is specified, the assembly is not signed.
// (*) KeyName refers to a key that has been installed in the Crypto Service
// Provider (CSP) on your machine. KeyFile refers to a file which contains
// a key.
// (*) If the KeyFile and the KeyName values are both specified, the
// following processing occurs:
// (1) If the KeyName can be found in the CSP, that key is used.
// (2) If the KeyName does not exist and the KeyFile does exist, the key
// in the KeyFile is installed into the CSP and used.
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
// When specifying the KeyFile, the location of the KeyFile should be
// relative to the project output directory which is
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
// located in the project directory, you would specify the AssemblyKeyFile
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile(@"c:\documents and settings\administrator\my documents\visual studio projects\ssatool.snk")]
[assembly: AssemblyKeyName("")]

89
SSATool/Condition.cs Normal file
View file

@ -0,0 +1,89 @@
/*
SSATool - A collection of utilities for Advanced Substation Alpha
Copyright (C) 2007 Dan Donovan
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; ONLY under version 2
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System;
//using System.Collections;
using System.Collections.Generic;
namespace SSATool
{
public class Condition : ICloneable {
public string ConditionOne;
public string ConditionOp;
public string ConditionTwo;
public bool ConditionEnabled;
public Condition() { }
public Condition(string ConditionOne, string ConditionOp, string ConditionTwo, bool ConditionEnabled) {
this.ConditionOne = ConditionOne;
this.ConditionOp = ConditionOp;
this.ConditionTwo = ConditionTwo;
this.ConditionEnabled = ConditionEnabled;
}
public object Clone() {
return this.MemberwiseClone();
}
}
public class ConditionColl {
protected List<Condition> conditionColl;
public ConditionColl() {
conditionColl = new List<Condition>();
}
public int ConditionCount {
get { return conditionColl.Count; }
}
public void AddCondition(string CondOne, string CondOp, string CondTwo) {
Condition newCond = new Condition(CondOne,CondOp,CondTwo,true);
conditionColl.Add(newCond);
}
public void AddCondition(string CondOne, string CondOp, string CondTwo, bool CondEnabled) {
Condition newCond = new Condition();
newCond.ConditionOne = CondOne;
newCond.ConditionOp = CondOp;
newCond.ConditionTwo = CondTwo;
newCond.ConditionEnabled = CondEnabled;
conditionColl.Add(newCond);
}
public void AddCondition(Condition tc) {
conditionColl.Add(tc);
}
public Condition GetCondition(int index) {
return conditionColl[index];
}
public void RemoveCondition(int index) {
if (conditionColl.Count > index) conditionColl.RemoveAt(index);
}
public List<Condition> CloneConditions() {
List<Condition> nl = new List<Condition>();
for(int index=0;index!=conditionColl.Count;index+=1)
nl.Add((Condition)conditionColl[index].Clone());
return nl;
}
}
}

252
SSATool/ConditionDialog.cs Normal file
View file

@ -0,0 +1,252 @@
/*
SSATool - A collection of utilities for Advanced Substation Alpha
Copyright (C) 2007 Dan Donovan
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; ONLY under version 2
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace SSATool
{
/// <summary>
/// Summary description for ConditionDialog.
/// </summary>
public class ConditionDialog : System.Windows.Forms.Form
{
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.ComboBox comboBox1;
private System.Windows.Forms.Button cmdCancel;
private System.Windows.Forms.Button cmdOK;
private System.Windows.Forms.TextBox txtC1;
private System.Windows.Forms.TextBox txtC2;
private System.Windows.Forms.Label lblPrompt;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public ConditionDialog() {
InitializeComponent();
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(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.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.txtC1 = new System.Windows.Forms.TextBox();
this.txtC2 = new System.Windows.Forms.TextBox();
this.lblPrompt = new System.Windows.Forms.Label();
this.comboBox1 = new System.Windows.Forms.ComboBox();
this.cmdCancel = new System.Windows.Forms.Button();
this.cmdOK = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// label1
//
this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
this.label1.Location = new System.Drawing.Point(8, 56);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(128, 20);
this.label1.TabIndex = 6;
this.label1.Text = "Condition One:";
this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// label2
//
this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
this.label2.Location = new System.Drawing.Point(8, 80);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(128, 20);
this.label2.TabIndex = 7;
this.label2.Text = "Condition Two:";
this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// label3
//
this.label3.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
this.label3.Location = new System.Drawing.Point(8, 104);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(128, 20);
this.label3.TabIndex = 8;
this.label3.Text = "Comparison:";
this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// txtC1
//
this.txtC1.Location = new System.Drawing.Point(144, 56);
this.txtC1.Name = "txtC1";
this.txtC1.Size = new System.Drawing.Size(336, 20);
this.txtC1.TabIndex = 0;
this.txtC1.Text = "";
this.txtC1.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.txtC_KeyPress);
//
// txtC2
//
this.txtC2.Location = new System.Drawing.Point(144, 80);
this.txtC2.Name = "txtC2";
this.txtC2.Size = new System.Drawing.Size(336, 20);
this.txtC2.TabIndex = 1;
this.txtC2.Text = "";
this.txtC2.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.txtC_KeyPress);
//
// lblPrompt
//
this.lblPrompt.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
this.lblPrompt.Location = new System.Drawing.Point(0, 8);
this.lblPrompt.Name = "lblPrompt";
this.lblPrompt.Size = new System.Drawing.Size(480, 40);
this.lblPrompt.TabIndex = 5;
//
// comboBox1
//
this.comboBox1.ImeMode = System.Windows.Forms.ImeMode.Off;
this.comboBox1.Items.AddRange(new object[] {
"=",
"==",
"!=",
"!==",
">",
">=",
"<",
"<="});
this.comboBox1.Location = new System.Drawing.Point(144, 104);
this.comboBox1.Name = "comboBox1";
this.comboBox1.Size = new System.Drawing.Size(120, 21);
this.comboBox1.TabIndex = 2;
this.comboBox1.Text = "==";
this.comboBox1.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.comboBox1_KeyPress);
//
// cmdCancel
//
this.cmdCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.cmdCancel.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
this.cmdCancel.Location = new System.Drawing.Point(384, 104);
this.cmdCancel.Name = "cmdCancel";
this.cmdCancel.Size = new System.Drawing.Size(96, 24);
this.cmdCancel.TabIndex = 4;
this.cmdCancel.Text = "Cancel";
//
// cmdOK
//
this.cmdOK.DialogResult = System.Windows.Forms.DialogResult.OK;
this.cmdOK.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
this.cmdOK.Location = new System.Drawing.Point(272, 104);
this.cmdOK.Name = "cmdOK";
this.cmdOK.Size = new System.Drawing.Size(96, 24);
this.cmdOK.TabIndex = 3;
this.cmdOK.Text = "OK";
//
// ConditionDialog
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(488, 135);
this.Controls.Add(this.cmdOK);
this.Controls.Add(this.cmdCancel);
this.Controls.Add(this.comboBox1);
this.Controls.Add(this.lblPrompt);
this.Controls.Add(this.txtC2);
this.Controls.Add(this.txtC1);
this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "ConditionDialog";
this.Text = "ConditionDialog";
this.Load += new System.EventHandler(this.ConditionDialog_Load);
this.ResumeLayout(false);
}
#endregion
private void ConditionDialog_Load(object sender, System.EventArgs e) {
}
public static ConditionDialogResult Show(string prompt, string title, int xpos, int ypos) {
using (ConditionDialog form = new ConditionDialog()) {
form.Text = title;
form.lblPrompt.Text = prompt;
if (xpos >= 0 && ypos >= 0) {
form.StartPosition = FormStartPosition.Manual;
form.Left = xpos;
form.Top = ypos;
}
DialogResult result = form.ShowDialog();
ConditionDialogResult retval = new ConditionDialogResult();
if (result == DialogResult.OK) {
retval.ConditionOne = form.txtC1.Text;
retval.ConditionTwo = form.txtC2.Text;
retval.ConditionComp = form.comboBox1.Text;
retval.OK = true;
}
return retval;
}
}
private void txtC_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) {
if ((e.KeyChar == (char)10) || (e.KeyChar == (char)13)) {
e.Handled = true;
cmdOK.PerformClick();
}
}
private void comboBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) {
e.Handled = true; // We don't want anyone typing here anyway!
if (e.KeyChar == (char)Keys.Enter)
cmdOK.PerformClick();
}
public static ConditionDialogResult Show(string prompt, string title) {
return Show(prompt, title, -1, -1);
}
}
public class ConditionDialogResult {
public string ConditionOne;
public string ConditionTwo;
public string ConditionComp;
public bool OK;
}
}

57
SSATool/DetectEncoding.cs Normal file
View file

@ -0,0 +1,57 @@
/*
SSATool - A collection of utilities for Advanced Substation Alpha
Copyright (C) 2007 Dan Donovan
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; ONLY under version 2
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace SSATool {
public static class DetectEncoding {
// This detection could use some serious improving.
// All detection should return the occurances as an integer.
public static int DetectSJIS(byte[] input) {
int occ=0;
byte lastMatched=0;
byte thisbyte;
for (int index=0;index!=input.Length;index++) {
thisbyte = input[index];
if ((lastMatched==130&&thisbyte>=159&&thisbyte<=241) ||
(lastMatched==131&&thisbyte>=64&&thisbyte<=151)) occ++;
else if (thisbyte==130||thisbyte==131||thisbyte>=136) lastMatched=thisbyte;
else lastMatched=0;
}
return occ;
}
public static int DetectEUCJP(byte[] input) {
int occ=0;
byte lastMatched=0;
byte thisbyte;
for (int index=0;index!=input.Length;index++) {
thisbyte = input[index];
if (lastMatched>=163&&lastMatched<=250&&thisbyte>=160) occ++;
else if (thisbyte>=163&&thisbyte<=250) lastMatched=thisbyte;
else lastMatched=0;
}
return occ;
}
}
}

739
SSATool/Evaluate.cs Normal file
View file

@ -0,0 +1,739 @@
/*
SSATool - A collection of utilities for Advanced Substation Alpha
Copyright (C) 2007 Dan Donovan
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; ONLY under version 2
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
using System.Windows.Forms;
using System.Collections.Generic;
namespace SSATool {
public static class Evaluate {
public static string ScriptParse(string input) {
char[] charain = input.ToCharArray(); // It is over twice as fast to parse this as a character array!
StringBuilder sb = new StringBuilder();
int dIndex = 0, eIndex = 0, pIndex = 0, lastIndex = -1, parenLevel = 0, index;
bool foundds = false;
for (index=0;index<input.Length;index+=1) {
if (charain[index].Equals('$')) {
if (parenLevel == 0) {
if (index != (lastIndex+1))
sb.Append(input, lastIndex+1, index-(lastIndex+1));
dIndex = index;
foundds = true;
}
}
else if (charain[index].Equals('(')) {
if ((parenLevel == 0)) pIndex = index;
parenLevel+=1;
}
else if (charain[index].Equals(')')) {
parenLevel--;
if ((parenLevel == 0) && (foundds) && (pIndex != 0)) {
eIndex = index;
sb.Append(ScriptParse_Helper(input.Substring(dIndex+1, pIndex-(dIndex+1)), ScriptParse(input.Substring(pIndex+1, index-(pIndex+1)))));
lastIndex = eIndex;
foundds = false;
}
else if (parenLevel == 0) {
sb.Append(input.Substring(lastIndex+1, pIndex-lastIndex) + ScriptParse(input.Substring(pIndex+1, index-(pIndex+1))) + ")");
lastIndex = eIndex = index;
}
}
}
if (input.Length > lastIndex) sb.Append(input, lastIndex+1, input.Length-(lastIndex+1));
return sb.ToString();
}
public static string ScriptParse_Helper(string function, string args) {
unsafe {
switch (function) {
case "eval":
return Evaluate.Eval(args).ToString();
case "logic":
return Evaluate.Eval(args).ToString();
case "iif":
string[] tok = args.Split(",".ToCharArray());
if (tok.Length != 3) return "error";
else if (Evaluate.Eval(tok[0]).Equals(true)) return tok[1];
else return tok[2];
case "len":
return args.Length.ToString(Util.nfi);
case "left":
string[] tokl = args.Split(",".ToCharArray());
if ((tokl.Length != 2) || (!Evaluate.isNum(tokl[1]))) return "error";
else try {
return tokl[0].Substring(0, int.Parse(tokl[1], Util.cfi));
} catch {
return "error";
}
case "mid":
string[] tokm = args.Split(",".ToCharArray());
if ((tokm.Length != 3) || (!Evaluate.isNum(tokm[1])) || (!Evaluate.isNum(tokm[2]))) return "error";
else try {
return tokm[0].Substring(int.Parse(tokm[1]), int.Parse(tokm[2], Util.cfi));
} catch {
return "error";
}
case "right":
string[] tokr = args.Split(",".ToCharArray());
if ((tokr.Length != 2) || (!Evaluate.isNum(tokr[1]))) return "error";
else try {
return tokr[0].Substring(tokr[0].Length - int.Parse(tokr[1], Util.cfi), int.Parse(tokr[1], Util.cfi));
} catch {
return "error";
}
case "str":
string[] str = args.Split(",".ToCharArray());
if ((str.Length != 2) || (!Evaluate.isNum(str[1]))) return "error";
else try {
string retstr = String.Empty;
for (int strindex=0;strindex<int.Parse(str[1], Util.cfi);strindex--)
retstr = retstr + str[0];
return retstr;
} catch {
return "error";
}
case "randlist":
string[] splitlist = args.Split(",".ToCharArray());
return splitlist[Evaluate.rand.Next(0, splitlist.Length)];
case "listindex":
string[] splitlist2 = args.Split(",".ToCharArray());
if ((splitlist2.Length < 2) || (Evaluate.isNum(splitlist2[0]) == false)) return "error";
int index = int.Parse(splitlist2[0], Util.cfi);
if ((index < 1) || (index <= splitlist2.Length)) return "error";
return splitlist2[index];
case "listindexwrap":
string[] splitlist3 = args.Split(",".ToCharArray());
if ((splitlist3.Length < 2) || (Evaluate.isNum(splitlist3[0]) == false)) return "error";
int index2 = int.Parse(splitlist3[0], Util.cfi);
if (index2 < 1) return "error";
return splitlist3[index2%splitlist3.Length];
case "listindexlast":
string[] splitlist4 = args.Split(",".ToCharArray());
if ((splitlist4.Length < 2) || (Evaluate.isNum(splitlist4[0]) == false)) return "error";
int index3 = int.Parse(splitlist4[0], Util.cfi);
if (index3 < 1) return "error";
else if (index3 >= splitlist4.Length) return splitlist4[splitlist4.Length-1];
else return splitlist4[index3];
default: // Unrecognized function... Let's treat it as a string.
return "$" + function + "(" + args + ")";
}
}
}
public static readonly Random rand = new Random();
private static SortedList<string, char> ops;
private static SortedList<string, object> constants;
private static void evaluate_stack_tops_function(Stack numStack, Stack<string> funcStack) {
short numParams = (short)numStack.Pop();
string func = funcStack.Pop();
switch (func.ToLowerInvariant()) {
case "rand" :
if (numParams > 2) throw new ArgumentException("Eval.rand");
switch (numParams) {
case 0 :
numStack.Push(rand.Next());
break;
case 1 :
int randOneR = Convert.ToInt32(numStack.Pop());
numStack.Push(rand.Next(randOneR));
break;
case 2 :
int randOne, randTwo;
randTwo = Convert.ToInt32(numStack.Pop(), Util.nfi);
randOne = Convert.ToInt32(numStack.Pop(), Util.nfi);
numStack.Push(rand.Next(randOne,randTwo));
break;
}
break;
case "randf" :
if (numParams > 2) throw new ArgumentException("Eval.randf");
switch (numParams) {
case 0 :
numStack.Push(rand.NextDouble());
break;
case 1 :
double randOneRF = (double)numStack.Pop();
numStack.Push(rand.NextDouble()*randOneRF);
break;
case 2 :
double randOneF, randTwoF;
randTwoF = (double)numStack.Pop();
randOneF = (double)numStack.Pop();
numStack.Push(randOneF + rand.NextDouble()*(randTwoF-randOneF));
break;
}
break;
case "randlist" :
int listindex = rand.Next(0, numParams - 1);
string randlist = string.Empty;
for (int i = 0; i != numParams; i += 1) {
if (i == listindex) randlist = (string)numStack.Pop();
else numStack.Pop();
}
numStack.Push(randlist);
break;
case "round" :
if (numParams != 2) throw new ArgumentException("Eval.round");
double roundme;
int dplaces;
dplaces = Convert.ToInt32(numStack.Pop(), Util.nfi);
roundme = (double) numStack.Pop();
numStack.Push(Math.Round(roundme,dplaces));
break;
case "bound" :
if (numParams != 3) throw new ArgumentException("Eval.bound");
double num, min, max;
max = (double) numStack.Pop();
min = (double) numStack.Pop();
num = (double) numStack.Pop();
num = ((num < min) ? min : num);
num = ((num > max) ? max : num);
numStack.Push(num);
break;
case "max" :
if (numParams < 2) throw new ArgumentException("Eval.max");
double ansMax;
ansMax = Math.Max((double)numStack.Pop(),(double)numStack.Pop());
for(int index=2;index!=numParams;index+=1) {
ansMax = Math.Max(ansMax,(double)numStack.Pop());
}
numStack.Push(ansMax);
break;
case "min" :
if (numParams < 2) throw new ArgumentException("Eval.min");
double ansMin;
ansMin = Math.Min((double)numStack.Pop(),(double)numStack.Pop());
for(int index=2;index!=numParams;index+=1) {
ansMin = Math.Min(ansMin,(double)numStack.Pop());
}
numStack.Push(ansMin);
break;
case "ceil" :
if (numParams != 1) throw new ArgumentException("Eval.ceil");
double ceil;
ceil = (double) numStack.Pop();
numStack.Push(Math.Ceiling(ceil));
break;
case "floor" :
if (numParams != 1) throw new ArgumentException("Eval.floor");
double floor;
floor = (double) numStack.Pop();
numStack.Push(Math.Floor(floor));
break;
case "int" :
if (numParams != 1) throw new ArgumentException("Eval.int");
double thisnum;
thisnum = (double) numStack.Pop();
numStack.Push(Convert.ToInt32(thisnum,Util.nfi));
break;
case "abs" :
if (numParams != 1) throw new ArgumentException("Eval.abs");
double abs;
abs = (double) numStack.Pop();
numStack.Push(Math.Abs(abs));
break;
case "sin" :
if (numParams != 1) throw new ArgumentException("Eval.sin");
double sin;
sin = (double) numStack.Pop();
numStack.Push(Math.Sin(sin));
break;
case "asin" :
if (numParams != 1) throw new ArgumentException("Eval.asin");
double asin;
asin = (double) numStack.Pop();
numStack.Push(Math.Asin(asin));
break;
case "cos" :
if (numParams != 1) throw new ArgumentException("Eval.cos");
double cos;
cos = (double) numStack.Pop();
numStack.Push(Math.Cos(cos));
break;
case "acos" :
if (numParams != 1) throw new ArgumentException("Eval.acos");
double acos;
acos = (double) numStack.Pop();
numStack.Push(Math.Acos(acos));
break;
case "tan" :
if (numParams != 1) throw new ArgumentException("Eval.tan");
double tan;
tan = (double) numStack.Pop();
numStack.Push(Math.Tan(tan));
break;
case "atan" :
if (numParams != 1) throw new ArgumentException("Eval.atan");
double atan;
atan = (double) numStack.Pop();
numStack.Push(Math.Atan(atan));
break;
case "atan2" :
if (numParams != 1) throw new ArgumentException("Eval.atan2");
double atanx,atany;
atanx = (double) numStack.Pop();
atany = (double) numStack.Pop();
numStack.Push(Math.Atan2(atanx,atany));
break;
case "log" :
if (numParams != 1) throw new ArgumentException("Eval.log");
double log;
log = (double) numStack.Pop();
numStack.Push(Math.Log(log));
break;
case "sqrt" :
if (numParams != 1) throw new ArgumentException("Eval.sqrt");
numStack.Push(Math.Sqrt((double)numStack.Pop()));
break;
case "len" :
if (numParams != 1) throw new ArgumentException("Eval.len");
numStack.Push(((string)numStack.Pop()).Length);
break;
case "fact" :
case "factorial" :
if (numParams != 1) throw new ArgumentException("Eval.fact");
numStack.Push(Convert.ToDouble(Factorial(Convert.ToInt32(numStack.Pop(), Util.nfi)), Util.nfi));
break;
case "gcd" :
if (numParams != 2) throw new ArgumentException("Eval.gcd");
numStack.Push(EuclidGCD(Convert.ToInt32(numStack.Pop(), Util.nfi), Convert.ToInt32(numStack.Pop(), Util.nfi)));
break;
case "lcm" :
if (numParams != 2) throw new ArgumentException("Eval.lcm");
int lcm2 = Convert.ToInt32(numStack.Pop(),Util.nfi);
int lcm1 = Convert.ToInt32(numStack.Pop(),Util.nfi);
numStack.Push((lcm1+lcm2)/EuclidGCD(lcm1,lcm2));
break;
default :
if (numParams==1 && numStack.Peek() is string) // might be a string w/o quotes, so push it back on as one
numStack.Push(func+"("+numStack.Pop()+")");
break;
}
}
private static void evaluate_stack_tops(Stack numStack, System.Collections.Generic.Stack<char> opStack, System.Collections.Generic.Stack<string> funcStack, bool safetyKill) {
if (((numStack.Count != 0) || (funcStack.Count != 0)) && (opStack.Count != 0) && (!opStack.Peek().Equals(","))) {
char Operation = opStack.Pop();
if (Operation == '@') { // @ is the placeholder for a function. The function itself is in funcStack.
evaluate_stack_tops_function(numStack, funcStack);
}
else if (Operation == '~') {
object obj = numStack.Pop();
if (obj is bool) numStack.Push(!(bool)obj);
else if (obj is int) numStack.Push(~(int)obj);
else numStack.Push(obj);
}
else if (Operation == '!') {
int fact = Convert.ToInt32(numStack.Pop(), Util.cfi);
numStack.Push(Convert.ToDouble(Factorial(fact), Util.nfi));
}
else if (numStack.Count >= 2) {
object objOne, objTwo;
objTwo = numStack.Pop();
objOne = numStack.Pop();
try {
switch (Operation) {
case 'c': // concatenation
numStack.Push((string)objOne + objTwo.ToString());
break;
case '^': // power
numStack.Push(Math.Pow((double)objOne, (double)objTwo));
break;
case '*': // multiplication
numStack.Push((double)objOne * (double)objTwo);
break;
case '/': // division
numStack.Push((double)objOne / (double)objTwo);
break;
case '%': // modulus
//numStack.Push((int)(double)objOne%(int)(double)objTwo);
numStack.Push(Math.IEEERemainder((double)objOne, (double)objTwo));
break;
case '+': // addition
numStack.Push((double)objOne + (double)objTwo);
break;
case '-': // subtraction
numStack.Push((double)objOne - (double)objTwo);
break;
case '>': // greater than
numStack.Push(doCompare(objOne, objTwo, false) >= 0);
break;
case 'G': // greater than or equal to
numStack.Push(doCompare(objOne, objTwo, false) == 1);
break;
case '<': // less than
numStack.Push(doCompare(objOne, objTwo, false) == -1);
break;
case 'L': // less than or equal to
numStack.Push(doCompare(objOne, objTwo, false) <= 0);
break;
case '=': // case-sensitive equal
numStack.Push(doCompare(objOne, objTwo, false) == 0);
break;
case 'i': // case-insensitive equal
numStack.Push(doCompare(objOne, objTwo, true) == 0);
break;
case 'N': // case-sensitive not equal
numStack.Push(doCompare(objOne, objTwo, false) != 0);
break;
case 'I': // case-insensitive not equal
numStack.Push(doCompare(objOne, objTwo, true) != 0);
break;
case '&': // bitwise-and
numStack.Push((int)objOne & (int)objTwo);
break;
case 'X': // bitwise-xor
numStack.Push((int)objOne ^ (int)objTwo);
break;
case '|': // bitwise-or
numStack.Push((int)objOne | (int)objTwo);
break;
case 'A': // boolean and
numStack.Push((bool)objOne && (bool)objTwo);
break;
case 'O': // boolean or
numStack.Push((bool)objOne || (bool)objTwo);
break;
case 'r': // shift right
numStack.Push((int)objOne >> (int)objTwo);
break;
case 'l': // shift left
numStack.Push((int)objOne << (int)objTwo);
break;
}
} catch { throw new FormatException(); }
}
// Can't make sense of the stacks, so just clear them...
else if (safetyKill) {
funcStack.Clear();
opStack.Clear();
numStack.Clear();
}
}
}
private static int doCompare(object objOne, object objTwo, bool caseIns) {
if (objOne is string || objTwo is string)
return String.Compare(objOne.ToString(), objTwo.ToString(), caseIns);
else if (objOne is bool && objTwo is bool)
return ((bool)objOne).CompareTo((bool)objTwo);
else if (objOne is double && objTwo is double)
return ((double)objOne).CompareTo((double)objTwo);
else if (objOne is bool && objTwo is double)
return ((bool)objOne).CompareTo((double)objTwo!=0.0);
else if (objOne is double && objTwo is bool)
return ((double)objOne!=0.0).CompareTo((bool)objTwo);
/*
else if (objOne is int && objTwo is int)
return ((int)objOne).CompareTo((int)objTwo);
else if (objOne is bool && objTwo is int)
return ((bool)objOne).CompareTo((int)objTwo!=0);
else if (objOne is int && objTwo is bool)
return ((int)objOne!=0).CompareTo((bool)objTwo);
else if (objOne is double && objTwo is int)
return ((double)objOne).CompareTo((double)(int)objTwo);
else if (objOne is int && objTwo is double)
return ((double)(int)objOne).CompareTo((double)objTwo);
*/
throw new ArgumentException("Eval.doCompare");
}
public static bool isNum(string input) {
if (input.Length == 0) return false;
char[] charain = input.ToCharArray();
for (int index=(input.StartsWith("-")?1:0);index<input.Length;index+=1)
if ((!char.IsDigit(charain[index])) && (charain[index] != '.')) return false;
return true;
}
public static int EuclidGCD(int u, int v) {
int k = 0;
if ((u|v)==0) return 0;
while (((u|v)&1)==0) { /* while both u and v are even */
u >>= 1; /* shift u right, dividing it by 2 */
v >>= 1; /* shift v right, dividing it by 2 */
k+=1; /* add a power of 2 to the final result */
}
/* At this point either u or v (or both) is odd */
do {
if ((u & 1) == 0) /* if u is even */
u >>= 1; /* divide u by 2 */
else if ((v & 1) == 0) /* else if v is even */
v >>= 1; /* divide v by 2 */
else if (u >= v) /* u and v are both odd */
u = (u-v) >> 1;
else /* u and v both odd, v > u */
v = (v-u) >> 1;
} while (u > 0);
return v << k; /* returns v * 2^k */
}
public static int Factorial(int x) {
int result=1;
for (int index = x; index != 0; index--) {
result *= index;
}
return result;
}
private static byte opOrder(char tOp) {
byte retVal;
switch (tOp) {
case '!': // factorial
retVal = 20;
break;
case '@': // function
retVal=16;
break;
case ',': // function argument separator
retVal=15;
break;
case 'c': // concatenation
retVal=14;
break;
case '~': // inversion
retVal=13;
break;
case '^': // power
retVal=12;
break;
case '*': // multiplication
case '/': // division
case '%': // modulus
case '\\': // integer division
retVal=11;
break;
case '+': // addition
case '-': // subtraction
retVal=10;
break;
case '>': // greater than
case 'G': // greater than or equal to
case '<': // less than
case 'L': // less than or equal to
retVal=8;
break;
case '=': // case-sensitive equal
case 'i': // case-insensitive equal
case 'N': // case-sensitive not equal
case 'I': // case-insensitive not equal
retVal=7;
break;
case '&': // bitwise-and
retVal=6;
break;
case 'X': // bitwise-xor
retVal=5;
break;
case '|': // bitwise-or
retVal=4;
break;
case 'A': // boolean and
retVal=3;
break;
case 'O': // boolean or
retVal=2;
break;
case 'r': // shift right
case 'l': // shift left
retVal=9;
break;
default: // not an operation
retVal=0;
break;
}
return retVal;
}
public static bool isOp(char i, short pos) {
if (pos==1) return ("!+-*/\\%^&|=<>~".IndexOf(i) != -1);
else if (pos==2) return ("&|^=)".IndexOf(i) != -1);
else if (pos==3) return i=='=';
return false;
}
public static void FillOpsList() {
ops = new SortedList<string, char>(23);
ops.Add(">>", 'r');
ops.Add(">=", 'G');
ops.Add(">", '>');
ops.Add("===", '=');
ops.Add("==", '=');
ops.Add("=", 'i');
ops.Add("<=", 'L');
ops.Add("<<", 'l');
ops.Add("<", '<');
ops.Add("+", '+');
ops.Add("||", 'O');
ops.Add("|", '|');
ops.Add("^^", 'X');
ops.Add("^", '^');
ops.Add("/", '/');
ops.Add("*", '*');
ops.Add("&&", 'A');
ops.Add("&", '&');
ops.Add("%", '%');
ops.Add("-", '-');
ops.Add("!==", 'I');
ops.Add("!=", 'N');
ops.Add("!", '!');
ops.Add("~", '~');
constants = new SortedList<string, object>(6);
constants.Add("e", Math.E);
constants.Add("false",false);
constants.Add("g", 1.6180339887498948482045868);
constants.Add("pi", Math.PI);
constants.Add("true", true);
constants.Add("y", 0.5772156649015328606065120);
}
public static object Eval(string input) {
char[] charain = input.ToCharArray();
Stack<char> opStack = new Stack<char>(16);
Stack numStack = new Stack(16);
Stack<string> funcStack = new Stack<string>(8);
string buff;
int i = 0, pLevel;
char thisOp;
short loop, numParams;
bool lastwasop = true;
bool isnumber, isfloat, infunc, inquotes, unknownString = false;
while (i < charain.Length) {
if (charain[i].Equals('(')) {
pLevel = 1;
buff = string.Empty;
while (pLevel!=0 && ++i<charain.Length) {
if (charain[i].Equals('(')) pLevel+=1;
if (charain[i].Equals(')')) pLevel--;
if (pLevel!=0 || !charain[i].Equals(')')) buff += charain[i];
}
numStack.Push(Eval(buff));
lastwasop = false;
}
else if ((!lastwasop||charain[i]!='-'||(i!=0&&charain[i-1]=='!')) && isOp(charain[i], 1)) {
buff = charain[i].ToString(Util.cfi);
loop=1;
while (++i<charain.Length && loop++<=3 && isOp(charain[i], loop))
buff += charain[i];
i--;
thisOp = ops[buff];
if (!unknownString && thisOp.Equals('+') && numStack.Count!=0 && numStack.Peek() is string) thisOp='c';
while (opStack.Count!=0 && numStack.Count!=0 && opOrder(thisOp)<=opOrder(opStack.Peek()))
evaluate_stack_tops(numStack, opStack, funcStack, false);
opStack.Push(thisOp);
lastwasop=true;
unknownString = false;
}
else if (charain[i] != ' ') {
buff = string.Empty;
if (charain[i].Equals('"')) {
while (i++!=charain.Length && charain[i]!='"')
buff += charain[i];
numStack.Push(buff);
}
else {
isnumber = true;
isfloat = infunc = inquotes = false;
pLevel = numParams = 0;
if (charain[i].Equals('-')) {
buff = "-";
i+=1;
}
while (i!=charain.Length && (!isOp(charain[i], 1) || infunc)) {
if (charain[i].Equals('(')) {
if (pLevel==0) {
funcStack.Push(buff);
buff = string.Empty;
opStack.Push('@');
infunc = true;
}
else buff += '(';
pLevel+=1;
}
else if (infunc && charain[i]==')') {
pLevel--;
if (pLevel==0) {
numStack.Push(Eval(buff));
numParams+=1;
}
else buff += ')';
}
else if (infunc && pLevel==1 && charain[i]==',') {
numStack.Push(Eval(buff));
numParams+=1;
buff = string.Empty;
}
else {
if (inquotes || charain[i]!=' ') {
if (charain[i] == '"') inquotes = !inquotes;
if (!(char.IsDigit(charain[i])||charain[i]=='.')) isnumber = false;
if (charain[i] == '.') isfloat=true;
buff += charain[i];
}
}
i+=1;
}
if (!infunc) {
if (isnumber) {
if (isfloat = true) numStack.Push(double.Parse(buff, Util.cfi)); // effectively disable ints (for now, at least)
else numStack.Push(int.Parse(buff, Util.cfi));
}
else if (constants.ContainsKey(buff.ToLowerInvariant())) numStack.Push(constants[buff.ToLowerInvariant()]);
else {
numStack.Push(buff);
//unknownString = true;
}
}
else numStack.Push(numParams);
i--;
}
lastwasop = false;
}
i+=1;
}
while (opStack.Count!=0 && numStack.Count!=0)
evaluate_stack_tops(numStack, opStack, funcStack, false);
if (numStack.Count != 0) return numStack.Pop();
else return false;
}
}
}

View file

@ -0,0 +1,19 @@
<?xml version="1.0"?>
<PSSA>
<Files />
<Layer Enabled="True" PerSyllable="True" RemoveK="False" AddAll="False" AddOnce="False" DontAddText="False" AddText="True" AddK="True" AddASSA="True" AddClosingBracket="True" Repetitions="1">
<Effect InstanceName="Hide previous" Name="Raw code" Enabled="True">
<Option Name="Code">\1a&amp;HFF&amp;\2a&amp;HFF&amp;\3a&amp;HFF&amp;\4a&amp;HFF&amp;</Option>
<Condition ConditionOne="%karanum%" ConditionTwo="0" ConditionOperation="==" Enabled="True" />
<Condition ConditionOne="%layernumlps%" ConditionTwo="0" ConditionOperation="!=" Enabled="True" />
</Effect>
<Effect InstanceName="Main Code" Name="Raw code" Enabled="True">
<Option Name="Code">\r\t(%karastart%,%karamid%,\fscx50)\t(%karamid%,%karaend%,\fscx100)</Option>
<Condition ConditionOne="%karanum%" ConditionTwo="%layernumlps%" ConditionOperation="==" Enabled="True" />
</Effect>
<Effect InstanceName="Hide next" Name="Raw code" Enabled="True">
<Option Name="Code">\r\1a&amp;HFF&amp;\2a&amp;HFF&amp;\3a&amp;HFF&amp;\4a&amp;HFF&amp;</Option>
<Condition ConditionOne="%karanum%" ConditionTwo="$eval(%layernumlps%+1)" ConditionOperation="==" Enabled="True" />
</Effect>
</Layer>
</PSSA>

View file

@ -0,0 +1,661 @@
<html>
<head>
<title>SSATool Readme</title>
<style type="text/css">
<!--
.header { background: #A0D0FF; border: thin black; margin-top: 0px; margin-bottom: 12px; color: #000000; padding: 6px; text-align: center; margin-left: 0px; margin-right: 0px; }
.box { background: #C0C0C0; border: thin black; color: #000000; width: 75%; border-color: #000000; text-align: left; padding-top: 4px; padding-bottom: 16px; padding-left: 12px; padding-right: 12px; }
.exp { background: #DADADA; border-style: solid; border: thick black; margin-left: 32px; margin-right: 32px; margin-bottom: 24px; line-height: 130%; }
.subinfo { background: #D4D4D4; border: thin black; color: #000000; border-color: #000000; text-align: left; margin-left: 48px; margin-right: 32px; }
#optlist li { list-style-type: square; line-height: 125%; }
#sublist li { list-style-type: circle; line-height: 150%; }
p { text-indent: 32px; }
h3 { text-indent: 10px; }
h4 { text-indent: 10px; }
-->
</style>
</head>
<body>
<center>
<h1>SSATool 4.3</h1><br />
<h2>Purpose</h2>To automate the creation and manipulation of Advanced Substation Alpha files.<br /><br />
<h2>Functions</h2>
<div class="box">
<div class="header">Shifting</div>
<div class="exp">
SSATool can shift a file by entering a time (hour:minutes:seconds.subseconds), by a given number of frames, or by specifying an 'old' time and the new time that it should be shifted to. Shifting by time or frames require a given direction, while time difference already has a direction, given the 2 times.
</div>
<h4>Shifting options</h4>
<div class="subinfo">
<ul id="optlist">
<li>Shift Start/End times: You may choose to only shift the start or end times of each line.</li>
<li>Replace negative times: If you're shifting backwards and some times end up negative, this option will replace them with a 0 time. After all, who wants to see subtitles before you even watch the video?</li>
<ul>
</div>
</div><br /><br />
<div class="box">
<div class="header">Commands</div>
<div class="exp">
These are parameterless functions that don't take much explaining.
</div>
<ul id="sublist">
<li>Strip SSA: Strips all SSA code except for \k,\K,\kf,\ko. Useful for when you want to undo typesetting to a file but keep the timing.</li>
<li>Removes duplicate dialogue lines. If you've got a file that used layer per syllable type karaoke and you strip SSA, you'll have several duplicate lines.</li>
<li>Change last \k based on line length: Goes through dialog lines, and adjusts the length of the last syllable to match the length of the line. It is possible for this value to turn out negative if the timing is way off, so use it with care.</li>
</ul>
</div><br /><br />
<div class="box">
<div class="header">Length-based \k or \K</div>
<div class="exp">
This changes each syllable to \k or \K as determined by a threshold.
</div>
<div class="subinfo">
<ul id="optlist">
<li>Threshold: Anything above or equal to this gets changed to \K and anything under it uses \k.</li>
</ul>
</div>
</div><br /><br />
<div class="box">
<div class="header">Scale Resolution</div>
<div class="exp">
SSATool can change a resolution of a SSA file for you. If you have two different files that you want to merge, but they have different resolutions, then you must use a function like this.
</div>
<h4>Scaling options</h4>
<div class="subinfo">
<ul id="optlist">
<li>Scale factor: Pretty straightforwardly, the amount that you want to scale by.</li>
<li>Scale PlayRes: Scale PlayResX/PlayResY in the header, if they're already there. They must be checked for this to do anything.</li>
</ul>
</div>
<h4>Scaled Parameters</h4>
<div class="subinfo">
<ul id="optlist">
<li>Style lines: Font size, outline, shadow, margins</li>
<li>Dialogue lines: Margin overrides</li>
<li>\bord: using Y scale</li>
<li>\clip: using X and Y scales</li>
<li>\fs: using Y scale</li>
<li>\fsp: using X scale</li>
<li>\move: using X and Y scales</li>
<li>\org: using X and Y scales</li>
<li>\p: Coordinates will be scaled with X and Y scales. If a \p1 is in a \clip, it DOES continue past the clip unless you \p0.</li>
<li>\pbo: using Y scale</li>
<li>\pos: using X and Y scales</li>
<li>\shad: using Y scale</li>
</ul>
</div>
</div><br /><br />
<div class="box">
<div class="header">Lead-in/out</div>
<div class="exp">
This adds a lead-in/out to lines. It can add a \k to the beginning of the line to compensate. It does not current affect other tags like \t, \move, etc.
</div>
<h4>Options</h4>
<div class="subinfo">
<ul id="optlist">
<li>In Time: If checked, this is the amount of lead-in time. If it's a number, it's interpreted as seconds. Else it's interpreted as a timecode.</li>
<li>Out Time: If checked, this is the amount of lead-out time. If it's a number, it's interpreted as seconds. Else it's interpreted as a timecode.</li>
<li>Affect only karaoke lines: Affect only lines with \k in them if checked.</li>
<li>Add empty \k for karaoke: Add a \k to compensate for lead-in time to lines that have \k in them already.</li>
</ul>
</div>
</div><br /><br />
<div class="box">
<div class="header">Gradient Maker</div>
<div class="exp">
This will create a gradient by making several lines using clip. You may type text in, or you may select a line from the loaded file and click "Copy Selected List Item to Input." If the line has dialogue: ... in it (IE the information for the line and not just the line itself), then select that and click the "Move Selected" button next to the "Before Grad." textbox. This will place that text before each line without actually putting it in the gradient. Fill in the boxes and click Create.
</div>
<h3>Options:</h3>
<div class="subinfo">
<ul id="optlist">
<li>Before Gradient: This is text that doesn't get gradiented. Put all the Dialogue: ... stuff here. This is easily accomplished by highlighting the appropriate text in the "Gradient Text" field and clicking the "Move Selected" button.</li>
<li>Clip Lines: How many lines the gradient will span. More lines is more precise.</li>
<li>Start/End Pos: The start and end positions in coordinate form x,y. Only include the part that will increase, IE if you want to go across a 640x480 screen horizontally, only x should be increasing here, and the height of 480 is an offset (it's always there), so leave height 0 here.</li>
<li>Offset: Static values that are added to the second X and Y positions. See the above example, where the offset here would be 0,480.</li>
<li>Start/End Value: The start and end colors in (A)BGR form. They can be in decimal form or in hex form with leading H. Do not include ampersands. Alpha is optional (as denoted by the parenthesis).</li>
<li>Linear/Log/Exp grad: These control how the colors are scaled: linearly, logarithmically, or exponentially (base^ratio). If you use one of the latter two, set the base to something greater than 1.</li>
<li>Turnaround: This will allow you to go from the start value to the end value somewhere in the middle of the gradient, and then back to start RGB. It's a percentage. At 50%, it will turn around at the halfway point.</li>
</ul>
</div>
</div><br /><br />
<div class="box">
<div class="header">Blur</div>
<div class="exp">
This allows you to use layered alpha blurring. Make sure your input does not have a \bord or \pos coordinate in it, unless you're doing a glow, which does allow \pos. Also, if your line has dialogue: ... in it, make sure to select that part of the line and click the "Move Selected" button next to the "Before Blur" textbox.
</div>
<h3>Options:</h3>
<div class="subinfo">
<ul id="optlist">
<li>Before Blur: This is text that doesn't get blurred. Put all the Dialogue: ... stuff here. This is easily accomplished by highlighting the appropriate text in the "Blur Text" field and clicking the "Move Selected" button.</li>
<li>Type: This allows you to select "true blur" or glow. True blur will move the line around with different alpha values given a position of the text. Glow will just leave the text in the same spot while creating subsequently larger borders with more alpha.</li>
<li>Lines: Only used with glow option. Creates the given amount of lines where each line has a larger border than the last.</li>
<li>Start/End alpha: Start and end alpha values. Decimal or hex with leading H. Omit the ampersands.</li>
<li>Blur Radius: How many pixels the blur should be.</li>
<li>Position: Only needed for true blur: The position on the screen where the text is in x,y form. Pixels will be added/subtracted to this value.</li>
<li>Linear/Log/Exp blur: These control how the alpha values are scaled: linearly, logarithmically, or exponentially (base^ratio). If you use one of the latter two, set the base to something greater than 1.</li>
<li>Affect: Will blur the selected elements (\1c, \2c, \3c, and/or \4c). Not applicable to glow.</li>
<li>On subsequent lines...: If not blurred, the elements selected here will have &HFF& alpha values for all lines except the main line.</li>
</ul>
</div>
</div><br /><br />
<div class="box">
<div class="header">Notebox Maker</div>
<div class="exp">
This allows you to easily create cool looking noteboxes from templates contained in the included XML file. Noteboxes can be one or two lines long and each template must specifically give code for each length. See the included file for an example. Templates may be of different resolutions. If a script is loaded which contains PlayResX and/or PlayResY, the generated notebox will be automatically resampled to the script size. Otherwise, the generated notebox will be at the default resolution of the template.
</div>
<h3>Options:</h3>
<div class="subinfo">
<ul id="optlist">
<li>Copy styles to file: The styles for the notebox will not be inserted into your file just by generation of a notebox. You can use this button to insert them automatically in that case.</li>
</ul>
</div>
</div><br /><br />
<div class="box">
<div class="header">Error Checker</div>
<div class="exp">
This will check a file for some common errors. It checks dialogue and style lines.</li>
</div>
<h4>Checks for:</h4>
<div class="subinfo">
<ul id="sublist">
<li>Unopened/unclosed parenthesis</li>
<li>Unopened/unclosed brackets</li>
<li>No trailing ampersand in color/alpha values</li>
<li>Lowercase H for hex</li>
<li>Malformed transformations (\t(time,time)\effect)</li>
<li>Decimals without leading integers (.01 vs. 0.01)</li>
</ul>
</div>
</div><br /><br />
<div class="box">
<div class="header">Font Test</div>
<div class="exp">
This will search a file for all fonts used and check if they are installed on your system. If fonts are not installed, you may search a directory for the fonts. It does not make sure the files it finds have the needed styles. It only matches by font name.
</div>
</div><br /><br />
<div class="box">
<div class="header">Manual Transform</div>
<div class="exp">
How many times have you wished you could use \t on something that doesn't allow it? How many times have you wanted a nonlinear acceleration parameter for \move? Here's a function that will automatically interpolate these things like \t, but it's much more powerful.
</div>
<h3>Zones/the Times Listbox</h3>
<div class="subinfo">
<p>Manual Transform is based on zones, which are made up of a start and end time. There must be at least one zone. Each additional zone uses the end time of the previous zone as its start time. So if you entered the times of 0:00:00.00, 0:01:00.00 and 0:02:00.00, there are two zones: one from 0:00:00.00-0:01:00.00 and one from 0:01.00.00-0:02:00.00.</p>
<p>Based on these different zones, you can have variables which can scale differently at different times. Numbers can scale linearly during one zone and exponentially during another if you like. Text can change between zones.</p>
<p>If this flexibility is not required, just entering a start time and an end time, making one zone only, will keep things simple.</p>
</div>
<h3>Variables</h3>
<div class="subinfo">
<p>This is the data that gets scaled. To add a variable, click the new button and type a name into the popup. You can then edit the values for each time by clicking on the appropriate field in the variable list. You may use either a string or a number. Numbers will be scaled automatically, whereas strings will switch over when a new zone is reached.</p>
<p>If you enter a string and a number under the same variable, then it will treat both as a string. If you have a string and a number and a number (2 zones), it will print the string until it hits the second zone, where it will then scale between the two numbers. That is to say that if, in the current zone, the start and end variable values are both numbers, the number will be scaled; If one or both are non-numbers, both will be treated as strings.</p>
<p>Acceleration: You can use linear, logarithmic or exponential acceleration for each variable and zone. Exponential acceleration has 2 forms: ratio^base, which is specified by just entering a number > 1, or base^ratio by specifying exp<i>base</i> (Example: exp2). Specify a log transform by typing log<i>base</i>. If none of these are specified or are incorrectly entered, a linear transform will be used. ASSA itself uses ratio^base for acceleration, so the default behavior (entering a number) works the same as entering that number into \t.</p>
</div>
<h3>Other options</h3>
<div class="subinfo">
<ul id="optlist">
<li>Code is how SSATool puts the variables together to form the text that gets output. To add the line times, use <b>%starttime%</b> and <b>%endtime%</b> in the code. To use a variable in the code, surround the variable name with percentage signs. You may use scripting functions here. If you're scaling an integer, you're going to want to round it with scripting because it will be printed as a decimal otherwise.</li>
<li>Times: Enter the times for this to span. You must enter at least two times. You may enter more than one time to create different zones where variables can be scaled differently. Times should be the first thing you add.</li>
<li>Frame Rate: The framerate of the video. All entered and output times will be snapped to the nearest frame.</li>
</ul>
</div>
</div><br /><br />
<div class="box">
<div class="header">Kanji timing</div>
<div class="exp">
This function will allow you to time Kanji (or pretty much any other East Asian character set) from Roman letters. You may combine \k times, but this function can't work with \t as it can't be sure how to handle the times. It could also technically be used in reverse, but it's not capable of splitting syllables from the source style.<br /><br />
You must have your two character sets entered in different styles. The kanji may already be timed, but those times will be overridden if so. Empty syllables will be copied alone, or will be combined with the surrounding syllables if those are to be combined.
</div>
<h3>Options</h3>
<div class="subinfo">
<ul id="optlist">
<li>Styles: Select your source and destination styles here. The source style will be used for times and all ASSA code. Destination lines will be overwritten in the list. Note: Any ASSA code appearing before the \k will be directly copied, and ASSA code after the \k is currently not copied at all.</li>
<li>Start: Brings the first lines of each style into the corresponding text fields.</li>
<li>Link: When you have selected corresponding syllables, this will pair them up and you will see them appear in the group list.</li>
<li>Unlink last: If you've made a mistake, this will unlink the last pair. You may use it as many times as needed.</li>
<li>Skip source line: Skip the current source line.</li>
<li>Skip destination line: Skip the current destination line. It won't be modified at all.</li>
<li>Go back a line: Goes back to the last line for both the source and destination. It does not undo any changes made, but you may redo it.</li>
<li>Accept line: When all of the grouping for a line is finished, this will modify the line in the list and automatically load the next lines for source and destination.</li>
</ul>
</div>
<h3>Keyboard shortcuts</h3>
<div class="subinfo">
<div class="subinfo">
Don't use the mouse to highlight grouping. If you incorrectly try to split syllables from the source, the function won't work right, so please use the following keyboard shortcuts while the destination textbox has focus. They're much faster.
</div>
<ul id="optlist">
<li>Right/left arrows: Select more or less text from the destination, respectively.</li>
<li>Up/down arrows: Select more or less text from the source, respectively. The source text is locked so it can not be split, but you may combine syllables from it.</li>
<li>Enter: Link the selected text, or if all text is linked, accept the line and move on to the next.</li>
<li>Backspace: Undo the previous linked text.</li>
</ul>
</div>
</div><br /><br />
<div class="box">
<div class="header">Karaoke effects</div>
<div class="exp">
The karaoke effect generator is a complex karaoke effects automator. In simple terms, it could be called a "\k to \t converter," though it is not limited to transformations. You have several variables (listed below) and scripting functions (listed further below in another section) available to use in template effects. You also have "raw code," which will just dump anything you put in there into the SSA. You can use variables in any of the effect fields. You may use raw code to accomplish anything that the other effects can do. Other effect templates are there just to make it easier for you to make presets. There's an effects editor to add your own presets available under the Effects menu.
</div>
<h3>Layers</h3>
<div class="subinfo">
<p>Layers are the basis of the effects system. They are, in essence, one of the base elements of ASSA itself. The simplest implementation of a layer is a single dialogue line. That's it. The subtitler program reads each line and decides where each line goes, and in what order they go.</p>
<p>However, in SSATool, layers are different than how SSA itself looks at them. A layer is how SSATool processes a line in order to add effects. Depending on the complexity of an effect, it may take from one to several lines to accomplish. That is, you might have two or three or even dozens of dialogue lines composing what we see as one line! So each layer in SSATool will add another dialogue line with the same text but potentially different overrides. But to make things even more confusing, there's an exception: Layer-Per-Syllable. What happens if you want to do something to a syllable in a karaoke as its "turn" comes up, but the command to do what you want to do is a command that affects the whole dialogue line, even if you use \r? You often have to make a dialogue line corresponding to each syllable.</p>
<p>This is what layer-per-syllable does. It will dynamically create a new dialogue line (layer) for each syllable. You're typically going to want to see each line only for the syllable it corresponds to, because that's the basic reason why layer-per-syllable exists. To accomplish that, you're going to want to have a couple of effects in addition to your transformation code. These extra effects will be to make the line invisible except at the corresponding syllable. You'll use conditions (explained below) to apply alpha codes before and after this syllable. A sample layer-per-syllable project file should be bundled to show you how to go about it. Don't use it as a basis every time you want to do layer-per-syllable, because it will ensure that you don't understand how the process works. To make karaoke, you must first understand how ASSA renders karaoke.</p>
<p>To enable layer-per-syllable mode, simply add a layer and make sure the Layer-per-Syllable checkbox is clicked. You may combine layer-per-syllable layers together or with fixed layers if you like.</p>
</div>
<h3>Conditions</h3>
<div class="subinfo">
<p>There are two types of conditions in the karaoke effects generator: effect conditions and layer conditions. They both do the same thing, but they work on a different scope. For both, you enter two things to compare. These things may be numbers or strings, and you may use variables and scripting functions (listed below).</p>
<ul id="optlist">
<br /><li>With effect conditions, each condition must be true for that effect to be applied, or it will just be skipped for that syllable. There is no condition checking for effects on a per-line scope, meaning the conditions are only checked per syllable, not per line. This is the more flexible option of the two.</li>
<br /><li>With layer conditions, each of these must work out for all of the effects in that layer to be applied. By default, if this is not met, there will be no dialogue line created at all. However, when you create your layer conditions, you may option to create the dialogue line WITHOUT effects if the conditions are not met. For fixed layers, the option is called, "Add line unchanged if layer conditions not met." If you're using layer-per-syllable, just that option will add the line several times (once per syllable) if the layer conditions aren't met, so you'll also want to enable the option, "Only add it once."</li>
</ul>
</div>
<h3>Layout</h3>
<div class="subinfo">
<p>The layout of the karaoke effects section can be a little confusing at first. At the left, there's a treeview. This holds information about all layers and effects. You can add a layer via the button under it. Once you have added and selected a layer, you may add effects to it through that button. You may drag items around the treeview to reorder them or to move effects to a different layer. You may duplicate or remove layers or effects through the corresponding buttons.</p>
<p>When you select a layer in the treeview, the layer options page automatically shows up. Here, you can add layer conditions or change the options for the layer. When you click on an effect, you get a tabbed setup where you can view the options for that effect or the conditions. To change an option for an effect, just click on the corresponding field.</p>
</div>
<h3>Options</h3>
<div class="subinfo">
<ul id="optlist">
<li>Don't add the syllable text: This will leave out the actual text for the syllable. You may add it yourself in your effects using the %text% variable. This allows you to split a \k if you like.</li>
<li>Remove \k: This will remove \k, \K, \ko and \kf after applying effects. Keep a backup file before you use this option in case timing needs to be changed later.</li>
<li>Add line unchanged if conditions not met: If layer conditions aren't met, add the dialogue line with no effects. You could get missing dialogue lines without this option.</li>
<li>Only add it once: An extension of the above for layer-per-syllable mode to prevent dialogue lines from being added multiple times when layer conditions are not met.</li>
<li>Layer-per-Syllable: Enable Layer-per-Syllable mode for this layer. See the explanation above.</li>
<li>Repetitions: This only applies to non-LPS layers. The layer will be repeated this amount of times. It only applies to karaoke lines, not regular dialogue lines.</li>
</ul>
</div>
<h3>Karaoke variables</h3>
<div class="subinfo">
<table border="0" cellspacing="8">
<tr>
<td width="150">%karastart%</td>
<td>Start time of current kara block in milliseconds.</td>
</tr><tr>
<td>%karastart[n]%</td>
<td>Start time of kara block <i>n</i> in milliseconds. Yes, the square brackets should be there. You may use other variables in the brackets (except for another variable with brackets). Example: %karastart[%totkaranum%]%</td>
</tr><tr>
<td>%karaend%</td>
<td>End time of current kara block in milliseconds.</td>
</tr><tr>
<td>%karaend[n]%</td>
<td>End time of kara block <i>n</i> in milliseconds. Yes, the square brackets should be there. You may use other variables in the brackets (except for another variable with brackets).</td>
</tr><tr>
<td>%karamid%</td>
<td>Mid point of current kara block in milliseconds. ((start+end)/2)</td>
</tr><tr>
<td>%karalen%</td>
<td>Length of current kara block in milliseconds.</td>
</tr><tr>
<td>%karalen[n]%</td>
<td>Length of kara block n in milliseconds. Yes, the square brackets should be there. You may use other variables in the brackets (except for another variable with brackets.</td>
</tr><tr>
<td>%karanum%</td>
<td>The number of the kara block being evaluated, indexed from 0.</td>
</tr><tr>
<td>%karanumtot%</td>
<td>The total number of kara blocks in this line. If you compare with %karanum%, make sure to add 1 to %karanum% since it starts at 0.</td>
</tr><tr>
<td>%linestart%</td>
<td>Start time of current line in seconds in seconds</td>
</tr><tr>
<td>%lineend%</td>
<td>End time of current line in seconds</td>
</tr><tr>
<td>%linelen%</td>
<td>Length of current line in seconds</td>
</tr><tr>
<td>%layernum%</td>
<td>The current layer number, indexed from 0.</td>
</tr><tr>
<td>%layernumtot%</td>
<td>The total number of layers</td>
</tr><tr>
<td>%layernumlps%</td>
<td>The current layer number in layer-per-syllable mode. In fixed layer mode, this is also also used when repetitions of the layer is set > 1. Indexed from 0.</td>
</tr><tr>
<td>%layernumlpstot%</td>
<td>The total number of layers in layer-per-syllable mode. In fixed layer mode, it is the total number of repetitions of the current layer.</td>
</tr><tr>
<td>%name%</td>
<td>The name (SSA) or actor (ASS) of the line.</td>
</tr><tr>
<td>%style%</td>
<td>The name of the current style</td>
</tr><tr>
<td>%text%</td>
<td>The text inside of the current syllable. Recommended for use with "Don't add the syllable text itself" in the Layer Conditions+Options tab, but can be used by itself.</td>
</tr>
</table>
</div>
</div><br /><br />
<div class="box">
<div class="header">Scripting</div>
<h4>Functions</h4>
<div class="subinfo">
<table border="0" cellspacing="8">
<tr>
<td width="200">$eval(expression)</td>
<td>Does math/logic. It supports the sub-functions listed in the table below. Strings used in this must be surrounded by double quotes. Not using quotes should work in most situations, but this is mostly for reasons of backwards compatibility. If used for logic, it will return True or False (as booleans, so no quotes around them).</td>
</tr><tr>
<td>$iif(expression,t, f)</td>
<td>Inline if (a conditional statement). The expression may be a boolean logic expression, or it may be something that evaluates to true or false. If the expression is True, it returns the second argument. If it's false, it returns the third. If it (or you) messes up, it returns "error".</td>
</tr><tr>
<td>$len(text)</td>
<td>Returns the length of <i>text</i>.</td>
</tr><tr>
<td>$left(text,length)</td>
<td>Returns the first <i>length</i> characters of <i>text</i>.</td>
</tr><tr>
<td>$listindex(n,item,item,...)</td>
<td>Returns the n<super>th</super> supplied item indexed from 1. Returns "error" if the supplied value is incorrect.</td>
</tr><tr>
<td>$listindexlast(item,item,item,...)</td>
<td>Returns the n<super>th</super> supplied item indexed from 1. Returns "error" if the supplied value is less than one. Returns the last value if the index is too big.</td>
</tr><tr>
<td>$listindexwrap(item,item,item,...)</td>
<td>Returns the n<super>th</super> supplied item indexed from 1. Returns "error" if the supplied value is less than one. Wraps around to the beginning of the list if the index is too big.</td>
</tr><tr>
<td>$mid(text,start,length)</td>
<td>Returns <i>length</i> characters of <i>text</i>, starting at <i>start</i>. The first character is indexed as 0.</td>
</tr><tr>
<td>$randlist(item,item,item,...)</td>
<td>Returns a random item from the given inputs.</td>
</tr><tr>
<td>$right(text,length)</td>
<td>Returns the last <i>length</i> characters of <i>text</i>.</td>
</tr><tr>
<td>$str(text,n)</td>
<td>Repeats <i>text</i> <i>n</i> times.</td>
</tr>
</table>
</div>
<br /><br />
<h4>Eval Sub-Functions</h4>
<div class="subinfo">
<table border="0" cellspacing="8">
<tr>
<td width="200">abs</td>
<td>Return the absolute value of a number.</td>
</tr><tr>
<td>acos</td>
<td>Returns the arc-cosine of a number.</td>
</tr><tr>
<td>asin</td>
<td>Returns the arc-sin of a number.</td>
</tr><tr>
<td>atan</td>
<td>Returns the arc-tangent of a number given an angle.</td>
</tr><tr>
<td>atan2</td>
<td>Returns the arc-tangent of a coordinate. Format: atan2(x,y)</td>
</tr><tr>
<td>bound</td>
<td>Bounds a number between 2 values. Takes 3 parameters: Number, LBound, UBound. Returns LBound if Number < LBound, or UBound if Number > UBound. Otherwise returns Number.</td>
</tr><tr>
<td>ceil</td>
<td>Rounds up. Example: ceil(5.01) returns 6</td>
</tr><tr>
<td>cos</td>
<td>Return the cosine of a number.</td>
</tr><tr>
<td>fact</td>
<td>Computes the factorial of an integer. This is the same as the ! operator.</td>
</tr><tr>
<td>floor</td>
<td>Rounds down. Example: floor(5.99) returns 5. floor(-5.99) returns -6.</td>
</tr><tr>
<td>int</td>
<td>Returns the integer of a number. int(-5.99) returns -5.</td>
</tr><tr>
<td>len</td>
<td>Returns the length of a string.</td>
</tr><tr>
<td>log</td>
<td>Return the log of a number. It's base e. If you want a different base, do log(number)/log(base)</td>
</tr><tr>
<td>max</td>
<td>Return the higher of 2 numbers.</td>
</tr><tr>
<td>min</td>
<td>Return the lower of 2 numbers.</td>
</tr><tr>
<td>rand</td>
<td>Returns a bounded random integer. rand() gives you an integer from 0 to 1, rand(maxvalue) gives an integerfrom 0 to maxvalue, and rand(low,high) from low to high</td>
</tr><tr>
<td>randf
<td>Returns a bounded double precision floating point number. randf() gives you a double from 0 to 1, randf(maxvalue) gives a double from 0 to maxvalue, and randf(low,high) from low to high</td>
</tr><tr>
<td>round</td>
<td>Rounds a number to the given number of decimal places. Format: round(number,decimal places)</td>
</tr><tr>
<td>sin</td>
<td>Return the sin of a number.</td>
</tr><tr>
<td>sqrt</td>
<td>Return the square root of a number.</td>
</tr><tr>
<td>tan</td>
<td>Return the tangent of a number.</td>
</tr>
</table><br />
Take note that these do NOT have a leading $ like the above functions. They must be used INSIDE of $eval.
</div>
<br /><br />
<h4>Data types supported by eval</h4>
<div class="subinfo">
<table border="0" cellspacing="8">
<tr>
<td>Boolean</td>
<td>true or false. Capitalization does not matter. Do not enclose in quotes.</td>
</tr><tr>
<td width="60">Integer</td>
<td>Support not done, numbers currently treated as double. All mathematical/bitwise operations are available.</td>
</tr><tr>
<td>Double</td>
<td>Double-precision floating point number. All mathematical operations except modulus are available.</td>
</tr><tr>
<td>Point</td>
<td>An x,y pair. You may add or subtract points, or you may add, subtract, multiply or divide points by scalars. Not finished.</td>
</tr><tr>
<td>String</td>
<td>A string. + may be used to concatenate strings. All strings MUST be enclosed by quotes.</td>
</tr>
</table><br />
Boolean logic comparisons are available with all types. Also, note that conditions in the karaoke effects tool internally use $eval, so strings must be enclosed in quotes in there. Variables that are strings currently do NOT automatically do so.
</div>
<br /><br />
<h4>Constants supported by eval</h4>
<div class="subinfo">
<table border="0" cellspacing="8">
<tr>
<td>e</td>
<td>e, the natural logarithmic base.</td>
</tr><tr>
<td width="60">g</td>
<td>The golden ratio.</td>
</tr><tr>
<td>Pi</td>
<td>Pi.</td>
</tr><tr>
<td>y</td>
<td>Euler's constant.</td>
</tr>
</table><br />
All numerical constants are double precision (64-bit) floating points.
</div>
<br /><br />
<h4>Mathematical/Bitwise operators</h4>
<div class="subinfo">
<table border="0" cellspacing="8">
<tr>
<td width="60">+</td>
<td>Add</td>
</tr><tr>
<td>-</td>
<td>Subtract</td>
</tr><tr>
<td>*</td>
<td>Multiply</td>
</tr><tr>
<td>/</td>
<td>Divide</td>
</tr><tr>
<td>!</td>
<td>Factorial</td>
</tr><tr>
<td>%</td>
<td>Modulus (remainder after integer division)</td>
</tr><tr>
<td>&</td>
<td>Bitwise and</td>
</tr><tr>
<td>\</td>
<td>Bitwise or</td>
</tr><tr>
<td>\</td>
<td>Bitwise xor</td>
</tr><tr>
<td>&lt;&lt;</td>
<td>Shift left</td>
</tr><tr>
<td>&gt;&gt;</td>
<td>Shift right</td>
</tr><tr>
<td>~</td>
<td>Inversion</td>
</tr>
</table>
</div>
<br /><br />
<h4>Boolean/comparison operators</h4>
<div class="subinfo">
<table border="0" cellspacing="8">
<tr>
<td width="60">=</td>
<td>Equal to (if used with text, is case insensitive)</td>
</tr><tr>
<td>&lt;&gt;</td>
<td>Equal to (if used with text, is case sensitive)</td>
</tr><tr>
<td>==</td>
<td>Equal to (if used with text, is case sensitive)</td>
</tr><tr>
<td>!=</td>
<td>Not equal to (if used with text, is case insensitive)</td>
</tr><tr>
<td>!=</td>
<td>Not equal to (if used with text, is case sensitive)</td>
</tr><tr>
<td>&gt;</td>
<td>Greater than</td>
</tr><tr>
<td>&gt;=</td>
<td>Greater than or equal to</td>
</tr><tr>
<td>&lt;</td>
<td>Less than</td>
</tr><tr>
<td>&lt;=</td>
<td>Less than or equal to</td>
</tr><tr>
<td>||</td>
<td>Boolean or</td>
</tr><tr>
<td>&&</td>
<td>Boolean and</td>
</tr>
</table>
</div>
</div><br /><br />
<div class="box">
<div class="header">Effect and project files</div>
<h3>Effect files</h3>
<div class="subinfo">
Effect files are XML files that hold all preset effects except for "raw code," which is built in. They use the extension exml. You may edit them in a text editor by using the bundled effects as a template. There's also an effects editor in the program to write them for you.
</div><br />
<h3>Project files</h3>
<div class="subinfo">
Project files are also XML files, but they are in a different format than the effect files. They contain all layer, filter and condition information as well as the filename to the loaded SSA, if applicable. They are not a script - they do not keep track of your commands, but merely karaoke effects information. They may be edited in a text editor, but I only recommend doing that if you want to make a slight modification to an existing file.
</div>
</div><br /><br />
<div class="box">
<div class="header">File Encoding</div>
SSATool will open most common file encodings including ANSI (using your local codepage), Shift-JIS, and Unicode in 1, 2, or 4 octet versions. Some encodings, such as Shift-JIS are notoriously hard to detect, so if your file includes Japanese text and you're unsure of the encoding, please make sure to find out, or that it displays correctly if you use the open file option without the SJIS.<br /><br />
As of version 4.1, SSATool employs extremely simple algorithms for attempting to detect Shift-JIS and EUC-JP. If a file is under 4KB, 100 or more characters detected with either encoding will trigger a prompt asking to reload using that encoding. If the file is 4KB-8KB, the threshold is 300, and if the file is 8KB or more, 600.
</div><br /><br />
<div class="box">
<div class="header">Thanks</div>
The following are people I want to thank for helping me with this, be that by testing, lending me webspace, putting up educational code samples on the web, etc. Some will be in names, and others will be in online nicknames.<br />
<div class="subinfo">
<ul>
<li>DeathWolf - testing, feature suggestions, webspace</li>
<li>Neil Davidson - the <a href="http://www.codeproject.com/csharp/GetSaveFileName.asp?print=true">save file dialog w/ encoding</a> I'm using</li>
<li>PovRayMan - icon</li>
<li>SCR512 - testing</li>
<li>zalas - feature suggestions</li>
<li>Dead-Cow - testing</li>
<li>Nikolai - testing, feature suggestions</li>
<li>Anyone else I forgot</li>
</ul>
</div>
</div><br /><br />
SSATool is copyright (C) 2005-2006 Dan Donovan. It is free to use.
</center>
</body>
</html>

View file

@ -0,0 +1,492 @@
4.3.6
-Fix saving a project file with default layer names not showing any names when loading the file again
-Fix small bug loading v5/6 scripts
4.3.5
-Truetype Collection (TTC) font files are supported in the font finder
-Factorial should work now
-More optimizations/cleanups
4.3.4
-Fixed/tweaked some UI stuff
-More resize code added
-Fixed double click in error list
-Optimized some stuff
-All karaoke variables now index from 0, not 1. This will break backwards compatibility with some karaoke, but it has never been consistent, so I am changing it.
-Fixed %karamid%
4.3.3
-A bunch of fixes for noteboxes
-Don't bother to scale resolution if the factor is 1:1
4.3.2
-Workaround for crash when line is 259 characters long
-Workaround to prevent splitter from stealing focus on resize (by design, MS? What were you thinking?)
-Fix in default notebox template
4.3.1
-Search/replace now affects everything as it used to
-Unparsable dialogue/style lines are now parsed as strings, displayed with green background
-Changing time precision or running search/replace refreshes the list automatically
4.3.0.2
-Fixed karaoke condition buttons
4.3.0
-Added notebox generator, see readme
-List and utility panel are now resizable panes
-Fixed a bug in resolution scaling
-Fixed error checker crash
-Fixed kanji timing crash
4.2.0.10
-Fixed strip SSA leaving off the last syllable
4.2.0.9
-Fixed a bunch of functions that did nothing
4.2.0.8
-Gradient fixes
-Make screen update when you copy text from gradient/blur/etc to it, and don't copy text backwards
4.2.0.7
-v6 script support improved
-Fix so that you can do both lead-in and lead-out
-A bunch of UI crashes from 4.2.0 fixed
4.2.0.6
-Timecodes may now be unapplied
4.2.0
-Lead no longer makes the list backwards
-Undo/redo optimized and now support adding/removing lines
-Fixed styles
-Optimizations, including overall memory usage
-Fixed lead and remove duplicate lines
-Reading negative times supported
-Other misc fixes, mostly UI-related
-Some Math constants added to $eval, see readme
-Boolean inversion is now denoted as ~ as opposed to ! in $eval
-Added LCM and GCD to $eval
-Fix loading some files through command line
-Fix to reading ARGB colors
-Timecode transform added
-Double clicking a line in the list will bring up the modify line dialogue box
-Bold, Italic, etc. now specified as -1 (instead of 1) as per specs. Parsing will work correctly with either.
4.1.0
-V6 scripts (AKA V4++) supported
-Fixed a bug with %layernum% when you have disabled layers
-Undo/redo added
-Fixed a couple of bugs with kanji timing
-Effects files now use .exml extension. Old files may be renamed.
-Manual transform times are now displayed in the listbox as entered, but are snapped internally to be between frames.
-Conditions may now be edited directly instead of removing/readding
-Completely rewritten script engine combining $logic and $eval
-Workaround to prevent resaving UTF-16 files as UTF-8 by default
-You may now edit the names for karaoke layers and effects.
-Error checker now looks for decimals without leading integers (.1 vs 0.1)
-Rudamentary SJIS/EUC-JP detection
-Fixes to gradient maker
-Lots of general optimizations and other internal code changes
-Put layer condition checking back to per line instead of per syllable, as it should be
-Added karaoke syllable-per-line mode
4.0.0
-Resolution scaling now has separate scale parameters for X and Y, no longer affects all lines, and no longer crashes
-FPS is now a global parameter
-Added option for ms precision. A modified VSFilter is required for it to work.
-Lead-in/out now affect \t and \move
-Karaoke layer options layed out a little differently
-Added kanji timing
-Fixed a possible crash with karaoke effects for short lines
-Fixed trying to save a project file as ANSI
-Various interface tweaks
3.7.3
-Fixed %text% for syllables with no text
-Fixed logic with non-number, non-digit characters, such as space.
3.7.2
-Fixed $iif when a condition is false
-Fix crash trying to remove an item in the karaoke tree when nothing is selected
-Adding an effect to the karaoke tree selects it automatically
-Added $str, see readme
-Fixed one layer being disabled affecting all layers below it
-Fixed one effect having unmet conditions disabling all effects below it
3.7.1
-Added lead-in/out. It does not yet correct for \t, \move, etc.
3.7.0
-Converting to C# 2.0. Filesize is much smaller. New bugs may be introduced.
-Fixed bug loading project files where layers didn't specify repetitions.
3.6.0
-Added repetitions to karaoke effects. See readme.
-Removing effects should work better now.
-$logic should correctly interpret strings with numbers
3.5.0
-Programming structure improved
-Random tweaks here and there
-Fixed cloning (copying effects, duplicating layers) in many cases
-Select first karaoke effects layer (if there is one) when loading a project
-Added manual transform. See readme.
-Improved precision of shifting by frame. Start times are now always rounded down (floor), while end times are rounded up (ceil)
-Changed interface for karaoke effects to use a treeview for layers and effects
-Fixed a bunch of eval functions
-Font names can now contain anything except \ or }
-Fix parameter order for $eval(round)
3.2.5
-Script parser should handle parenthesis better now.
-Made $eval play nicer with decimals
-(hopefully) fixed one parameter functions for $eval
-$eval should bail and return String.Empty if it can't make sense of the data it's given
-Added sqrt() to $eval (or you can still do ^0.5)
-Fixed =/== in $evallogic/$iif
-Strings in $evallogic/$iif no longer are expected to be in quotes
3.2.4
-Fixed <, <=, >, >=
3.2.3
-Fixed a few bugs with writing XML Project files
-Fixed a bug when loading an XML project file that options would become confused between filters with multiple instances
-Fixed a couple of bugs that rendered effect conditions pretty much useless
-%layernum% and %layernumlps% now index from 1, not 0
-Pressing enter in the condition dialog box will click OK automatically
3.2.2
-The selected line information now properly moves when the form is resized.
3.2.1
-You can now load files (except effects files) through the command line (do "Open With" in Explorer)
3.2.0
-Karaoke effects generator can now allow you to edit the actual text for each syllable by setting "don't add the syllable text itself" in Layer Conditions+Options and using %text%.
-Length-based \k / \K fixed again
3.1.0
-Select/Deselect Line Range now accept the last line number (IE if you have a 10 line file, 1-10 works now)
-Slight optimization to how effects are created
-Blur now only has two types: true blur and glow. However, it is more powerful than before. See the readme for more.
-Blur no longer adds an empty line at the end
-Exponential blur no longer disregards BlurStart for the center line.
-Gradient now accepts a parameter called mirror. See the readme, but know that leaving it at 100 (%) will act the same as it used to.
-Added $listindex, $listindexwrap, $listindexlast functions
3.0.3 (3.0.2019.28843)
-Adding the same effect multiple times no longer mixes up the options between them.
-Fixed length-based \k / \K
3.0.2 (3.0.2017.31380)
-Offset in gradient maker now only affects the second X,Y pair in \clip
3.0.1 (3.0.2017.27737)
-Detecting unclosed parenthesis/brackets at the end of the line now works.
3.0 (3.0.2017.5108)
-Added $len, $left, $mid, $right
-Slight optimizations in $iif
-Added select/deselect line range to list menu. If you don't know the line numbers, click on the lines and use the go to line option and it'll show the current line.
-Made go to line show the selected line number by default and added a label to show this as well
-Optimizations to shifting and length based \k-\K
-Fixed strip SSA
-Fixed linear glow type blur accuracy
-Error checker will now report unclosed ampersands in \alpha, \2c, \2a, \3c, \3a, \4c, \4a
-Error checker will now report lowercase hex markers in \alpha
3.0 beta 6 (3.0.1975.5261)
-Fixed shifting if your file is 10 hours or more
-Fixed font check sometimes adding fonts more than once
-Workaround for looking for vertical fonts (@fonts). It will just omit the @. It doesn't check if the font is actually capable of being vertical.
-Added ability to search for fonts that aren't installed in a directory
-Saving as UTF-8 fixed
3.0 beta 5 (3.0.1958.3274)
-Fixed shifting cutting off part of the line in many cases.
3.0 beta 4
-Made form resizable
-Made default (and minimum) form width 1024 for those people using 1024x768
-Fixed logarithmic glow blur alpha values
-Fixed logarithmic and exponential gradient values when using a start color > 0
-Added font checker. Make good use of it. I know I will.
3.0 beta 3
-Fixed some menu options that weren't doing anything
-Double clicking on a line in error checking now takes you to the line in question. Also added a couple of checks for style lines.
-Added a layered blur option.
-Added option to do logarithmic and exponential gradients.
-Removed messagebox popping up with $iif
-Added some more error checks for various functions (not talking about the error checker, but when you enter invalid parameters to functions)
3.0 beta 2 (3.0.1948.40271)
-Also check for colors/alpha with lowercase hex codes (including the H) and also where there is not a trailing ampersand
-Scale PlayResX and PlayResY too
-Fixed eval
-Added the "list" menu with some useful list functions
-Performance increases in scripting/eval/evallogic. Thanks to DeathWolf for helping with this.
-Fixed effect conditions
3.0 beta 1 (3.0.1948.26940)
-Complete rewrite of application using C# 1.1, so you now need .NET to run it. Speed increases and GUI improvements result.
-Variables have changed formats. See readme.
-Scripting language is much different. See readme.
-Project files and effects list files both use XML now. They are not backwards compatible.
-Program supports basically all normal encodings, including UTF-16 (Unicode) that previous versions didn't.
-Gradient maker can do \1c, \2c, \3c, \4c (user selectable) and can handle RGBA (in ARGB order) and decimal input
-Resolution scaling now scales a lot more stuff. See readme.
--Old versions--
2.0.161
-Even bigger speedup
-Completely rewrote effects procedure, kept the old one as it may be buggy, as usual
-Made after 3.0 for those looking to avoid .Net (bad choice though)
2.0.158
-HUGE speedup
-Will no longer affect non-karaoke dialog lines
-Probably buggy
-Made after 3.0 for those looking to avoid .Net (bad choice though)
2.0.157
-More bugfixes and speedups
2.0.154
-More bugfixes
-Layer-per-syllable and fixed layer modes may be combined
-New variables dealing with layers: $layernumtot$, $layernumlps$, $layernumlpstot$. If you have a "legacy" layer-per-syllable file, open the PSSA in Notepad and add PerSyllable=True. When using $layernum$ for layer-per-syllable, you must now use $layernumlps$.
1.6.153
-Fixed several bugs introduced in the last release
-More speedups
-Added $style$ variable (see readme)
-Added ability to resize the program
1.5.152
-Fixed $iif with more than one comparison
-Some other random bugfixes
-There should be a minor speedup all around, but I don't know if it'll be noticeable
1.5.151
-Added ability to insert a gradient into a file without replacing a line
1.5.150
-A small bugfix in the gradient maker. Not sure if it even affected anything.
1.5.149
-Added some more to gradient maker
-New HTML readme
1.5.146
-Added a bunch of stuff to gradient maker, such as copying to/from the SSA file and automatically adding text before and after the line.
-Gradient maker no longer adds 1 extra line
1.4.145
-Another fix
1.4.144
-Fixed a gradient maker problem having to do with some parts of it being unfinished and disabled.
1.4.143
-More gradient maker work
-Added $randlist
1.3.142
-Started to implement a gradient maker. It's not done and what is done is experimental.
1.2.141
-New version scheme, actually using minor (and eventually major) version numbers instead of just build numbers.
-Added ability to change font in Listbox, including encoding.
1.1.140
-Fixed strip SSA, it should no longer strip numbers after \kf.
1.1.139
-Added: \k or \K depending on the length of the syllable
-Fixed a little big with scaling where it would try to work on lines it shouldn't be (though it shouldn't have messed anything up)
1.1.138
-Added: SSA Resolution Scaling. Use at your own risk.
-Removed: Old load/save projects
-Removed: Old add effects procedure.
1.1.137
-Fixed: Shifting now correctly abides the lines being checked/unchecked
1.1.136
-Some minor interface tweaks
-Added 'Move Down' for effects
1.1.135
-Restructured/cleaned up the code for adding karaoke effects. The old code will be left in for a little while until I can be sure there are no bugs in the new code. Please try the new code, but make sure you save before doing so.
1.1.134
-Fixed: Reparsing styles (made typo last build)
1.1.133
-Fixed: Read ASS Styles reparsing (also made slightly faster)
1.1.132
-Fixed: Read ASS Styles ([v4+ styles]) correctly.
1.1.131
-Fixed: Layer conditions and effect count were, in certain conditions, obtained from the wrong layer. This has been (hopefully) corrected.
1.1.130
-Fixed shifting...
1.1.129
-Fixed (I don't know): Shifting............. last time? Nah...
1.1.128
-Fixed (probably): Shifting... again. Should be accurate and not crash.
1.1.127
-Fixed (maybe): Shifting should be more accurate.
1.1.126
-Fixed: Effect condition checkboxes now correctly show as checked/unchecked when the condition is active/inactive as opposed to always being checked.
-Fixed: Layer condition checkboxes now correctly show as checked/unchecked when the condition is active/inactive as opposed to always being checked.
-Fixed: Effect conditions should no longer crash when loading a project.
-Fixed: Layer conditions should now correctly load as layer conditions instead of effect conditions when loading a project.
1.1.125
-Added: $lastkaranzkstart$
-Fixed: Trying to move/copy an effect when there are no effects no longer creates a blank effect.
1.1.124
-Fixed effects list not being correctly loaded if you open a SSA/ASS/PSSA from the command line.
1.1.123
-Added ability to load SSA/ASS and PSSA (project files) from command line. You can now associate SSATool with SSA, ASS and/or PSSA files and it will open them.
1.1.122
-Effects can now use variables in the code line and not just the options lines. If you don't know what this means, don't worry about it.
1.1.121
-Forgot to comment out some code before hitting compile in last version that made load project crash. Fixed.
-Added script tracing in the help tab... Every call to the script parser adds a line to the listbox. It will be at least 2 lines per script call.
1.1.120
-Fixed bug in $calc where a negative as the first number would not be recognized.
-Fixed: Trying to delete a layer when there are no layers no longer crashes.
-Fixed: Trying to delete an effect condition when there are no effect conditions no longer crashes.
-Fixes to load project
1.1.119
-Fixed: Shifting by difference now works in both directions.
-Fixed: Shifting bug introduced last version for times w/o decimals hopefully fixed.
-Improvement: Times are now stored as double precision instead of single precision.
1.1.118
-Fixed: Trying to save in various situations as opposed to save as no longer results in a crash
-Fixed: $rand no longer returns 0 or gives type mismatch crashes
-Fixed: Trying to move an effect up when there is no effect to move up no longer results in a crash
-Fixed: Copying or moving an effect to another layer now includes the conditons.
-Fixed: Shifting times should no longer mess up if a time has a decimal >= .995 (which was rounded as 1.0 before, screwing things up)
1.1.117
-Fixed: Scripting should now properly support recursion.
1.1.116
-Fixed bug where closing the program did not unload it from memory.
-Fixed select/deselect all styles.
1.1.115
-Added script functions: and, nand, or, nor, not, xor
-Added operator info to readme
-Added script testing/debugging in the help tab. This is mostly for me, but you may test your own logic on it if you like.
1.1.114
-Fix stupid typo in new load project. Effects should correctly load now...
1.1.113
-Fixed new project format to actually attempt to load the SSA file itself
-Added a progress popup w/ cancel option for karaoke effects
-Added list of variables to readme
1.1.112
-New project format. Please only use the old format if you find bugs in the new one.
-Added time shifting by difference.
1.1.111
-Make multicharacter comparisons (!=, <>, etc) work correctly
-Fixed saving a ssa file without the extension causing a crash. Really this time.
1.1.110
-Changed to common dialog for open/save
-Added version number to form title
-Minor code cleanup, slightly smaller file
1.1.109
-Removed preview in the open box because it was causing problems for some computers.
-Fixed saving a ssa file without the extension causing a crash.
-Added remove duplicate dialog lines option-Useful for when stripping a multilayer SSA leaves you with duplicate lines.
-Added tooltips for a few things.
1.1.108
-Minor tweaks in open/save windows
-Fixed major multilayering bug introduced in build 105.
1.1.107
-Fix (allow) removal of effect conditions.
1.1.106
-Fix checkmarks in layer conditions tab.
1.1.105
-Remove limit of 100 layers
-Fixed condition checking
-Saving/loading project now also saves conditions.
-Added "layer per syllable" mode
-Added ability to not add layers to the output if the conditions are not met (as opposed to adding the line unchanged)
-Added "Invert Line Selection" for the SSA list.
1.1.104
-Changed name to SSATool.
-Changed the UI around.
-Fixed: $iif should now work correctly when comparing numbers, as opposed to comparing them as strings
-Added ability to define custom conditions specifying when each layer and each filter are used.
-Added variable $karanumtot$ to tell how many syllables are on the line.
1.0.103
-Added ability to effect only certain lines.
-Added option to shift only start/end times.
1.0.102
-Changed format of effects file and project files to get around some delimiting issues and to make more readable if you open them in a text editor.
-Changed extension of project file to .pssa to get around a VB quirk (*.aas would also return .aasp files)
-Added scripting functions: bound, round, int, sin, cos, tan, log, exp, abs
-Calc now supports parenthesis and uses the order of operations instead of left-to-right processing.
-Fixed floor behavior
1.0.101
-Made copy/move to layer work again.
-Added scripting functions: ceil, floor. math is now a synonym for calc.
1.0.100
-Implemented simple inline scripting. Supported functions: iif, rand, randf (floating), calc (math)
-Added variable $layernum$
1.0.99
-Fixed bug with enabling/disabling filters
-Implemented save/load project, does not save layer conditions yet
-Fixed saving effects list
-Speedups
1.0.98
-Finished implementing the effects editor.
1.0.97
-The default style may now be effected. SSA by default calls Default *Default in your lines, which was screwing up the comparison.
-Time shifting now correctly rounds decimals insdtead of giving you several numbers as an exponential.
-Stripping a SSA will now copy lines which have unselected styles instead of leaving them out.

View file

@ -0,0 +1,17 @@
<?xml version="1.0"?>
<ESSA>
<Effect Name="Transformation" Code="\t($Start Time$,$End Time$,$Acceleration$,$Code$)">
<Option Name="Start Time">%karastart%</Option>
<Option Name="End Time">%karaend%</Option>
<Option Name="Acceleration">1</Option>
<Option Name="Code"></Option>
</Effect>
<Effect Name="Move" Code="\move($Start X$,$Start Y$,$End X$,$End Y$,$Start Time$,$End Time$)">
<Option Name="Start X"></Option>
<Option Name="Start Y"></Option>
<Option Name="End X"></Option>
<Option Name="End Y"></Option>
<Option Name="Start Time">0</Option>
<Option Name="End Time">$eval(%linelen%*1000)</Option>
</Effect>
</ESSA>

View file

@ -0,0 +1,67 @@
<?xml version="1.0"?>
<NSSA>
<Note name="getfresh v4" author="getfresh" desc="Notebox by getfresh. Start a little early and end a little late as it fades+scrolls in." resx="1024" resy="768">
<Styles version="5">
<Style>Style: NoteBOX1,Arial,29,&amp;HFFD6AE85,&amp;HFFFFFFFF,&amp;HFFFFFFFF,&amp;HFF000000,0,0,0,0,100,100,0,0.00,1,0,0,7,0,0,0,0</Style>
<Style>Style: NoteBOX2,Arial,29,&amp;HFFFFFFFF,&amp;HFFFFFFFF,&amp;HFF000000,&amp;HFF000000,1,0,0,0,100,100,0,0.00,1,0.5,1.5,7,0,0,0,128</Style>
<Style>Style: NoteBOX3,Arial,29,&amp;HFFC9471E,&amp;HFFFFFFFF,&amp;HFFFFFFFF,&amp;HFF000000,0,0,0,0,100,100,0,0.00,1,0,0,7,0,0,0,0</Style>
</Styles>
<LSet lines="1">
<line style="NoteBOX1">{\pos(174,-99)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\fscy70\t(0,500,\1a&amp;Haa&amp;\3a&amp;H00&amp;\4a&amp;H00&amp;)\t(3500,4000,,\alpha&amp;HFF&amp;)\bord3}{\p1}m 0 0 l 690 0 690 80 0 80{\p0}</line>
<line style="NoteBOX3">{\pos(254,-105)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\fscy144\fscx200\t(0,500,\alpha&amp;H00&amp;)\t(3500,4000,,\alpha&amp;HFF&amp;)\bord1.5}{\p1}m 0 0 l 1 0 1 47 0 47{\p0}</line>
<line style="NoteBOX3">{\pos(255,-105)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\fscy146\t(0,500,\alpha&amp;H00&amp;)\t(3500,4000,\alpha&amp;HFF&amp;)}{\p1}m 0 0 l 1 0 1 48 0 48{\p0}</line>
<line style="NoteBOX3">{\pos(170,-105)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\fscy100\t(0,500,\alpha&amp;H40&amp;)\t(3500,4000,\alpha&amp;HFF&amp;)}{\p1}m 0 0 l 700 0 700 3 0 3{\p0}</line>
<line style="NoteBOX3">{\pos(170,-35)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\fscy150\t(0,500,\alpha&amp;H00&amp;)\t(3500,4000,\alpha&amp;HFF&amp;)}{\p1}m 0 0 l 699 0 699 3 0 3{\p0}</line>
<line style="NoteBOX3">{\pos(170,-105)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\fscy77\t(0,500,\alpha&amp;H00&amp;)\t(3500,4000,\alpha&amp;HFF&amp;)}{\p1}m 0 0 l 1 0 1 93 0 93{\p0}</line>
<line style="NoteBOX3">{\pos(868,-105)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\fscy77\t(0,500,\alpha&amp;H00&amp;)\t(3500,4000,\alpha&amp;HFF&amp;)}{\p1}m 0 0 l 1 0 1 93 0 93{\p0}</line>
<line style="NoteBOX3">{\pos(170,-105)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\fscy77\t(0,500,\1a&amp;HCA&amp;\3a&amp;H00&amp;\4a&amp;H00&amp;)\t(3500,4000,,\alpha&amp;HFF&amp;)\bord3}{\p1}m 0 0 l 699 0 699 93 0 93{\p0}</line>
<line style="NoteBOX1">{\pos(184,-86)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\t(0,500,\alpha&amp;H00&amp;)\t(3500,4000,\alpha&amp;HFF&amp;)\1c&amp;HFFFFFF&amp;\3c&amp;H000000&amp;\bord0.5\shad1.5\b1\i1}NOTE</line>
<line style="NoteBOX2">{\pos(264,-92)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\t(0,500,\alpha&amp;H00&amp;)\t(3500,4000,\alpha&amp;HFF&amp;)\fs40}%line1%</line>
</LSet>
<LSet lines="2">
<line style="NoteBOX1">{\pos(174,-99)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\fscy150\t(0,500,\1a&amp;Haa&amp;\3a&amp;H00&amp;\4a&amp;H00&amp;)\t(3500,4000,,\alpha&amp;HFF&amp;)\bord3}{\p1}m 0 0 l 690 0 690 80 0 80{\p0}</line>
<line style="NoteBOX3">{\pos(254,-105)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\fscy142\fscx200\t(0,500,\alpha&amp;H00&amp;)\t(3500,4000,,\alpha&amp;HFF&amp;)\bord1.5}{\p1}m 0 0 l 1 0 1 47 0 47{\p0}</line>
<line style="NoteBOX3">{\pos(173,-41)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\fscy150\t(0,500,\alpha&amp;H00&amp;)\t(3500,4000,\alpha&amp;HFF&amp;)\bord1.5}{\p1}m 0 0 l 82 0 82 1 0 1{\p0}</line>
<line style="NoteBOX3">{\pos(255,-105)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\fscy130\t(0,500,\alpha&amp;H00&amp;)\t(3500,4000,\alpha&amp;HFF&amp;)}{\p1}m 0 0 l 1 0 1 48 0 48{\p0}</line>
<line style="NoteBOX3">{\pos(170,-105)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\fscy150\t(0,500,\alpha&amp;H50&amp;)\t(3500,4000,\alpha&amp;HFF&amp;)}{\p1}m 0 0 l 700 0 700 3 0 3{\p0}</line>
<line style="NoteBOX3">{\pos(170,28)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\fscy150\t(0,500,\alpha&amp;H00&amp;)\t(3500,4000,\alpha&amp;HFF&amp;)}{\p1}m 0 0 l 699 0 699 3 0 3{\p0}</line>
<line style="NoteBOX3">{\pos(170,-105)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\fscy150\t(0,500,\alpha&amp;H00&amp;)\t(3500,4000,\alpha&amp;HFF&amp;)}{\p1}m 0 0 l 2 0 2 93 0 93{\p0}</line>
<line style="NoteBOX3">{\pos(868,-105)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\fscy150\t(0,500,\alpha&amp;H00&amp;)\t(3500,4000,\alpha&amp;HFF&amp;)}{\p1}m 0 0 l 1 0 1 93 0 93{\p0}</line>
<line style="NoteBOX1">{\pos(170,-105)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\fscy145\t(0,500,\1a&amp;HCA&amp;\3a&amp;H00&amp;\4a&amp;H00&amp;)\t(3500,4000,,\alpha&amp;HFF&amp;)\bord3}{\p1}m 0 0 l 699 0 699 93 0 93{\p0}</line>
<line style="NoteBOX3">{\pos(184,-87)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\t(0,500,\alpha&amp;H00&amp;)\t(3500,4000,\alpha&amp;HFF&amp;)\1c&amp;HFFFFFF&amp;\3c&amp;H000000&amp;\bord0.5\shad1.5\b1\i1}NOTE</line>
<line style="NoteBOX2">{\pos(264,-85)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\t(0,500,\alpha&amp;H00&amp;)\t(3500,4000,\alpha&amp;HFF&amp;)\fs40}%line1%</line>
<line style="NoteBOX2">{\pos(180,-28)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&amp;HFF&amp;}0\N{\r\t(0,500,\alpha&amp;H00&amp;)\t(3500,4000,\alpha&amp;HFF&amp;)\fs40}%line2%</line>
</LSet>
</Note>
</NSSA>
<!--
Style: NoteBOX1,Arial,29,&HFFF6E0FF,&HFFFFFFFF,&HFF000000,&HFF000000,0,0,0,0,100,100,0,0,1,0,0,7,0,0,0,0
Style: NoteBOX2,Arial,29,&HFFFFFFFF,&HFFFFFFFF,&HFF000000,&HFF000000,0,0,0,0,100,100,0,0,1,0.5,0,7,0,0,0,128
{\pos(174,-74)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\fscy70\t(0,500,\1a&Haa&\3a&H00&\4a&H00&)\t(3500,4000,,\alpha&Hff&)\bord2}{\p1}m 0 0 l 690 0 690 60 0 60{\p0}
{\pos(254,-79)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\fscy144\fscx200\t(0,500,\alpha&H00&)\t(3500,4000,,\alpha&Hff&)\bord1.5}{\p1}m 0 0 l 1 0 1 35 0 35{\p0}
{\pos(255,-79)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\fscy146\t(0,500,\alpha&H00&)\t(3500,4000,\alpha&Hff&)}{\p1}m 0 0 l 1 0 1 36 0 36{\p0}
{\pos(170,-79)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\fscy100\t(0,500,\alpha&H40&)\t(3500,4000,\alpha&Hff&)}{\p1}m 0 0 l 700 0 700 2 0 2{\p0}
{\pos(170,-26)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\fscy150\t(0,500,\alpha&H00&)\t(3500,4000,\alpha&Hff&)}{\p1}m 0 0 l 699 0 699 2 0 2{\p0}
{\pos(170,-79)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\fscy77\t(0,500,\alpha&H00&)\t(3500,4000,\alpha&Hff&)}{\p1}m 0 0 l 1 0 1 70 0 70{\p0}
{\pos(868,-79)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\fscy77\t(0,500,\alpha&H00&)\t(3500,4000,\alpha&Hff&)}{\p1}m 0 0 l 1 0 1 70 0 70{\p0}
{\pos(170,-79)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\fscy77\t(0,500,\1a&Hca&\3a&H00&\4a&H00&)\t(3500,4000,,\alpha&Hff&)\bord2}{\p1}m 0 0 l 699 0 699 70 0 70{\p0}
{\pos(184,-68)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\t(0,500,\alpha&H00&)\t(3500,4000,\alpha&Hff&)\1c&HFFFFFF&\bord0\shad1.5\bord0.5\3c&H000000&\b1\i1}NOTE
{\pos(264,-69)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\t(0,500,\alpha&H00&)\t(3500,4000,\alpha&Hff&)\shad1.5\b1\fs30}%line1%
{\pos(174,-74)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\fscy150\t(0,500,\1a&Haa&\3a&H00&\4a&H00&)\t(3500,4000,,\alpha&Hff&)\bord2}{\p1}m 0 0 l 690 0 690 60 0 60{\p0}
{\pos(254,-79)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\fscy142\fscx200\t(0,500,\alpha&H00&)\t(3500,4000,,\alpha&Hff&)\bord1.5}{\p1}m 0 0 l 1 0 1 35 0 35{\p0}
{\pos(173,-31)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\fscy150\t(0,500,\alpha&H00&)\t(3500,4000,\alpha&Hff&)\bord1.5}{\p1}m 0 0 l 82 0 82 1 0 1{\p0}
{\pos(255,-79)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\fscy130\t(0,500,\alpha&H00&)\t(3500,4000,\alpha&Hff&)}{\p1}m 0 0 l 1 0 1 36 0 36{\p0}
{\pos(170,-79)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\fscy150\t(0,500,\alpha&H50&)\t(3500,4000,\alpha&Hff&)}{\p1}m 0 0 l 700 0 700 2 0 2{\p0}
{\pos(170,21)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\fscy150\t(0,500,\alpha&H00&)\t(3500,4000,\alpha&Hff&)}{\p1}m 0 0 l 699 0 699 2 0 2{\p0}
{\pos(170,-79)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\fscy150\t(0,500,\alpha&H00&)\t(3500,4000,\alpha&Hff&)}{\p1}m 0 0 l 2 0 2 70 0 70{\p0}
{\pos(868,-79)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\fscy150\t(0,500,\alpha&H00&)\t(3500,4000,\alpha&Hff&)}{\p1}m 0 0 l 1 0 1 70 0 70{\p0}
{\pos(170,-79)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\fscy145\t(0,500,\1a&Hca&\3a&H00&\4a&H00&)\t(3500,4000,,\alpha&Hff&)\bord2}{\p1}m 0 0 l 699 0 699 70 0 70{\p0}
{\pos(184,-70)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\t(0,500,\alpha&H00&)\t(3500,4000,\alpha&Hff&)\1c&HFFFFFF&\bord0\shad1.5\bord0.5\3c&H000000&\b1\i1}NOTE
{\pos(264,-64)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\t(0,500,\alpha&H00&)\t(3500,4000,\alpha&Hff&)\shad1.5\b1\fs30}%line1%
{\pos(180,-21)\fscy0\t(0,500,\fscy320)\t(3500,4000,\fscy0)\alpha&Hff&}0\N{\r\t(0,500,\alpha&H00&)\t(3500,4000,\alpha&Hff&)\shad1.5\b1\fs30}%line2%
-->

194
SSATool/Filter.cs Normal file
View file

@ -0,0 +1,194 @@
/*
SSATool - A collection of utilities for Advanced Substation Alpha
Copyright (C) 2007 Dan Donovan
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; ONLY under version 2
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System;
using System.Collections;
using System.Collections.Generic; //.Net 2.0
namespace SSATool {
public class Filter : ConditionColl, System.Collections.Generic.IEnumerable<FilterOption>, IEquatable<Filter> {
private Filter template;
protected List<FilterOption> fOptions;
public string Name, Code;
public bool Enabled;
public Filter() : base() {
fOptions = new List<FilterOption>();
Enabled = true;
}
public Filter(List<FilterOption> optionsList) : base() {
fOptions = optionsList;
Code = String.Empty;
}
public Filter(string name) : this() {
Name = name;
Code = String.Empty;
}
public Filter(string name, string code) : this() {
Name = name;
Code = code;
}
public Filter(string name, List<FilterOption> optionsList)
: this(optionsList) {
Name = name;
Enabled = true;
}
bool System.IEquatable<Filter>.Equals(Filter f) {
return (String.CompareOrdinal(this.Name, f.Name) == 0);
}
public override string ToString() {
return Name;
}
public int NumOptions {
get { return fOptions.Count; }
}
public Filter Template {
get { return template; }
}
public void AddOption(string Name,string Val) {
fOptions.Add(new FilterOption(Name,Val));
}
public void AddOption(FilterOption fo) {
fOptions.Add(fo);
}
public void SetOptionValueByIndex(int index, string val) {
if (fOptions.Count > index) fOptions[index].Value = val;
}
public void SetOptionValueByName(string name, string val) {
for (int index=0;index<fOptions.Count;index+=1)
if (string.CompareOrdinal(fOptions[index].Name,name) == 0)
fOptions[index].Value = val;
}
public void SetOptionNameByIndex(int index, string name) {
if (fOptions.Count > index) fOptions[index].Name = name;
}
public void SetOptionByIndex(int index, string name, string val) {
if (fOptions.Count > index) {
fOptions[index].Name = name;
fOptions[index].Value = val;
}
}
public FilterOption GetOptionByIndex(int index) {
return fOptions[index];
}
public string GetOptionValueByIndex(int index) {
return fOptions[index].Value;
}
public FilterOption GetOptionByName(string name) {
for(int index=0;index<fOptions.Count;index+=1)
if (fOptions[index].Name == name)
return fOptions[index];
return (FilterOption) null;
}
public string GetOptionValueByName(string name) {
for(int index=0;index<fOptions.Count;index+=1)
if (fOptions[index].Name == name)
return fOptions[index].Value;
return null;
}
public void RemoveOptionByIndex(int index) {
fOptions.RemoveAt(index);
}
public void RemoveOptionByName(string name) {
for(int index=0;index<fOptions.Count;index+=1)
if (fOptions[index].Name == name) fOptions.RemoveAt(index);
}
public List<FilterOption> CloneOptions() {
List<FilterOption> nl = new List<FilterOption>();
for(int index=0;index!=fOptions.Count;index+=1)
nl.Add((FilterOption)fOptions[index].Clone());
return nl;
}
public object Clone() {
Filter nf = new Filter(Name, CloneOptions());
nf.conditionColl = CloneConditions();
nf.template = (this.template==null)?this:this.template;
return nf;
}
#region IEnumerable Members
IEnumerator<FilterOption> IEnumerable<FilterOption>.GetEnumerator() {
return new FilterEnumerator(this);
}
public System.Collections.IEnumerator GetEnumerator() {
return new FilterEnumerator(this);
}
#endregion
}
public class FilterEnumerator : IEnumerator<FilterOption>, IDisposable {
Filter f;
int index;
public void Dispose() {
}
public FilterEnumerator(Filter f) {
this.f = f;
Reset();
}
public void Reset() {
index=-1;
}
object IEnumerator.Current {
get { return f.GetOptionByIndex(index); }
}
public FilterOption Current {
get { return f.GetOptionByIndex(index); }
}
public bool MoveNext() {
if (++index >= f.NumOptions) return false;
else return true;
}
}
public class FilterOption : ICloneable {
public string Name;
public string Value;
public FilterOption() { }
public FilterOption(string name, string val) {
Name = name;
Value = val;
}
public object Clone() {
return new FilterOption(Name,Value);
}
}
}

6485
SSATool/Form1.cs Normal file

File diff suppressed because it is too large Load diff

241
SSATool/Form1.ja.resx Normal file
View file

@ -0,0 +1,241 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
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">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</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 forserialized 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="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>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="cmdSearchReplace.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="label12.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="label11.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="cmdShift.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="chkShiftNoNeg.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="chkShiftEnd.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="chkShiftStart.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="radTShiftBack.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="radTShiftForward.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="label3.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="radFShiftBackward.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="radFShiftForward.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="label5.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="label4.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="label7.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="label6.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="label10.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="label9.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="label8.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="cmdNewLayer.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="cmdDelLayer.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="cmdAddEffect.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="cmdCopyEffect.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="cmdMoveEffect.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="cmdMoveEffDown.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="cmdMoveEffUp.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="cmdDelEffect.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="label2.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="chkDelEffectCondition.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="cmdAddEffectCondition.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="chkAddOnce.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="chkAddAnyway.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="chkRemoveK.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="chkLayerPerSyllable.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="cmdDelLayerCondition.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="CmdNewLayerCondition.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="cmdDoEffects.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="cmdDupLayer.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="label1.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="cmdReloadFile.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="cmdSSAInvertSel.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="cmdSSADeselall.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="cmdSSASelall.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="cmdReparse.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="cmdDeselAll.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="cmdSelAll.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>On</value>
</data>
<data name="lstSSA.Font" type="System.Drawing.Font, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>MS UI Gothic, 9pt</value>
</data>
</root>

8963
SSATool/Form1.resx Normal file

File diff suppressed because it is too large Load diff

223
SSATool/InputBox.cs Normal file
View file

@ -0,0 +1,223 @@
/*
SSATool - A collection of utilities for Advanced Substation Alpha
Copyright (C) 2007 Dan Donovan
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; ONLY under version 2
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace SSATool
{
/// <summary>
/// Summary description for InputBox.
///
public class InputBox : System.Windows.Forms.Form {
#region Windows Contols and Constructor
private System.Windows.Forms.Label lblPrompt;
private System.Windows.Forms.Button btnOK;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.TextBox txtInput;
/// <summary>
/// Required designer variable.
///
private System.ComponentModel.Container components = null;
public InputBox() {
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
}
#endregion
#region Dispose
/// <summary>
/// Clean up any resources being used.
///
protected override void Dispose( bool disposing ) {
if( disposing ) {
if(components != null) {
components.Dispose();
}
}
base.Dispose( disposing );
}
#endregion
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///
private void InitializeComponent() {
this.lblPrompt = new System.Windows.Forms.Label();
this.btnOK = new System.Windows.Forms.Button();
this.button1 = new System.Windows.Forms.Button();
this.txtInput = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// lblPrompt
//
this.lblPrompt.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.lblPrompt.BackColor = System.Drawing.SystemColors.Control;
this.lblPrompt.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
this.lblPrompt.Location = new System.Drawing.Point(12, 9);
this.lblPrompt.Name = "lblPrompt";
this.lblPrompt.Size = new System.Drawing.Size(302, 82);
this.lblPrompt.TabIndex = 3;
//
// btnOK
//
this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK;
this.btnOK.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
this.btnOK.Location = new System.Drawing.Point(326, 24);
this.btnOK.Name = "btnOK";
this.btnOK.Size = new System.Drawing.Size(64, 24);
this.btnOK.TabIndex = 1;
this.btnOK.Text = "&OK";
//
// button1
//
this.button1.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.button1.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
this.button1.Location = new System.Drawing.Point(326, 56);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(64, 24);
this.button1.TabIndex = 2;
this.button1.Text = "&Cancel";
//
// txtInput
//
this.txtInput.ImeMode = System.Windows.Forms.ImeMode.Off;
this.txtInput.Location = new System.Drawing.Point(8, 100);
this.txtInput.Name = "txtInput";
this.txtInput.Size = new System.Drawing.Size(379, 20);
this.txtInput.TabIndex = 0;
this.txtInput.Text = "";
this.txtInput.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.txtInput_KeyPress);
//
// InputBox
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(398, 128);
this.Controls.Add(this.txtInput);
this.Controls.Add(this.button1);
this.Controls.Add(this.btnOK);
this.Controls.Add(this.lblPrompt);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.ImeMode = System.Windows.Forms.ImeMode.Off;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "InputBox";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "InputBox";
this.ResumeLayout(false);
}
#endregion
#region Private Variables
string formCaption = string.Empty;
string formPrompt = string.Empty;
string inputResponse = string.Empty;
string defaultValue = string.Empty;
#endregion
#region Public Properties
public string FormCaption {
get{return formCaption;}
set{formCaption = value;}
} // property FormCaption
public string FormPrompt {
get{return formPrompt;}
set{formPrompt = value;}
} // property FormPrompt
public string InputResponse {
get{return inputResponse;}
set{inputResponse = value;}
} // property InputResponse
public string DefaultValue {
get{return defaultValue;}
set{defaultValue = value;}
} // property DefaultValue
#endregion
#region Form and Control Events
public static InputBoxResult Show(string prompt, string title, string defaultResponse,
int xpos, int ypos) {
using (InputBox form = new InputBox()) {
form.lblPrompt.Text = prompt;
form.Text = title;
form.txtInput.Text = defaultResponse;
if (xpos >= 0 && ypos >= 0) {
form.StartPosition = FormStartPosition.Manual;
form.Left = xpos;
form.Top = ypos;
}
DialogResult result = form.ShowDialog();
InputBoxResult retval = new InputBoxResult();
if (result == DialogResult.OK) {
retval.Text = form.txtInput.Text;
retval.OK = true;
}
return retval;
}
}
private void txtInput_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) {
if ((e.KeyChar == '\r') || (e.KeyChar == '\n')) {
btnOK.PerformClick();
e.Handled = true;
}
else if (e.KeyChar == 27) { //escape key
button1.PerformClick();
e.Handled = true;
}
}
public static InputBoxResult Show(string prompt, string title, string defaultText) {
return Show(prompt, title, defaultText, -1, -1);
}
}
#endregion
public class InputBoxResult {
public bool OK;
public string Text;
}
}

166
SSATool/InputBox.resx Normal file
View file

@ -0,0 +1,166 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
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">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</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 forserialized 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="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>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="lblPrompt.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lblPrompt.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblPrompt.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="btnOK.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="btnOK.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="btnOK.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="button1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="button1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="button1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="txtInput.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="txtInput.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="txtInput.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>(Default)</value>
</data>
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>8, 8</value>
</data>
<data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.Name">
<value>InputBox</value>
</data>
<data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>80</value>
</data>
<data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
</root>

126
SSATool/Layer.cs Normal file
View file

@ -0,0 +1,126 @@
/*
SSATool - A collection of utilities for Advanced Substation Alpha
Copyright (C) 2007 Dan Donovan
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; ONLY under version 2
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System;
using System.Collections;
using System.Collections.Generic; //.Net 2.0
namespace SSATool
{
public class Layer : ConditionColl, IEnumerable, ICloneable {
private List<Filter> filterColl;
public string Name;
public int Repetitions;
public bool Enabled;
public bool PerSyllable, SyllablePerLine;
public bool AddAll, AddOnce;
public bool AddK, AddASSA, AddBracket, AddText;
public Layer() {
filterColl = new List<Filter>();
Enabled = true;
PerSyllable = SyllablePerLine = AddAll = AddOnce = false;
AddK = AddASSA = AddBracket = AddText = true;
Repetitions = 1;
}
public int Count {
get { return filterColl.Count; }
}
public Filter GetFilter(int index) {
return filterColl[index];
}
public void AddFilter(Filter tf) {
filterColl.Add(tf);
}
public void InsertFilter(int index, Filter tf) {
filterColl.Insert(index,tf);
}
public void RemoveFilter(int index) {
if (filterColl.Count > index) filterColl.RemoveAt(index);
}
public void SwapFilterPositions(int indexone, int indextwo) {
if ((filterColl.Count > Math.Max(indexone,indextwo)) && (indexone != indextwo)) {
Filter swap;
swap = filterColl[indexone];
filterColl[indexone] = filterColl[indextwo];
filterColl[indextwo] = swap;
}
}
public List<Filter> CloneFilters() {
List<Filter> nl = new List<Filter>();
for (int index=0;index!=filterColl.Count;index+=1)
nl.Add((Filter)filterColl[index].Clone());
return nl;
}
public object Clone() {
Layer nl = (Layer)this.MemberwiseClone();
nl.filterColl = CloneFilters();
nl.conditionColl = CloneConditions();
return nl;
}
public IEnumerator GetEnumerator() {
return new LayerEnumerator(this);
}
}
public class LayerEnumerator : IEnumerator {
Layer l;
int index;
#region IEnumerator Members
public void Reset() {
index = -1;
}
public object Current {
get {
return l.GetFilter(index);
}
}
public bool MoveNext() {
if (++index >= l.Count) return false;
else return true;
}
#endregion
internal LayerEnumerator(Layer l) {
this.l = l;
Reset();
}
}
}

305
SSATool/Line.cs Normal file
View file

@ -0,0 +1,305 @@
/*
SSATool - A collection of utilities for Advanced Substation Alpha
Copyright (C) 2007 Dan Donovan
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; ONLY under version 2
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
namespace SSATool {
public enum LineType {
dialogue,
comment,
style,
other,
error
}
public class DialogueLine : ICloneable {
public TimeSpan start, end;
public Style style;
public string actor, effect;
public string text;
public int marginl, marginr, margint, marginb;
public int layer;
public bool marked;
public override string ToString() {
string retStr = String.Format("Dialogue: {0},{1},{2},{3},{4},{5:D4},{6:D4},{7:D4},{8}{9},{10}",
(Form1.sver==4)?("Marked="+(this.marked?"1":"0")):this.layer.ToString(Util.nfi),
Util.TimeSpanSSA(this.start,false,1),
Util.TimeSpanSSA(this.end,true,1),
this.style.name, this.actor,
this.marginl, this.marginr, this.margint,
((Form1.sver == 6) ? this.marginb.ToString(Util.nfi).PadLeft(4, '0') + "," : String.Empty),
this.effect,this.text);
return retStr;
}
public Object Clone() {
return this.MemberwiseClone(); // A shallow memberwise-clone is fine
}
/// <summary>
/// Return just the text of the line without any SSA
/// </summary>
/// <returns></returns>
public string JustText {
get {
string justtext = string.Empty;
char[] linechar = this.text.ToCharArray();
bool inCode = false;
for (int charindex = 0; charindex != this.text.Length; charindex+=1) {
if (linechar[charindex] == '{') inCode = true;
else if (linechar[charindex] == '}') inCode = false;
else if (!inCode) justtext = justtext + linechar[charindex];
}
return justtext;
}
}
/// <summary>
/// Return the margin of this line, taking overrides into account
/// </summary>
/// <returns>The margin as a rectangle</returns>
public RectangleF GetMargin() {
int Marginl = (this.marginl==0)?this.style.marginl:this.marginl;
int Margint = (this.margint==0)?this.style.margint:this.margint;
int Marginb = (this.marginb==0)?this.style.marginb:this.marginb;
int Marginr = (this.marginr==0)?this.style.marginr:this.marginr;
int Height = Form1.ResY - (Margint+Marginb);
int Width = Form1.ResX - (Marginl+Marginr);
return new RectangleF(Marginl, Margint, Width, Height);
}
/// <summary>
/// Find the bounding rectangle of an area of the line
/// </summary>
/// <param name="startIndex"></param>
/// <param name="length"></param>
/// <returns>The bounding rectangle</returns>
public RectangleF GetRect(int startIndex, int length) {
Graphics graphics = Form1.listSSAg;
StringFormat format = new System.Drawing.StringFormat();
CharacterRange[] ranges = { new CharacterRange(startIndex, length) };
Region[] regions = new Region[1];
RectangleF margin, rect;
margin = this.GetMargin();
format.SetMeasurableCharacterRanges(ranges);
int align = this.style.scrAlignment;
switch (align&3) {
case 1:
format.LineAlignment = StringAlignment.Near;
break;
case 2:
format.LineAlignment = StringAlignment.Center;
break;
default:
format.LineAlignment = StringAlignment.Far;
break;
}
switch (align&12) {
case 0:
format.Alignment = StringAlignment.Far;
break;
case 4:
format.Alignment = StringAlignment.Near;
break;
default:
format.Alignment = StringAlignment.Center;
break;
}
regions = graphics.MeasureCharacterRanges(this.JustText, this.style.GetFont(), margin, format);
rect = regions[0].GetBounds(graphics);
rect = new RectangleF(margin.X+rect.X, margin.Y+rect.Y, rect.Width, rect.Height);
return rect;
}
public static DialogueLine ParseLine(string theLine, LineType lt) {
try {
DialogueLine retLine = new DialogueLine();
char[] linechar = theLine.ToCharArray();
string buff = String.Empty;
int pos = 0;
bool neg = false;
for (int index = (Form1.sver == 4) ? 17 : 9; index != linechar.Length; index+=1) {
if ((pos<9||pos==9&&Form1.sver==6) && linechar[index].Equals(',')) {
switch (pos) {
case 0:
if (Form1.sver == 4) retLine.marked = linechar[index - 1].Equals('1');
else retLine.layer = int.Parse(buff, Util.cfi);
break;
case 1:
if (neg) retLine.start = TimeSpan.Parse(buff.Replace("-", String.Empty)).Negate();
else retLine.start = TimeSpan.Parse(buff);
break;
case 2:
if (neg) retLine.end = TimeSpan.Parse(buff.Replace("-", String.Empty)).Negate();
else retLine.end = TimeSpan.Parse(buff);
break;
case 3:
retLine.style = Form1.styleColl.Find(delegate(Style s) { return s.Equals(buff); });
if (retLine.style == null) retLine.style = new Style(buff);
break;
case 4:
retLine.actor = buff;
break;
case 5:
retLine.marginl = int.Parse(buff, Util.cfi);
break;
case 6:
retLine.marginr = int.Parse(buff, Util.cfi);
break;
case 7:
retLine.margint = int.Parse(buff, Util.cfi);
break;
case 8:
if (Form1.sver < 6) retLine.effect = buff;
else retLine.marginb = int.Parse(buff, Util.cfi);
break;
case 9:
retLine.effect = buff;
break;
}
pos += 1;
buff = string.Empty;
neg = false;
}
else if ((pos != 0 || char.IsDigit(linechar[index])) && (pos == 3 || pos == 4 || pos >= 8 || !char.IsWhiteSpace(linechar[index]))) {
buff += linechar[index];
neg = neg || (linechar[index] == '-');
}
}
retLine.text = buff;
return retLine;
} catch {
throw new FormatException();
}
}
public DialogueLine() { }
public DialogueLine(TimeSpan StartTime, TimeSpan EndTime, Style Style) {
start = StartTime;
end = EndTime;
style = Style;
}
public DialogueLine(string Text) {
text = Text;
}
public DialogueLine(Style Style, string Text) : this(Text) {
style = Style;
}
}
public class Line : IEquatable<Line>, ICloneable {
public LineType lineType;
public object line;
public bool enabled, selected;
public Line() {
this.enabled = true;
}
public static LineType getLineType(string theLine) {
if (theLine.Length > 20 && String.Compare(theLine.Substring(0, 9), "dialogue:", true, Util.cfi) == 0)
return LineType.dialogue;
else if (theLine.Length > 8 && String.Compare(theLine.Substring(0, 8), "comment:", true, Util.cfi) == 0)
return LineType.comment;
else if (theLine.Length > 20 && String.Compare(theLine.Substring(0, 6), "style:", true, Util.cfi) == 0)
return LineType.style;
else
return LineType.other;
}
public static Line ParseLine(string inStr) {
Line l = new Line();
l.lineType = getLineType(inStr);
switch (l.lineType) {
case LineType.dialogue:
try {
l.line = DialogueLine.ParseLine(inStr, LineType.dialogue);
} catch {
l.lineType = LineType.error;
l.line = inStr;
}
break;
case LineType.style:
try {
Style s = Style.ParseStyle(inStr);
l.line = s;
Form1.styleColl.Add(s);
} catch {
l.lineType = LineType.error;
l.line = inStr;
}
break;
default:
if (inStr.Length > 8 && String.Compare(inStr.Substring(0, 7), "playres", true, Util.cfi) == 0) {
switch (inStr.ToCharArray()[7]) {
case 'x':
case 'X':
Form1.ResX = int.Parse(inStr.Substring(9, inStr.Length - 9), Util.cfi);
break;
case 'y':
case 'Y':
Form1.ResY = int.Parse(inStr.Substring(9, inStr.Length - 9), Util.cfi);
break;
}
}
else if (inStr.Length > 10 && String.Compare(inStr.Substring(0, 10), "scripttype", true, Util.cfi) == 0) {
//TODO: Improve this detection
inStr = inStr.TrimEnd();
if (inStr.EndsWith("+=1")) Form1.sver = 6;
else if (inStr.EndsWith("+")) Form1.sver = 5;
else Form1.sver = 4;
}
l.line = inStr;
break;
}
return l;
}
bool System.IEquatable<Line>.Equals(Line line) {
return this.line==line.line;
}
public override int GetHashCode() {
return base.GetHashCode();
}
public Object Clone() {
Line retLine = new Line();
retLine.enabled = this.enabled;
retLine.lineType = this.lineType;
if (this.lineType == LineType.dialogue)
retLine.line = ((DialogueLine)line).Clone();
else if (this.lineType == LineType.style)
retLine.line = ((Style)line).Clone();
else
retLine.line = this.line;
return retLine;
}
public override string ToString() {
return line.ToString();
}
}
}

368
SSATool/ListViewES.cs Normal file
View file

@ -0,0 +1,368 @@
/*
SSATool - A collection of utilities for Advanced Substation Alpha
Copyright (C) 2007 Dan Donovan
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; ONLY under version 2
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
//using System.ComponentModel.Design;
//using System.Windows.Forms.Design;
//using System.Drawing.Design;
namespace SSATool {
/// <summary>
/// Summary description for ListViewES.
/// </summary>
public class ListViewES : System.Windows.Forms.ListView {
private System.Windows.Forms.TextBox textBox1;
private ComboBox comboBox1;
private System.ComponentModel.Container components = null;
#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.textBox1 = new System.Windows.Forms.TextBox();
this.comboBox1 = new System.Windows.Forms.ComboBox();
this.SuspendLayout();
//
// textBox1
//
this.textBox1.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.textBox1.Enabled = false;
this.textBox1.Location = new System.Drawing.Point(17, 17);
this.textBox1.Margin = new System.Windows.Forms.Padding(3, 1, 3, 1);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(20, 13);
this.textBox1.TabIndex = 1;
this.textBox1.Visible = false;
this.textBox1.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.textBox1_KeyPress);
//
// comboBox1
//
this.comboBox1.Cursor = System.Windows.Forms.Cursors.Default;
this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBox1.Enabled = false;
this.comboBox1.ImeMode = System.Windows.Forms.ImeMode.Disable;
this.comboBox1.IntegralHeight = false;
this.comboBox1.Location = new System.Drawing.Point(32, 32);
this.comboBox1.Margin = new System.Windows.Forms.Padding(1);
this.comboBox1.Name = "comboBox1";
this.comboBox1.Size = new System.Drawing.Size(121, 21);
this.comboBox1.TabIndex = 0;
this.comboBox1.Visible = false;
this.comboBox1.Leave += new System.EventHandler(this.ListViewES_Leave);
this.comboBox1.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.textBox1_KeyPress);
//
// ListViewES
//
this.Controls.Add(this.textBox1);
this.Controls.Add(this.comboBox1);
this.LabelEdit = true;
this.Size = new System.Drawing.Size(992, 616);
this.View = System.Windows.Forms.View.Details;
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.ListViewES_MouseUp);
this.Leave += new System.EventHandler(this.ListViewES_Leave);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
public event LabelSubEditEventHandler SubItemClicked;
public event LabelSubEditEventHandler SubItemBeginEditing;
public event LabelSubEditEndEventHandler SubItemEndEditing;
public event ScrollEventHandler OnScroll;
public ListViewES() {
InitializeComponent();
//this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
this.DoubleBuffered = true;
}
protected override void Dispose(bool disposing) {
if (disposing) {
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
public new void SetStyle(System.Windows.Forms.ControlStyles flag, bool value) {
base.SetStyle(flag, value);
}
private ListViewItem item;
private int subItemIndex;
private Control c;
public int ItemsOnScreen {
get {
Rectangle tib = this.TopItem.Bounds;
int offH = this.Height - tib.Top;
int height = tib.Height;
int num = Convert.ToInt32(Math.Floor((float)offH / height),Util.nfi);
return num;
}
}
public void StartEditing(ListViewItem item, int subitem) {
if (c != null) EndEditing(true);
this.item = item;
this.subItemIndex = subitem;
c = (Control) this.textBox1;
StartEditingHelper();
}
public void StartEditing(ListViewItem item, int subitem, string[] ComboChoices) {
if (c != null) EndEditing(true);
this.item = item;
this.subItemIndex = subitem;
c = (Control)this.comboBox1;
comboBox1.Items.Clear();
comboBox1.Items.AddRange(ComboChoices);
StartEditingHelper();
}
private void StartEditingHelper() {
this.SuspendLayout();
c.Enabled = true;
PositionControl();
c.Text = item.SubItems[subItemIndex].Text;
c.Show();
c.Focus();
this.ResumeLayout(true);
}
private void PositionControl() {
if (c != null) {
c.Bounds = this.GetSubItemBounds(item, subItemIndex);
//if (GridLines == true) c.Height -= 1;
if (this.CheckBoxes==true && subItemIndex==0) {
c.Left += 20;
c.Width -= 22;
}
else {
c.Left += 4;
c.Width -= 6;
}
}
}
private void EndEditing(bool saveValue) {
if ((item != null) && (subItemIndex != -1)) {
this.SuspendLayout();
if (saveValue) item.SubItems[subItemIndex].Text = c.Text;
if (SubItemEndEditing != null)
this.SubItemEndEditing(this,
new LabelSubEditEndEventArgs(item, subItemIndex,
item.SubItems[subItemIndex].Text, !saveValue));
this.item = null;
this.subItemIndex = -1;
c.Text = String.Empty;
c.Hide();
c.Enabled = false;
this.ResumeLayout(true);
saveValue = true;
c = null;
}
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e) {
if (e.KeyChar == (char)(int)Keys.Enter) {
EndEditing(true);
e.Handled = true;
}
else if (e.KeyChar == (char)(int)Keys.Escape) {
EndEditing(false);
e.Handled = true;
}
}
private void ListViewES_MouseUp(object sender, MouseEventArgs e) {
if (c != null) EndEditing(true);
if (this.View==System.Windows.Forms.View.Details) {
int index;
ListViewItem lvi;
index = this.GetSubItemAt(e.X,e.Y,out lvi);
if ((index != -1) && ((this.CheckBoxes == false) || (e.X > 15))) {
LabelSubEditEventArgs lsa = new LabelSubEditEventArgs(lvi, index);
if (SubItemBeginEditing != null) this.SubItemBeginEditing(this, lsa);
if (SubItemClicked != null) this.SubItemClicked(this, lsa);
else if (this.LabelEdit == true) this.StartEditing(lvi, index);
}
}
}
public int GetSubItemAt(int x, int y, out ListViewItem item) {
if (this.Items.Count != 0) {
Rectangle tib = this.TopItem.Bounds;
int left = tib.Left;
if (left < 0) {
item = null;
return -1;
}
int offH = this.Height - tib.Top;
int top = this.TopItem.Index;
int height = tib.Height;
int bottom = top + Convert.ToInt32(Math.Floor((float)offH / (float)height),Util.nfi);
int row = top - 1 + Convert.ToInt32((((float)bottom - top) * ((float)y / offH)),Util.nfi);
if ((row < this.Items.Count) && (row >= 0)) {
for(int column=0;column<this.Columns.Count;column+=1) {
left += this.Columns[column].Width;
if (x <= left) { item = this.Items[row]; return column;}
}
}
}
item = null;
return -1;
}
public Rectangle GetSubItemBounds(ListViewItem Item, int SubItem) {
if (SubItem >= this.Columns.Count)
throw new IndexOutOfRangeException("SubItem " + SubItem + " out of range");
else if (Item == null)
return Rectangle.Empty; // throw new ArgumentNullException("Item");
int top, left, width, height;
//Item.EnsureVisible();
Rectangle bounds = Item.GetBounds(ItemBoundsPortion.Entire);
top = bounds.Top;
width = this.Columns[SubItem].Width;
height = bounds.Height;
left = bounds.Left;
for(int index=0;index<SubItem;index+=1)
left += this.Columns[index].Width;
return new Rectangle(new Point(left,top),new Size(width,height));
}
/// <summary>
/// Used to recreate the list items when columns are modified
/// </summary>
public void RecopyListItems() {
this.BeginUpdate();
string[] news;
ListViewItem lvi;
for(int outerindex=0; outerindex!=this.Items.Count; outerindex+=1) {
lvi = this.Items[outerindex];
news = new string[this.Columns.Count];
// Can't copy more parameters than in the old one,
// and can't copy more than the new one can store
for(int index=0;index!=lvi.SubItems.Count&&index!=news.Length;index+=1) {
news[index] = lvi.SubItems[index].Text;
}
this.Items[outerindex] = new ListViewItem(news);
}
this.EndUpdate();
}
private void ListViewES_Leave(object sender, EventArgs e) {
EndEditing(true);
}
//[Category("Action")]
//public event ScrollEventHandler Scrolled = null;
[Serializable]
public delegate void LabelSubEditEventHandler(
object sender,
LabelSubEditEventArgs e
);
[Serializable]
public delegate void LabelSubEditEndEventHandler(
object sender,
LabelSubEditEndEventArgs e
);
public class LabelSubEditEventArgs : EventArgs {
private int _subIndex;
private ListViewItem _item;
public LabelSubEditEventArgs(ListViewItem lvi, int subItem) {
_subIndex = subItem;
_item = lvi;
}
public ListViewItem Item {
get { return _item; }
}
public int SubIndex {
get { return _subIndex; }
}
}
public class LabelSubEditEndEventArgs : LabelSubEditEventArgs {
string _text;
bool _cancel;
public LabelSubEditEndEventArgs(ListViewItem lvi, int subItem, string text, bool cancel) :
base(lvi,subItem) {
_text = text;
_cancel = cancel;
}
public bool Cancel {
get { return _cancel; }
}
public string Text {
get { return _text; }
}
}
private const int WM_HSCROLL = 0x114;
private const int WM_VSCROLL = 0x115;
protected override void WndProc(ref System.Windows.Forms.Message msg) {
if ((msg.Msg == WM_HSCROLL) || (msg.Msg == WM_VSCROLL)) {
if (c!=null) PositionControl();
if (OnScroll != null) OnScroll(this,new ScrollEventArgs(ScrollEventType.EndScroll,0,0,(msg.Msg == WM_HSCROLL)?ScrollOrientation.HorizontalScroll:ScrollOrientation.VerticalScroll));
base.WndProc(ref msg);
}
else base.WndProc(ref msg);
}
}
}

129
SSATool/ListViewES.resx Normal file
View file

@ -0,0 +1,129 @@
<?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=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>
<metadata name="textBox1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 54</value>
</metadata>
<metadata name="comboBox1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>107, 57</value>
</metadata>
<metadata name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
</root>

180
SSATool/ManualTransform.cs Normal file
View file

@ -0,0 +1,180 @@
/*
SSATool - A collection of utilities for Advanced Substation Alpha
Copyright (C) 2007 Dan Donovan
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; ONLY under version 2
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace SSATool {
public class ManualTransform {
public static MTVars ListViewToMTV(ListView lv) {
double expbase, opt;
MTVars mtv = new MTVars();
MTVars.MTVariable mtvar;
ListViewItem lvi;
string text;
for(int lvindex=0;lvindex!=lv.Items.Count;lvindex+=1){
lvi = lv.Items[lvindex];
mtvar = new MTVars.MTVariable(lvi.Text);
for(int index=1;index<lvi.SubItems.Count;index+=2) {
text = lvi.SubItems[index].Text;
if (double.TryParse(text,out opt)) mtvar.AddOption(opt);
else mtvar.AddOption(text);
}
for(int index=2;index<lvi.SubItems.Count;index+=2) {
text = lvi.SubItems[index].Text.ToLower(Util.cfi);
Util.ScaleRatioS srs = new Util.ScaleRatioS();
expbase = 1;
if (double.TryParse(text, out opt)) {
srs.srt = Util.ScaleRatioType.Polynomial;
expbase = opt;
}
if ((text.StartsWith("log")) && (double.TryParse(text.Substring(3,text.Length-3), out opt))) {
srs.srt = Util.ScaleRatioType.Logarithmic;
expbase = opt;
}
else if ((text.StartsWith("exp")) && (double.TryParse(text.Substring(3, text.Length-3), out opt))) {
srs.srt = Util.ScaleRatioType.Exponential;
expbase = opt;
}
srs.expbase = expbase;
mtvar.AddAccel(srs);
}
mtv.AddVariable(mtvar);
}
return mtv;
}
public static string DoTransform(List<TimeSpan> TransformTimes, MTVars Vars, string Code, double FrameRate) {
double fp = 1.0/FrameRate;
double ratio;
TimeSpan frame = TimeSpan.FromSeconds(fp);
TimeSpan curtime;
StringBuilder sb = new StringBuilder(6144);
MTVars.MTVariable mtv;
string rep, repwith, output;
int index, windex, comp;
/* The times are already sorted because the listbox is sorted.
* We'll loop from the first time to the last time
* and figure out which section we're in then.
* I'm doing this because rounding problems could otherwise
* cause us to miss a frame between sections or give us an
* invalid offset (for example, each frame was .02 seconds off in time)
*/
index = windex = 0;
curtime = TransformTimes[0];
TransformTimes[TransformTimes.Count-1].Add(frame);
while(curtime.CompareTo(TransformTimes[TransformTimes.Count-1]) == -1) {
// Find out what zone we're in (0-based)
while((comp = curtime.CompareTo(TransformTimes[windex])) == -1)
windex+=1;
sb.Append(
Code.Replace("%starttime%",
Util.TimeSpanSSA(
(index==0&&curtime.CompareTo(TimeSpan.Zero)==-1)?TimeSpan.Zero:curtime,false,1))
.Replace("%endtime%",Util.TimeSpanSSA(curtime=curtime.Add(frame),false,1))
); // curtime is incremented in the line above this, notice the single equals
for(int mtindex=0;mtindex!=Vars.Count;mtindex+=1){
mtv = Vars.GetVariable(mtindex);
ratio = Convert.ToDouble(curtime.Subtract(TransformTimes[0]).Ticks,Util.nfi)
/ Convert.ToDouble(((TransformTimes[windex+1]).Subtract(frame.Add(TransformTimes[windex]))).Ticks,Util.nfi);
rep = "%" + mtv.Name + "%";
repwith = mtv.Value(windex,ratio).ToString();
sb.Replace(rep,repwith);
}
sb.AppendLine();
index+=1;
}
output = sb.ToString().TrimEnd();
if (Code.Contains("$")) return Evaluate.ScriptParse(output);
return output;
}
public class MTVars {
private List<MTVariable> varList;
public MTVars() {
varList = new List<MTVariable>(4);
}
public int Count {
get { return varList.Count; }
}
public void AddVariable(MTVariable mtvar) {
varList.Add(mtvar);
}
public MTVariable GetVariable(int index) {
return varList[index];
}
public class MTVariable {
private ArrayList optList;
private List<Util.ScaleRatioS> accelList;
private string _name;
public object Value(int index) {
return optList[index];
}
public object Value(int index, double ratio) {
if ((optList[index] is string) || (optList[index+1] is string))
return optList[index];
else return (double)optList[index] + Util.ScaleRatio(ratio,accelList[index])
*((double)optList[index+1]-(double)optList[index]);
}
public MTVariable(string name) {
optList = new ArrayList();
accelList = new List<Util.ScaleRatioS>();
_name = name;
}
public void AddOption(object opt) {
optList.Add(opt);
}
public void AddAccel(Util.ScaleRatioS srs) {
accelList.Add(srs);
}
public string Name {
get { return _name; }
}
}
}
}
}

184
SSATool/Notebox.cs Normal file
View file

@ -0,0 +1,184 @@
/*
SSATool - A collection of utilities for Advanced Substation Alpha
Copyright (C) 2007 Dan Donovan
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; ONLY under version 2
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Xml;
namespace SSATool {
public static class Notebox {
public struct NoteBox {
public string name;
public string author;
public string description;
public int resx, resy;
public List<NoteBoxLine> nblines;
public List<Style> stylelist;
}
public struct NoteBoxLine {
public int maxLines;
public List<DialogueLine> lines;
}
public static List<Notebox.NoteBox> noteBoxColl;
public static List<Style> nbStyleColl;
public static void readNoteBoxes() {
if (File.Exists("notebox.xml")) {
noteBoxColl = new List<NoteBox>();
NoteBox nb;
NoteBoxLine thisnbl;
List<NoteBoxLine> nblList;
List<DialogueLine> thisNoteList;
List<Style> slist;
int stylever, lsetindex;
Form1.FormMain.cmbNBStyle.Items.Clear();
XmlDocument xDocM = new XmlDocument();
try {
xDocM.Load("notebox.xml");
XmlNode xDoc = xDocM.SelectSingleNode("NSSA");
XmlNodeList notes = xDoc.SelectNodes("Note");
foreach (XmlNode nnode in notes) {
nb = new NoteBox();
slist = new List<Style>(3);
nblList = new List<NoteBoxLine>(2);
nb.name = (nnode.Attributes["name"] != null) ? nnode.Attributes["name"].Value : "Untitled";
nb.author = (nnode.Attributes["author"] != null) ? nnode.Attributes["author"].Value : "Unknown";
nb.description = (nnode.Attributes["desc"] != null) ? nnode.Attributes["desc"].Value : "";
nb.resx = (nnode.Attributes["resx"] != null) ? int.Parse(nnode.Attributes["resx"].Value) : 640;
nb.resy = (nnode.Attributes["resy"] != null) ? int.Parse(nnode.Attributes["resy"].Value) : 480;
XmlNode styles = nnode.SelectSingleNode("Styles");
stylever = (styles.Attributes["version"] != null) ? int.Parse(styles.Attributes["version"].Value) : 0;
if (styles != null) {
XmlNodeList stylelist = styles.SelectNodes("Style");
foreach (XmlNode style in stylelist) {
slist.Add(Style.ParseStyle(style.InnerText, stylever));
}
}
nb.stylelist = slist;
XmlNodeList lsets = nnode.SelectNodes("LSet");
for (lsetindex = 0; lsetindex != lsets.Count; lsetindex+=1) {
XmlNode lsnode = lsets[lsetindex];
thisNoteList = new List<DialogueLine>(16);
XmlNodeList lines = lsnode.SelectNodes("line");
foreach (XmlNode lnode in lines) {
if (lnode.Attributes["style"]==null)
thisNoteList.Add(new DialogueLine(lnode.InnerText));
else
thisNoteList.Add(new DialogueLine(new Style(lnode.Attributes["style"].Value),lnode.InnerText));
}
thisnbl = new NoteBoxLine();
thisnbl.lines = thisNoteList;
thisnbl.maxLines = (lsnode.Attributes["lines"] != null) ? int.Parse(lsnode.Attributes["lines"].Value) : 1;
nblList.Add(thisnbl);
}
nb.nblines = nblList;
noteBoxColl.Add(nb);
Form1.FormMain.cmbNBStyle.Items.Add(nb.name + " by " + nb.author);
Form1.FormMain.cmbNBStyle.SelectedIndex = 0;
}
} catch {
MessageBox.Show("Error parsing noteboxes.");
}
}
}
public static void DoNotebox(string Line1, string Line2, int NoteboxIndex) {
double scalefactorx=0, scalefactory=0;
int lines = String.IsNullOrEmpty(Line2) ? 1 : 2;
NoteBox nb = noteBoxColl[NoteboxIndex];
NoteBoxLine nbl = nb.nblines.Find(delegate(NoteBoxLine n) { return n.maxLines.Equals(lines); });
StringBuilder sb = new StringBuilder(1024);
TimeSpan startTime, endTime;
Line line;
DialogueLine dl;
nbStyleColl = new List<Style>(4);
if (Form1.ResX > 0 && nb.resx > 0) scalefactorx = ((double)Form1.ResX / nb.resx);
if (Form1.ResY > 0 && nb.resy > 0) scalefactory = ((double)Form1.ResY / nb.resy);
if (scalefactorx == 0 && scalefactory != 0) scalefactorx = scalefactory;
else if (scalefactory == 0 && scalefactorx != 0) scalefactory = scalefactorx;
else if ((scalefactorx+scalefactory)==0) scalefactorx = scalefactory = 1.0;
startTime = TimeSpan.Parse(Form1.FormMain.maskedTextNBStart.Text);
endTime = TimeSpan.Parse(Form1.FormMain.maskedTextNBEnd.Text);
Resscale rs = new Resscale(scalefactorx,scalefactory);
for (int index = 0; index != nbl.lines.Count; index+=1) {
line = new Line();
line.lineType = LineType.dialogue;
dl = (DialogueLine)(nbl.lines[index].Clone());
dl.start = startTime;
dl.end = endTime;
line.line = dl;
dl.text = dl.text.Replace("%line1%",Line1).Replace("%line2%",Line2);
dl = rs.ScaleDialogue(dl);
dl.style = nb.stylelist.Find(delegate(Style s) { return s.name.Equals(dl.style.name); });
dl.style = (Style)(dl.style.Clone());
if (nbStyleColl.Contains(dl.style) == false) nbStyleColl.Add(rs.ScaleStyle(dl.style));
sb.AppendLine(dl.ToString());
}
Form1.FormMain.textNBOut.Text = sb.ToString().TrimEnd();
sb = new StringBuilder(1024);
for (int index = 0; index != nb.stylelist.Count; index+=1)
sb.AppendLine(nb.stylelist[index].ToString());
Form1.FormMain.textNBStyles.Text = sb.ToString().TrimEnd();
}
public static void CopyStyles() {
int styleLine = -1;
Line newLine;
for (int index = 0; index != Form1.lineColl.Count; index+=1) {
if (Form1.lineColl[index].lineType == LineType.style) {
styleLine = index;
break;
}
}
if (styleLine != -1) {
for (int index = 0; index != nbStyleColl.Count; index+=1) {
if (Form1.styleColl.Contains(nbStyleColl[index]) == false) {
newLine = new Line();
newLine.lineType = LineType.style;
newLine.line = nbStyleColl[index];
Form1.lineColl.Insert(styleLine, newLine);
Form1.styleColl.Add(nbStyleColl[index]);
}
}
Form1.FormMain.ExtractStyles();
}
}
}
}

181
SSATool/Resscale.cs Normal file
View file

@ -0,0 +1,181 @@
/*
SSATool - A collection of utilities for Advanced Substation Alpha
Copyright (C) 2007 Dan Donovan
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; ONLY under version 2
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace SSATool {
public class Resscale {
public static Regex rscale = new Regex(@"(\\[a-zA-Z]+\(?)([0-9,\-]+)", RegexOptions.IgnoreCase | RegexOptions.Singleline);
public static Regex rscaledrawing = new Regex(@"{.*\\p(?<scale>\d+)(.*?((\s*(c|([mnlbsp](\s+(?<num>\d+\.?\d*))+)))+))+", RegexOptions.IgnoreCase | RegexOptions.Singleline);
public double scalefactorx, scalefactory;
StringBuilder sb;
GroupCollection gc;
Match m;
MatchCollection mc;
string[] split;
string linetok;
int lastindex, tokindex;
int pscale;
bool x; // x or y coordinate, used for drawing
public Resscale(double ScaleFactorX, double ScaleFactorY) {
scalefactorx = ScaleFactorX;
scalefactory = ScaleFactorY;
}
public Style ScaleStyle(Style s) {
//No need to scale 1:1
if (scalefactorx==1.0 && scalefactory==1.0) return s;
s.fontSize *= (float)scalefactory;
s.shadowDepth *= scalefactory;
s.outlineWidth *= scalefactory;
s.margint = Convert.ToInt32(Math.Round(s.margint * scalefactory, 0), Util.nfi);
s.marginb = Convert.ToInt32(Math.Round(s.marginb * scalefactory, 0), Util.nfi);
s.marginl = Convert.ToInt32(Math.Round(s.marginl * scalefactorx, 0), Util.nfi);
s.marginr = Convert.ToInt32(Math.Round(s.marginr * scalefactorx, 0), Util.nfi);
return s;
}
public DialogueLine ScaleDialogue(DialogueLine dl) {
//No need to scale 1:1
if (scalefactorx==1.0 && scalefactory==1.0) return dl;
sb = new StringBuilder(1024);
linetok = dl.text;
lastindex = 0;
mc = rscale.Matches(linetok);
for (int mindex = 0; mindex != mc.Count; mindex+=1) {
m = mc[mindex];
if (m.Index > lastindex)
sb.Append(linetok.Substring(lastindex, m.Index - lastindex));
gc = m.Groups; //gc[1] is the command with parenthesis, gc[2] is all the params
sb.Append(gc[1]);
switch (gc[1].Value) {
case "\\pos(":
split = gc[2].Value.Split(",".ToCharArray());
sb.Append(String.Format("{0},{1}",
Math.Round((double.Parse(split[0], Util.nfi) * scalefactorx), 0),
Math.Round((double.Parse(split[1], Util.nfi) * scalefactory), 0)));
break;
case "\\org(":
split = gc[2].Value.Split(",".ToCharArray());
sb.Append(String.Format("{0},{1}",
Math.Round((double.Parse(split[0], Util.nfi) * scalefactorx), 0),
Math.Round((double.Parse(split[1], Util.nfi) * scalefactory), 0)));
break;
case "\\clip(":
split = gc[2].Value.Split(",".ToCharArray());
// if it doesn't have 4 tokens, it's either malformed or a drawing type clip
// and if it's a drawing type clip, the drawing itself will be caught later
if (split.Length == 4) {
try {
String.Format("{0},{1},{2},{3}",
Math.Round((double.Parse(split[0], Util.cfi) * scalefactorx), 0),
Math.Round((double.Parse(split[1], Util.cfi) * scalefactory), 0),
Math.Round((double.Parse(split[2], Util.cfi) * scalefactorx), 0),
Math.Round((double.Parse(split[3], Util.cfi) * scalefactory), 0));
} catch { }
}
break;
case "\\move(":
split = gc[2].Value.Split(",".ToCharArray());
tokindex = 0;
for (tokindex = 0; tokindex != split.Length; tokindex+=1) {
if (tokindex != 1) sb.Append(",");
if (tokindex < 5)
//Tokens will alternate x and y, so tokindex&1==0 should mean x, otherwise y
sb.Append(Math.Round((double.Parse(split[tokindex], Util.cfi) * (((tokindex&1) == 0) ? scalefactorx : scalefactory)), 0));
else //5 and 6 are times, don't scale them
sb.Append(split[tokindex]);
}
break;
case "\\bord":
sb.Append(Math.Round((double.Parse(gc[2].Value, Util.cfi) * scalefactory), 0));
break;
case "\\shad":
sb.Append(Math.Round((double.Parse(gc[2].Value, Util.cfi) * scalefactory), 0));
break;
case "\\fs":
sb.Append(Math.Round((double.Parse(gc[2].Value, Util.cfi) * scalefactory), 0));
break;
case "\\fsp":
sb.Append(Math.Round((double.Parse(gc[2].Value, Util.cfi) * scalefactorx), 0));
break;
case "\\pbo":
sb.Append(Math.Round((double.Parse(gc[2].Value, Util.cfi) * scalefactory), 0));
break;
default:
sb.Append(gc[2]); // don't know what it is, don't touch the params
break;
}
lastindex = m.Index + m.Length;
}
if (linetok.Length > lastindex)
sb.Append(linetok.Substring(lastindex, linetok.Length - lastindex));
if (rscaledrawing.IsMatch(linetok)) { // linetok isn't current yet but it's enough to just find a match
linetok = sb.ToString();
x = true; // x first
sb = new StringBuilder(1024);
lastindex = 0;
mc = rscaledrawing.Matches(linetok);
for (int mindex = 0; mindex != mc.Count; mindex+=1) {
m = mc[mindex];
pscale = int.Parse(m.Groups["scale"].Value);
foreach (Capture c in m.Groups["num"].Captures) {
if (c.Index > lastindex)
sb.Append(linetok.Substring(lastindex, c.Index - lastindex));
sb.Append((pscale > 0) ? Math.Round(double.Parse(c.Value) * (x ? scalefactorx : scalefactory), 0).ToString(Util.cfi) : c.Value);
x = !x; // Alternate X and Y
lastindex = c.Index + c.Length;
}
}
if (linetok.Length > lastindex)
sb.Append(linetok.Substring(lastindex, linetok.Length - lastindex));
}
dl.text = sb.ToString();
return dl;
}
}
}

172
SSATool/SSATool.csproj Normal file
View file

@ -0,0 +1,172 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectType>Local</ProjectType>
<ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{0C46ECAB-3C2E-43E6-A039-99ADC77F50E7}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ApplicationIcon>ssa24ov.ico</ApplicationIcon>
<AssemblyKeyContainerName>
</AssemblyKeyContainerName>
<AssemblyName>SSATool</AssemblyName>
<AssemblyOriginatorKeyFile>ssatool.snk</AssemblyOriginatorKeyFile>
<DefaultClientScript>JScript</DefaultClientScript>
<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
<DefaultTargetSchema>IE50</DefaultTargetSchema>
<DelaySign>false</DelaySign>
<OutputType>WinExe</OutputType>
<RootNamespace>SSATool</RootNamespace>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
<StartupObject>
</StartupObject>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<SignManifests>false</SignManifests>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<OutputPath>bin\Debug\</OutputPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>true</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<NoStdLib>false</NoStdLib>
<NoWarn>
</NoWarn>
<Optimize>true</Optimize>
<RegisterForComInterop>false</RegisterForComInterop>
<RemoveIntegerChecks>false</RemoveIntegerChecks>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<DebugType>full</DebugType>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<OutputPath>bin\Release\</OutputPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>TRACE</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>false</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<NoStdLib>false</NoStdLib>
<NoWarn>
</NoWarn>
<Optimize>true</Optimize>
<RegisterForComInterop>false</RegisterForComInterop>
<RemoveIntegerChecks>false</RemoveIntegerChecks>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<DebugType>none</DebugType>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<Reference Include="System">
<Name>System</Name>
</Reference>
<Reference Include="System.Data">
<Name>System.Data</Name>
</Reference>
<Reference Include="System.Drawing">
<Name>System.Drawing</Name>
</Reference>
<Reference Include="System.Windows.Forms">
<Name>System.Windows.Forms</Name>
</Reference>
<Reference Include="System.Xml">
<Name>System.XML</Name>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Condition.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="ConditionDialog.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="DetectEncoding.cs" />
<Compile Include="Filter.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="formEffectsEditor.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="InputBox.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Layer.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Line.cs" />
<Compile Include="ListViewES.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="ManualTransform.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Notebox.cs" />
<Compile Include="Resscale.cs" />
<Compile Include="SaveFileDialogWithEncoding.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Evaluate.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Style.cs" />
<Compile Include="TimeCodes.cs" />
<Compile Include="Undo.cs" />
<Compile Include="util.cs">
<SubType>Code</SubType>
</Compile>
<EmbeddedResource Include="ConditionDialog.resx">
<DependentUpon>ConditionDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Form1.ja.resx">
<DependentUpon>Form1.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="formEffectsEditor.resx">
<DependentUpon>formEffectsEditor.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="InputBox.resx">
<DependentUpon>InputBox.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="ListViewES.resx">
<DependentUpon>ListViewES.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<Content Include="ssa24ov.ico" />
</ItemGroup>
<ItemGroup>
<None Include="ssatool.snk" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
</Project>

View file

@ -0,0 +1,70 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<LastOpenVersion>7.10.3077</LastOpenVersion>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ReferencePath>
</ReferencePath>
<CopyProjectDestinationFolder>
</CopyProjectDestinationFolder>
<CopyProjectUncPath>
</CopyProjectUncPath>
<CopyProjectOption>0</CopyProjectOption>
<ProjectView>ProjectFiles</ProjectView>
<ProjectTrust>0</ProjectTrust>
<PublishUrlHistory>publish\</PublishUrlHistory>
<InstallUrlHistory>
</InstallUrlHistory>
<SupportUrlHistory>
</SupportUrlHistory>
<UpdateUrlHistory>
</UpdateUrlHistory>
<BootstrapperUrlHistory>
</BootstrapperUrlHistory>
<ApplicationRevision>0</ApplicationRevision>
<FallbackCulture>en-US</FallbackCulture>
<VerifyUploadedFiles>false</VerifyUploadedFiles>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<EnableASPDebugging>false</EnableASPDebugging>
<EnableASPXDebugging>false</EnableASPXDebugging>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
<EnableSQLServerDebugging>false</EnableSQLServerDebugging>
<RemoteDebugEnabled>false</RemoteDebugEnabled>
<RemoteDebugMachine>
</RemoteDebugMachine>
<StartAction>Project</StartAction>
<StartArguments>
</StartArguments>
<StartPage>
</StartPage>
<StartProgram>
</StartProgram>
<StartURL>
</StartURL>
<StartWorkingDirectory>
</StartWorkingDirectory>
<StartWithIE>true</StartWithIE>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<EnableASPDebugging>false</EnableASPDebugging>
<EnableASPXDebugging>false</EnableASPXDebugging>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
<EnableSQLServerDebugging>false</EnableSQLServerDebugging>
<RemoteDebugEnabled>false</RemoteDebugEnabled>
<RemoteDebugMachine>
</RemoteDebugMachine>
<StartAction>Project</StartAction>
<StartArguments>
</StartArguments>
<StartPage>
</StartPage>
<StartProgram>
</StartProgram>
<StartURL>
</StartURL>
<StartWorkingDirectory>
</StartWorkingDirectory>
<StartWithIE>true</StartWithIE>
</PropertyGroup>
</Project>

19
SSATool/SSATool.sln Normal file
View file

@ -0,0 +1,19 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual C# Express 2005
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SSATool", "SSATool.csproj", "{0C46ECAB-3C2E-43E6-A039-99ADC77F50E7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0C46ECAB-3C2E-43E6-A039-99ADC77F50E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0C46ECAB-3C2E-43E6-A039-99ADC77F50E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0C46ECAB-3C2E-43E6-A039-99ADC77F50E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0C46ECAB-3C2E-43E6-A039-99ADC77F50E7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

BIN
SSATool/SSATool.suo Normal file

Binary file not shown.

BIN
SSATool/SSAToolsource.rar Normal file

Binary file not shown.

View file

@ -0,0 +1,346 @@
using System;
using System.Collections;
using System.Windows.Forms;
using System.Data;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;
public enum EncodingType {
//UTF8=0,
//UTF8WithPreamble,
//Unicode,
//Ansi
ANSI,
BigEndianUnicode,
Unicode,
UTF8,
Shift_JIS
};
public class SaveFileDialogWithEncoding {
private delegate int OFNHookProcDelegate(int hdlg, int msg, int wParam, int lParam);
private int m_LabelHandle=0;
private int m_ComboHandle=0;
private string m_Filter="";
private string m_DefaultExt="";
private string m_FileName="";
private EncodingType m_EncodingType;
private Screen m_ActiveScreen;
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
private struct OPENFILENAME {
public int lStructSize;
public IntPtr hwndOwner;
public int hInstance;
[MarshalAs(UnmanagedType.LPTStr)] public string lpstrFilter;
[MarshalAs(UnmanagedType.LPTStr)] public string lpstrCustomFilter;
public int nMaxCustFilter;
public int nFilterIndex;
[MarshalAs(UnmanagedType.LPTStr)] public string lpstrFile;
public int nMaxFile;
[MarshalAs(UnmanagedType.LPTStr)] public string lpstrFileTitle;
public int nMaxFileTitle;
[MarshalAs(UnmanagedType.LPTStr)] public string lpstrInitialDir;
[MarshalAs(UnmanagedType.LPTStr)] public string lpstrTitle;
public int Flags;
public short nFileOffset;
public short nFileExtension;
[MarshalAs(UnmanagedType.LPTStr)] public string lpstrDefExt;
public int lCustData;
public OFNHookProcDelegate lpfnHook;
[MarshalAs(UnmanagedType.LPTStr)] public string lpTemplateName;
//only if on nt 5.0 or higher
public int pvReserved;
public int dwReserved;
public int FlagsEx;
}
[DllImport("Comdlg32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern bool GetSaveFileName(ref OPENFILENAME lpofn);
[DllImport("Comdlg32.dll")]
private static extern int CommDlgExtendedError();
[DllImport("user32.dll")]
private static extern bool SetWindowPos(int hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
private struct RECT {
public int Left;
public int Top;
public int Right;
public int Bottom;
}
private struct POINT {
public int X;
public int Y;
}
private struct NMHDR {
public int HwndFrom;
public int IdFrom;
public int Code;
}
[DllImport("user32.dll")]
private static extern bool GetWindowRect(int hWnd, ref RECT lpRect);
[DllImport("user32.dll")]
private static extern int GetParent(int hWnd);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern bool SetWindowText(int hWnd, string lpString);
[DllImport("user32.dll")]
private static extern int SendMessage(int hWnd, int Msg, int wParam, int lParam);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern int SendMessage(int hWnd, int Msg, int wParam, string lParam);
[DllImport("user32.dll")]
private static extern bool DestroyWindow(int hwnd);
private const int OFN_ENABLEHOOK=0x00000020;
private const int OFN_EXPLORER=0x00080000;
private const int OFN_FILEMUSTEXIST=0x00001000;
private const int OFN_HIDEREADONLY=0x00000004;
private const int OFN_CREATEPROMPT=0x00002000;
private const int OFN_NOTESTFILECREATE=0x00010000;
private const int OFN_OVERWRITEPROMPT=0x00000002;
private const int OFN_PATHMUSTEXIST=0x00000800;
private const int SWP_NOSIZE=0x0001;
private const int SWP_NOMOVE=0x0002;
private const int SWP_NOZORDER=0x0004;
private const int WM_INITDIALOG=0x110;
private const int WM_DESTROY=0x2;
private const int WM_SETFONT=0x0030;
private const int WM_GETFONT=0x0031;
private const int CBS_DROPDOWNLIST=0x0003;
private const int CBS_HASSTRINGS=0x0200;
private const int CB_ADDSTRING=0x0143;
private const int CB_SETCURSEL=0x014E;
private const int CB_GETCURSEL=0x0147;
private const uint WS_VISIBLE=0x10000000;
private const uint WS_CHILD=0x40000000;
private const uint WS_TABSTOP=0x00010000;
private const int CDN_FILEOK=-606;
private const int WM_NOTIFY=0x004E;
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern int GetDlgItem(int hDlg, int nIDDlgItem);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern int CreateWindowEx(int dwExStyle, string lpClassName, string lpWindowName, uint dwStyle, int x, int y, int nWidth, int nHeight, int hWndParent, int hMenu, int hInstance, int lpParam);
[DllImport("user32.dll")]
private static extern bool ScreenToClient(int hWnd, ref POINT lpPoint);
private int HookProc(int hdlg, int msg, int wParam, int lParam) {
switch (msg) {
case WM_INITDIALOG:
//we need to centre the dialog
Rectangle sr=m_ActiveScreen.Bounds;
RECT cr=new RECT();
int parent=GetParent(hdlg);
GetWindowRect(parent, ref cr);
int x=(sr.Right + sr.Left - (cr.Right-cr.Left))/2;
int y=(sr.Bottom + sr.Top - (cr.Bottom-cr.Top))/2;
SetWindowPos(parent, 0, x, y, cr.Right-cr.Left, cr.Bottom - cr.Top + 32, SWP_NOZORDER);
//we need to find the label to position our new label under
int fileTypeWindow=GetDlgItem(parent, 0x441);
RECT aboveRect=new RECT();
GetWindowRect(fileTypeWindow, ref aboveRect);
//now convert the label's screen co-ordinates to client co-ordinates
POINT point=new POINT();
point.X=aboveRect.Left;
point.Y=aboveRect.Bottom;
ScreenToClient(parent, ref point);
//create the label
int labelHandle=CreateWindowEx(0, "STATIC", "mylabel", WS_VISIBLE | WS_CHILD | WS_TABSTOP, point.X, point.Y + 12, 200, 100, parent, 0, 0, 0);
SetWindowText(labelHandle, "&Encoding:");
int fontHandle=SendMessage(fileTypeWindow, WM_GETFONT, 0, 0);
SendMessage(labelHandle, WM_SETFONT, fontHandle, 0);
//we now need to find the combo-box to position the new combo-box under
int fileComboWindow=GetDlgItem(parent, 0x470);
aboveRect=new RECT();
GetWindowRect(fileComboWindow, ref aboveRect);
point=new POINT();
point.X=aboveRect.Left;
point.Y=aboveRect.Bottom;
ScreenToClient(parent, ref point);
POINT rightPoint=new POINT();
rightPoint.X=aboveRect.Right;
rightPoint.Y=aboveRect.Top;
ScreenToClient(parent, ref rightPoint);
//we create the new combobox
int comboHandle=CreateWindowEx(0, "ComboBox", "mycombobox", WS_VISIBLE | WS_CHILD | CBS_HASSTRINGS | CBS_DROPDOWNLIST | WS_TABSTOP, point.X, point.Y + 8, rightPoint.X-point.X, 100, parent, 0, 0, 0);
SendMessage(comboHandle, WM_SETFONT, fontHandle, 0);
//and add the encodings we want to offer
SendMessage(comboHandle, CB_ADDSTRING, 0, "ANSI");
SendMessage(comboHandle, CB_ADDSTRING, 0, "BigEndianUnicode");
SendMessage(comboHandle, CB_ADDSTRING, 0, "Unicode");
SendMessage(comboHandle, CB_ADDSTRING, 0, "UTF-8");
SendMessage(comboHandle, CB_ADDSTRING, 0, "SJIS");
SendMessage(comboHandle, CB_SETCURSEL, (int)m_EncodingType, 0);
//remember the handles of the controls we have created so we can destroy them after
m_LabelHandle=labelHandle;
m_ComboHandle=comboHandle;
break;
case WM_DESTROY:
//destroy the handles we have created
if (m_ComboHandle!=0) {
DestroyWindow(m_ComboHandle);
}
if (m_LabelHandle!=0) {
DestroyWindow(m_LabelHandle);
}
break;
case WM_NOTIFY:
//we need to intercept the CDN_FILEOK message
//which is sent when the user selects a filename
NMHDR nmhdr=(NMHDR)Marshal.PtrToStructure(new IntPtr(lParam), typeof(NMHDR));
if (nmhdr.Code==CDN_FILEOK) {
//a file has been selected
//we need to get the encoding
m_EncodingType=(EncodingType)SendMessage(m_ComboHandle, CB_GETCURSEL, 0, 0);
}
break;
}
return 0;
}
public string DefaultExt {
get { return m_DefaultExt; }
set { m_DefaultExt=value; }
}
public string Filter {
get { return m_Filter; }
set { m_Filter=value; }
}
public string FileName {
get { return m_FileName; }
set { m_FileName=value; }
}
public EncodingType EncodingType {
get { return m_EncodingType; }
set { m_EncodingType=value; }
}
public DialogResult ShowDialog(IntPtr ownerhwnd, Screen ownerscreen) {
return ShowDialog(ownerhwnd,ownerscreen,"Unicode");
}
public DialogResult ShowDialog(IntPtr ownerhwnd, Screen ownerscreen, string encoding) {
//m_EncodingType = stringToEncodingType(encoding);
//set up the struct and populate it
OPENFILENAME ofn=new OPENFILENAME();
ofn.lStructSize= Marshal.SizeOf( ofn );
ofn.lpstrFilter= m_Filter.Replace('|', '\0') + '\0';
ofn.lpstrFile = m_FileName + new string(' ', 512);
ofn.nMaxFile= ofn.lpstrFile.Length;
ofn.lpstrFileTitle= System.IO.Path.GetFileName(m_FileName) + new string(' ', 512);
ofn.nMaxFileTitle = ofn.lpstrFileTitle.Length;
ofn.lpstrTitle= "Save file as";
ofn.lpstrDefExt=m_DefaultExt;
//position the dialog above the active window
ofn.hwndOwner=ownerhwnd;
//we need to find out the active screen so the dialog box is
//centred on the correct display
m_ActiveScreen=ownerscreen;
//set up some sensible flags
ofn.Flags=OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_NOTESTFILECREATE | OFN_ENABLEHOOK | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
//this is where the hook is set. Note that we can use a C# delegate in place of a C function pointer
ofn.lpfnHook=new OFNHookProcDelegate(HookProc);
//if we're running on Windows 98/ME then the struct is smaller
if (System.Environment.OSVersion.Platform!=PlatformID.Win32NT) {
ofn.lStructSize-=12;
}
//show the dialog
if (!GetSaveFileName(ref ofn)) {
int ret=CommDlgExtendedError();
if (ret!=0) {
throw new ApplicationException("Couldn't show file open dialog - " + ret.ToString());
}
return DialogResult.Cancel;
}
m_FileName=ofn.lpstrFile;
return DialogResult.OK;
}
public static System.Text.Encoding stringToEncodingType(string input) {
unsafe {
switch (input) {
case "ASCII" : return System.Text.Encoding.ASCII;
case "ANSI" : return System.Text.Encoding.GetEncoding(1252);
case "BigEndianUnicode" : return System.Text.Encoding.BigEndianUnicode;
case "SJIS" :
case "Shift_JIS" : return System.Text.Encoding.GetEncoding("shift_jis");
case "UTF8" :
case "UTF-8" : return System.Text.Encoding.UTF8;
case "Unicode" :
default : return System.Text.Encoding.Unicode;
}
}
}
}

214
SSATool/Style.cs Normal file
View file

@ -0,0 +1,214 @@
/*
SSATool - A collection of utilities for Advanced Substation Alpha
Copyright (C) 2007 Dan Donovan
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; ONLY under version 2
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System;
using System.Drawing;
using System.Windows.Forms;
namespace SSATool {
/// <summary>
/// (A)SSA style (copied/adapted from VSFilter)
/// </summary>
public class Style : ICloneable {
public double outlineWidth;
public double shadowDepth;
public double fontScaleX, fontScaleY; // percent
public double fontSpacing; // +/- pixels
public double fontAngleZ, fontAngleX, fontAngleY;
public float fontSize;
public string name, fontName;
public Color[] colors; //pri,sec,outline/bg,shadow
public int marginl, marginr, margint, marginb;
public int charset;
public int scrAlignment; // 1 - 9: as on the numpad, 0: default
public int borderStyle; // 0: outline, 1: opaque box
public bool fBlur, fBold, fItalic, fUnderline, fStrikeOut;
public bool enabled;
public byte relativeTo;
public Style() {
// Set default values
name = "Default";
fontName = "Arial";
fontSize = 20;
colors = new System.Drawing.Color[4];
colors[0] = System.Drawing.Color.White;
colors[1] = System.Drawing.Color.FromArgb(0,0xFF,0xFF,0);
colors[2] = System.Drawing.Color.Black;
colors[3] = System.Drawing.Color.Black;
marginl = marginr = margint = marginb = 30;
scrAlignment = 2;
borderStyle = 0;
outlineWidth = 2;
shadowDepth = 3;
fontScaleX = fontScaleY = 100.0;
fontSpacing = 0;
fBlur = fBold = fItalic = fUnderline = false;
fontAngleZ = fontAngleX = fontAngleY = 0;
enabled = true;
}
public Style(string Name) : this() {
this.name=Name;
}
public Object Clone() {
return this.MemberwiseClone();
}
public Font GetFont() {
float size = (float)fontSize;
Font prelim = new Font(fontName, size);
FontFamily ff = prelim.FontFamily;
FontStyle fs = FontStyle.Regular;
if (fBold) fs |= FontStyle.Bold;
if (fItalic) fs |= FontStyle.Italic;
if (fUnderline) fs |= FontStyle.Underline;
if (fStrikeOut) fs |= FontStyle.Strikeout;
bool vsfilter=true;
bool scaledpi=false;
if (vsfilter)
size *= ff.GetEmHeight(fs) / (ff.GetCellAscent(fs) + ff.GetCellDescent(fs));
if (scaledpi)
size*=(72.0f/Form1.listSSAg.DpiY);
return new System.Drawing.Font(fontName, size, fs);
}
public Rectangle GetMarginRect() {
if (Form1.sver <= 5) marginb = margint;
return new Rectangle(marginl,marginr,Form1.ResX-(marginl+marginr),Form1.ResY-(margint+marginb));
}
public override bool Equals(object obj) {
if (obj is Style) {
Style s = (Style)obj;
return ((String.Equals(this.fontName, s.fontName, StringComparison.OrdinalIgnoreCase)) &&
(this.fontSize.Equals(s.fontSize)) &&
(this.fItalic.Equals(s.fItalic)) &&
(this.fUnderline.Equals(s.fUnderline)) &&
(this.fStrikeOut.Equals(s.fStrikeOut)) &&
(this.colors[0].Equals(s.colors[0])) &&
(this.colors[1].Equals(s.colors[1])) &&
(this.colors[2].Equals(s.colors[2])) &&
(this.colors[3].Equals(s.colors[3])) &&
(this.scrAlignment == s.scrAlignment) &&
(this.borderStyle == s.borderStyle) &&
(this.outlineWidth == s.outlineWidth) &&
(this.shadowDepth == s.shadowDepth) &&
(this.fontScaleX == s.fontScaleX) &&
(this.fontScaleY == s.fontScaleY) &&
(this.fontSpacing == s.fontSpacing) &&
(this.fBold == s.fBold) &&
(this.fBlur == s.fBlur) &&
(this.fontAngleZ == s.fontAngleZ) &&
(this.fontAngleX == s.fontAngleX) &&
(this.fontAngleY == s.fontAngleY));
}
else if (obj is string) return (String.Equals(this.name, (string)obj, StringComparison.OrdinalIgnoreCase));
else return false;
}
public override int GetHashCode() {
return base.GetHashCode ();
}
public override string ToString() {
uint andMask = (Form1.sver==4)?0xFFFFFF:0xFFFFFFFF; // cut out alpha if v4 with this and
string retStr = String.Format("Style: {0},{1},{2},&H{3:X6}&,&H{4:X6}&,&H{5:X6}&,&H{6:X6}&,{7},{8},",
this.name, this.fontName, this.fontSize, this.colors[0].ToArgb()&andMask,
this.colors[1].ToArgb()&andMask, this.colors[2].ToArgb()&andMask,
this.colors[3].ToArgb()&andMask, (this.fBold ? "-1" : "0"), (this.fItalic ? "-1" : "0"));
if (Form1.sver >= 5) {
retStr = String.Format("{0}{1},{2},{3},{4},{5},{6},",
retStr,
(this.fUnderline ? "-1" : "0"),
(this.fStrikeOut ? "-1" : "0"),
this.fontScaleX, this.fontScaleY,
this.fontSpacing, this.fontAngleZ);
}
retStr += String.Format("{0},{1},{2},{3},{4:G4},{5:G4},{6:G4},",
this.borderStyle, this.outlineWidth, this.shadowDepth,
this.scrAlignment, this.marginl, this.marginr, this.margint);
if (Form1.sver >= 6) retStr += Convert.ToString(this.marginb,Util.cfi) + ",";
else if (Form1.sver == 4) retStr += Convert.ToString(this.colors[0].A,Util.cfi) + ",";
retStr += Convert.ToString(this.charset,Util.cfi);
if (Form1.sver >= 6) retStr += "," + this.relativeTo.ToString(Util.cfi);
return retStr;
}
public static Style ParseStyle(string inStr) {
return ParseStyle(inStr, Form1.sver);
}
public static Style ParseStyle(string inStr, int scriptVer) {
int startpos = inStr.IndexOf(':')+1;
string[] xInfo = inStr.Substring(startpos,inStr.Length-startpos).TrimStart().Split(",".ToCharArray());
Style style = new Style();
int index;
uint alpha = (scriptVer != 4 ? 0 : (Util.ReadColor(xInfo[16]) << 24));
style.name = xInfo[0];
style.fontName = xInfo[1];
style.fontSize = float.Parse(xInfo[2]);
style.colors[0] = Util.uintToColor(Util.ReadColor(xInfo[3])+alpha);
style.colors[1] = Util.uintToColor(Util.ReadColor(xInfo[4])+alpha);
style.colors[2] = Util.uintToColor(Util.ReadColor(xInfo[5])+alpha);
style.colors[3] = Util.uintToColor(Util.ReadColor(xInfo[6])+alpha);
style.fBold = !String.Equals(xInfo[7], "0", StringComparison.Ordinal);
style.fItalic = !String.Equals(xInfo[index=8], "0", StringComparison.Ordinal);
if (scriptVer >= 5) {
style.fUnderline = !String.Equals(xInfo[++index], "0", StringComparison.Ordinal);
style.fStrikeOut = !String.Equals(xInfo[++index], "0", StringComparison.Ordinal);
style.fontScaleX = double.Parse(xInfo[++index]);
style.fontScaleY = double.Parse(xInfo[++index]);
style.fontSpacing = double.Parse(xInfo[++index]);
style.fontAngleZ = double.Parse(xInfo[++index]);
}
style.borderStyle = int.Parse(xInfo[++index]);
style.outlineWidth = double.Parse(xInfo[++index]);
style.shadowDepth = double.Parse(xInfo[++index]);
style.scrAlignment = int.Parse(xInfo[++index]);
style.marginl = int.Parse(xInfo[++index]);
style.marginr = int.Parse(xInfo[++index]);
style.margint = int.Parse(xInfo[++index]);
if (scriptVer >= 6) style.marginb = int.Parse(xInfo[++index]);
if (scriptVer == 4) index++; //alphaLevel is in v4 only and is taken care of at the top (uint alpha), so just advance the index
style.charset = int.Parse(xInfo[++index]);
if (scriptVer >= 6) style.relativeTo = byte.Parse(xInfo[++index]);
//Following is code from VSFilter, but since we're not interpreting this, merely spitting it back out the way it came in, we don't currently need it
//if (sver <= 4) style.scrAlignment = ((style.scrAlignment & 4) == 1) ? ((style.scrAlignment & 3) + 6) // top
// : ((style.scrAlignment & 8) == 1) ? ((style.scrAlignment & 3) + 3) // mid
// : (style.scrAlignment & 3); // bottom
return style;
}
}
}

101
SSATool/TimeCodes.cs Normal file
View file

@ -0,0 +1,101 @@
/*
SSATool - A collection of utilities for Advanced Substation Alpha
Copyright (C) 2007 Dan Donovan
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; ONLY under version 2
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System;
using System.Text;
using System.IO;
namespace SSATool {
public class TimeCodes {
private float[] times;
private double frameRate;
public TimeCodes(string filename, double frameRate) {
this.frameRate = frameRate;
double AssumeFPS = 29.97;
string thisline;
int frames = 0, index;
bool v1;
StreamReader fs = new StreamReader(filename);
thisline = fs.ReadLine(); // Save the first line now
if (string.Compare(thisline, "# timecode format v1", true, Util.cfi) == 0) v1 = true;
else if (string.Compare(thisline, "# timecode format v2", true, Util.cfi) == 0) v1 = false;
else throw new InvalidDataException("File was not detected as an MKV TimeCode v1 or v2 file.");
//count frames
while (!fs.EndOfStream) {
if ((fs.Peek() != '#') && ((thisline = fs.ReadLine()).Length > 3)) {
if (v1 == false) frames+=1;
else frames = Math.Max(frames, int.Parse(thisline.Split(",".ToCharArray())[1]));
}
else if ((fs.Peek() == 'A' || fs.Peek() == 'a') && (string.Compare(thisline.Split(" ".ToCharArray())[0], "assumefps", true, Util.cfi) == 0))
AssumeFPS = double.Parse(thisline.Split(" ".ToCharArray())[1]);
}
fs.Close();
//restart, actually saving info
fs = new StreamReader(filename);
while ((fs.Peek() == '#') || (fs.Peek() == 'a') || (fs.Peek() == 'A'))
fs.ReadLine();
times = new float[frames];
for (index = 0;index < frames;index+=1) {
if (v1) {
string[] splitv1 = fs.ReadLine().Split(",".ToCharArray());
for (;index <= int.Parse(splitv1[1]);index+=1) // frames is the number of frames with v1, so index SHOULD go up for every frame
times[index] = ((index != 0) ? times[index - 1] : 0) + (float)(1.0 / ((splitv1.Length == 3) ? float.Parse(splitv1[2]) : AssumeFPS));
}
else
times[index] = float.Parse(fs.ReadLine());
}
fs.Close();
}
/// <summary>
/// Finds the frame number of a given VFR time, so that frame number can be used to convert to a CFR time
/// </summary>
/// <param name="time">The time in MILLISECONDS</param>
/// <returns></returns>
public int FindFrame(float time) {
int k, low = 0, high = times.Length-1;
while (low!=high) {
k=(int)Math.Ceiling((high+low)/2.0f);
if (times[k].CompareTo(time) == -1)
low=k;
else if (k!=0 && times[k-1].CompareTo(time) == -1)
return k;
else high=k;
}
return 0;
}
public TimeSpan GetTimeInverse(TimeSpan time) {
int frame = System.Convert.ToInt32(time.TotalSeconds * frameRate, Util.cfi);
return TimeSpan.FromMilliseconds((frame<times.Length)?times[frame]:0);
}
public TimeSpan GetTime(TimeSpan time) {
return TimeSpan.FromSeconds(FindFrame((float)time.TotalMilliseconds) / frameRate);
}
}
}

44
SSATool/Undo.cs Normal file
View file

@ -0,0 +1,44 @@
/*
SSATool - A collection of utilities for Advanced Substation Alpha
Copyright (C) 2007 Dan Donovan
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; ONLY under version 2
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace SSATool {
//This could be simplified
public struct Undo {
public List<int> DeleteLines;
public List<UndoLine> AddLines;
}
public struct UndoLine {
public int index;
public Line line;
}
public struct LineUndo {
public int index;
public Line line;
}
public struct LineCUndo {
public int index;
public Line line;
}
}

103
SSATool/effects.aas Normal file
View file

@ -0,0 +1,103 @@
Name=Raw code (first \k only)
Code=$Code$
FstK=True
ONam=Code
ODef=
Name=Position
Code=\pos($x$,$y$)
FstK=True
ONam=x
ODef=
ONam=y
ODef=
Name=Origin
Code=\org($x$,$y$)
FstK=True
ONam=x
ODef=
ONam=y
ODef=
Name=Transformation
Code=\t($Start Time$,$End Time$,$Acceleration$,$Code$)
ONam=Start Time
ODef=%karastart%
ONam=End Time
ODef=%karaend%
ONam=Acceleration
ODef=1
ONam=Code
ODef=
Name=Move
Code=\move($Start X$,$Start Y$,$End X$,$End Y$,$Start Time$,$End Time$)
FstK=True
ONam=Start X
ODef=
ONam=Start Y
ODef=
ONam=End X
ODef=
ONam=End Y
ODef=
ONam=Start Time
ODef=
ONam=End Time
ODef=
Name=Revert
Code=\r
Name=Expanding Border
Code=\bord$Initial Border Size$\3a&$Initial Border Alpha$\t(%karastart%,%karaend%,\bord$Expanded Border Size$\3a&$Expanded Border Alpha$&)\t(%karaend%,%karaend%,\bord$Initial Border Size$\3a&$Initial Border Alpha$&)
ONam=Initial Border Size
ODef=1
ONam=Expanded Border Size
ODef=12
ONam=Initial Border Alpha
ODef=H00
ONam=Expanded Border Alpha
ODef=H60
Name=Font Size
Code=\fs$Size$
ONam=Size
ODef=20
Name=Font Scaling (X)
Code=\fscx$Scaling$
ONam=Scaling
ODef=100
Name=Font Scaling (X)
Code=\fscy$Scaling$
ONam=Scaling
ODef=100
Name=Font Spacing (X)
Code=\fspx$Spacing$
ONam=Spacing
ODef=0
Name=Font Spacing (Y)
Code=\fspy$Spacing$
ONam=Spacing
ODef=0
Name=Font Rotation (X)
Code=\frx$Rotation$
ONam=Rotation
ODef=0
Name=Font Rotation (Y)
Code=\fry$Rotation$
ONam=Rotation
ODef=0
Name=Font Rotation (Z)
Code=\frz$Rotation$
ONam=Rotation
ODef=0

9
SSATool/effects.exml Normal file
View file

@ -0,0 +1,9 @@
<?xml version="1.0"?>
<ESSA>
<Effect Name="Transformation" Code="\t($Start Time$,$End Time$,$Acceleration$,$Code$)">
<Option Name="Start Time">%karastart%</Option>
<Option Name="End Time">%karaend%</Option>
<Option Name="Acceleration">1</Option>
<Option Name="Code"></Option>
</Effect>
</ESSA>

View file

@ -0,0 +1,434 @@
/*
SSATool - A collection of utilities for Advanced Substation Alpha
Copyright (C) 2007 Dan Donovan
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; ONLY under version 2
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System;
using System.Drawing;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
namespace SSATool
{
/// <summary>
/// Summary description for formEffectsEditor.
/// </summary>
public class formEffectsEditor : System.Windows.Forms.Form
{
#region form stuff
private System.Windows.Forms.MainMenu mainMenu1;
private System.Windows.Forms.MenuItem menuItem1;
private System.Windows.Forms.MenuItem menuItem4;
private System.Windows.Forms.Button cmdNewEffect;
private System.Windows.Forms.Button cmdDelEffect;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox txtCode;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.TextBox txtDefaultVal;
private System.Windows.Forms.TextBox txtOptName;
private System.ComponentModel.Container components = null;
private System.Windows.Forms.ListBox lstEffects;
private System.Windows.Forms.Button cmdChangeOpt;
private System.Windows.Forms.Button cmdRemoveOpt;
private System.Windows.Forms.Button cmdNewOpt;
private System.Windows.Forms.ListBox lstParams;
private System.Windows.Forms.MenuItem menuLoadEffectsFile;
private System.Windows.Forms.MenuItem menuSaveEffectsFile;
private System.Windows.Forms.MenuItem menuClose;
private System.Windows.Forms.Button cmdChangeCode;
#endregion
private System.Collections.Generic.List<Filter> tColl;
public formEffectsEditor(System.Collections.Generic.List<Filter> templateFilterColl) {
InitializeComponent();
tColl = templateFilterColl;
}
public formEffectsEditor() {
InitializeComponent();
tColl = new System.Collections.Generic.List<Filter>();
}
protected override void Dispose(bool disposing) {
if(disposing) {
if(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.lstEffects = new System.Windows.Forms.ListBox();
this.mainMenu1 = new System.Windows.Forms.MainMenu();
this.menuItem1 = new System.Windows.Forms.MenuItem();
this.menuLoadEffectsFile = new System.Windows.Forms.MenuItem();
this.menuSaveEffectsFile = new System.Windows.Forms.MenuItem();
this.menuItem4 = new System.Windows.Forms.MenuItem();
this.menuClose = new System.Windows.Forms.MenuItem();
this.cmdNewEffect = new System.Windows.Forms.Button();
this.cmdDelEffect = new System.Windows.Forms.Button();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.cmdChangeCode = new System.Windows.Forms.Button();
this.txtOptName = new System.Windows.Forms.TextBox();
this.txtDefaultVal = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.txtCode = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.cmdChangeOpt = new System.Windows.Forms.Button();
this.cmdRemoveOpt = new System.Windows.Forms.Button();
this.cmdNewOpt = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.lstParams = new System.Windows.Forms.ListBox();
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// lstEffects
//
this.lstEffects.Location = new System.Drawing.Point(0, 8);
this.lstEffects.Name = "lstEffects";
this.lstEffects.Size = new System.Drawing.Size(160, 251);
this.lstEffects.TabIndex = 0;
this.lstEffects.SelectedIndexChanged += new System.EventHandler(this.lstEffects_SelectedIndexChanged);
//
// mainMenu1
//
this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.menuItem1});
//
// menuItem1
//
this.menuItem1.Index = 0;
this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.menuLoadEffectsFile,
this.menuSaveEffectsFile,
this.menuItem4,
this.menuClose});
this.menuItem1.Text = "File";
//
// menuLoadEffectsFile
//
this.menuLoadEffectsFile.Index = 0;
this.menuLoadEffectsFile.Text = "Load Effects File";
//
// menuSaveEffectsFile
//
this.menuSaveEffectsFile.Index = 1;
this.menuSaveEffectsFile.Text = "Save Effects File";
this.menuSaveEffectsFile.Click += new System.EventHandler(this.menuSaveEffectsFile_Click);
//
// menuItem4
//
this.menuItem4.Index = 2;
this.menuItem4.Text = "-";
//
// menuClose
//
this.menuClose.Index = 3;
this.menuClose.Text = "Exit";
this.menuClose.Click += new System.EventHandler(this.menuClose_Click);
//
// cmdNewEffect
//
this.cmdNewEffect.Location = new System.Drawing.Point(0, 264);
this.cmdNewEffect.Name = "cmdNewEffect";
this.cmdNewEffect.Size = new System.Drawing.Size(80, 24);
this.cmdNewEffect.TabIndex = 1;
this.cmdNewEffect.Text = "New";
this.cmdNewEffect.Click += new System.EventHandler(this.cmdNewEffect_Click);
//
// cmdDelEffect
//
this.cmdDelEffect.Location = new System.Drawing.Point(80, 264);
this.cmdDelEffect.Name = "cmdDelEffect";
this.cmdDelEffect.Size = new System.Drawing.Size(80, 24);
this.cmdDelEffect.TabIndex = 2;
this.cmdDelEffect.Text = "Remove";
this.cmdDelEffect.Click += new System.EventHandler(this.cmdDelEffect_Click);
//
// groupBox1
//
this.groupBox1.Controls.Add(this.cmdChangeCode);
this.groupBox1.Controls.Add(this.txtOptName);
this.groupBox1.Controls.Add(this.txtDefaultVal);
this.groupBox1.Controls.Add(this.label4);
this.groupBox1.Controls.Add(this.label3);
this.groupBox1.Controls.Add(this.txtCode);
this.groupBox1.Controls.Add(this.label2);
this.groupBox1.Controls.Add(this.cmdChangeOpt);
this.groupBox1.Controls.Add(this.cmdRemoveOpt);
this.groupBox1.Controls.Add(this.cmdNewOpt);
this.groupBox1.Controls.Add(this.label1);
this.groupBox1.Controls.Add(this.lstParams);
this.groupBox1.Location = new System.Drawing.Point(168, 8);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(416, 280);
this.groupBox1.TabIndex = 3;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Selected Effect";
//
// cmdChangeCode
//
this.cmdChangeCode.Location = new System.Drawing.Point(328, 256);
this.cmdChangeCode.Name = "cmdChangeCode";
this.cmdChangeCode.Size = new System.Drawing.Size(80, 18);
this.cmdChangeCode.TabIndex = 11;
this.cmdChangeCode.Text = "Change";
this.cmdChangeCode.Click += new System.EventHandler(this.cmdChangeCode_Click);
//
// txtOptName
//
this.txtOptName.Location = new System.Drawing.Point(104, 144);
this.txtOptName.Name = "txtOptName";
this.txtOptName.Size = new System.Drawing.Size(304, 20);
this.txtOptName.TabIndex = 10;
this.txtOptName.Text = "";
//
// txtDefaultVal
//
this.txtDefaultVal.Location = new System.Drawing.Point(104, 168);
this.txtDefaultVal.Name = "txtDefaultVal";
this.txtDefaultVal.Size = new System.Drawing.Size(304, 20);
this.txtDefaultVal.TabIndex = 9;
this.txtDefaultVal.Text = "";
//
// label4
//
this.label4.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
this.label4.Location = new System.Drawing.Point(8, 168);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(96, 24);
this.label4.TabIndex = 8;
this.label4.Text = "Default Value:";
this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// label3
//
this.label3.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
this.label3.Location = new System.Drawing.Point(8, 144);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(96, 24);
this.label3.TabIndex = 7;
this.label3.Text = "Option Name:";
this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// txtCode
//
this.txtCode.Location = new System.Drawing.Point(8, 256);
this.txtCode.Name = "txtCode";
this.txtCode.Size = new System.Drawing.Size(312, 20);
this.txtCode.TabIndex = 6;
this.txtCode.Text = "";
this.txtCode.TextChanged += new System.EventHandler(this.txtCode_TextChanged);
//
// label2
//
this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
this.label2.Location = new System.Drawing.Point(8, 192);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(400, 64);
this.label2.TabIndex = 5;
this.label2.Text = "Code: Put together the SSA code using the variables above (surrounded by dollar s" +
"igns, IE length would be $length$) here. You may use variables as well.";
this.label2.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
//
// cmdChangeOpt
//
this.cmdChangeOpt.Location = new System.Drawing.Point(296, 104);
this.cmdChangeOpt.Name = "cmdChangeOpt";
this.cmdChangeOpt.Size = new System.Drawing.Size(112, 24);
this.cmdChangeOpt.TabIndex = 4;
this.cmdChangeOpt.Text = "Change";
this.cmdChangeOpt.Click += new System.EventHandler(this.cmdChangeOpt_Click);
//
// cmdRemoveOpt
//
this.cmdRemoveOpt.Location = new System.Drawing.Point(296, 64);
this.cmdRemoveOpt.Name = "cmdRemoveOpt";
this.cmdRemoveOpt.Size = new System.Drawing.Size(112, 24);
this.cmdRemoveOpt.TabIndex = 3;
this.cmdRemoveOpt.Text = "Remove";
this.cmdRemoveOpt.Click += new System.EventHandler(this.cmdRemoveOpt_Click);
//
// cmdNewOpt
//
this.cmdNewOpt.Location = new System.Drawing.Point(296, 40);
this.cmdNewOpt.Name = "cmdNewOpt";
this.cmdNewOpt.Size = new System.Drawing.Size(112, 24);
this.cmdNewOpt.TabIndex = 2;
this.cmdNewOpt.Text = "New";
this.cmdNewOpt.Click += new System.EventHandler(this.cmdNewOpt_Click);
//
// label1
//
this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
this.label1.Location = new System.Drawing.Point(8, 16);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(280, 16);
this.label1.TabIndex = 1;
this.label1.Text = "Parameters";
this.label1.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
//
// lstParams
//
this.lstParams.Location = new System.Drawing.Point(8, 40);
this.lstParams.Name = "lstParams";
this.lstParams.Size = new System.Drawing.Size(280, 95);
this.lstParams.TabIndex = 0;
this.lstParams.SelectedIndexChanged += new System.EventHandler(this.lstParams_SelectedIndexChanged);
//
// formEffectsEditor
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(584, 291);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.cmdDelEffect);
this.Controls.Add(this.cmdNewEffect);
this.Controls.Add(this.lstEffects);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.ImeMode = System.Windows.Forms.ImeMode.On;
this.MaximizeBox = false;
this.Menu = this.mainMenu1;
this.Name = "formEffectsEditor";
this.Text = "SSATool Effects Editor";
this.Load += new System.EventHandler(this.formEffectsEditor_Load);
this.groupBox1.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private void formEffectsEditor_Load(object sender, System.EventArgs e) {
foreach(Filter tf in tColl)
lstEffects.Items.Add(tf.ToString());
}
private void cmdNewEffect_Click(object sender, System.EventArgs e) {
InputBoxResult newvalue = InputBox.Show("Enter the name of the new effect:","Input",String.Empty);
if (newvalue.OK == true) {
int index, cmp;
for(index=0;index<tColl.Count;index++) {
cmp = newvalue.Text.CompareTo(tColl[index].ToString());
if (cmp == 0) {
MessageBox.Show("An effect of that name already exists.");
return;
}
if (cmp == -1) break;
}
Filter nt = new Filter(newvalue.Text);
tColl.Insert(index, nt);
}
}
private void cmdDelEffect_Click(object sender, System.EventArgs e) {
if (lstEffects.SelectedItems.Count != 0) {
tColl.RemoveAt(lstEffects.SelectedIndex);
lstEffects.Items.RemoveAt(lstEffects.SelectedIndex);
}
}
private void cmdNewOpt_Click(object sender, System.EventArgs e) {
if (lstEffects.SelectedItems.Count != 0) {
(tColl[lstEffects.SelectedIndex]).AddOption("New Option",String.Empty);
lstParams.Items.Add("New Option");
}
else MessageBox.Show("Select an effect first.");
}
private void cmdRemoveOpt_Click(object sender, System.EventArgs e) {
if ((lstEffects.SelectedItems.Count != 0) && (lstParams.SelectedItems.Count != 0)) {
(tColl[lstEffects.SelectedIndex]).RemoveOptionByIndex(lstParams.SelectedIndex);
lstParams.Items.RemoveAt(lstParams.SelectedIndex);
}
else MessageBox.Show("Select an effect first.");
}
private void cmdChangeOpt_Click(object sender, System.EventArgs e) {
if ((lstEffects.SelectedItems.Count != 0) && (lstParams.SelectedItems.Count != 0)) {
(tColl[lstEffects.SelectedIndex]).SetOptionByIndex(lstParams.SelectedIndex,txtOptName.Text,txtDefaultVal.Text);
lstParams.Items.Clear();
foreach(FilterOption fo in (Filter)tColl[lstEffects.SelectedIndex]) {
lstParams.Items.Add(fo.Name);
}
}
else MessageBox.Show("Select an effect and a parameter first.");
}
private void cmdChangeCode_Click(object sender, System.EventArgs e) {
if (lstEffects.SelectedItems.Count != 0)
(tColl[lstEffects.SelectedIndex]).Code = txtCode.Text;
else MessageBox.Show("Select an effect first.");
}
private void txtCode_TextChanged(object sender, System.EventArgs e) {
if (lstEffects.SelectedItems.Count != 0)
(tColl[lstEffects.SelectedIndex]).Code = txtCode.Text;
}
private void lstEffects_SelectedIndexChanged(object sender, System.EventArgs e) {
lstParams.Items.Clear();
if (lstEffects.SelectedItems.Count != 0) {
foreach(FilterOption fo in (tColl[lstEffects.SelectedIndex])) {
lstParams.Items.Add(fo.Name);
txtCode.Text = (tColl[lstEffects.SelectedIndex]).Code;
}
}
}
private void lstParams_SelectedIndexChanged(object sender, System.EventArgs e) {
if ((lstEffects.SelectedItems.Count != 0) && (lstParams.SelectedItems.Count != 0)) {
txtOptName.Text = lstParams.Items[lstParams.SelectedIndex].ToString();
txtDefaultVal.Text = (tColl[lstEffects.SelectedIndex]).GetOptionValueByName(lstParams.Items[lstParams.SelectedIndex].ToString());
}
else
txtOptName.Text = txtDefaultVal.Text = String.Empty;
}
private void menuClose_Click(object sender, System.EventArgs e) {
this.Close();
}
private void menuSaveEffectsFile_Click(object sender, System.EventArgs e) {
SaveFileDialogWithEncoding ofd=new SaveFileDialogWithEncoding();
ofd.DefaultExt="exml";
ofd.EncodingType=EncodingType.ANSI;
ofd.Filter="XML effect files (*.exml)|*.exml|All files (*.*)|*.*";
if (ofd.ShowDialog((IntPtr)this.Handle,Screen.FromControl(this))==DialogResult.OK) {
Form1.SaveEffectsFile(ofd.FileName,tColl);
}
}
}
}

View file

@ -0,0 +1,322 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
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">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</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 forserialized 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="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>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="lstEffects.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lstEffects.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lstEffects.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="mainMenu1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="mainMenu1.Location" type="System.Drawing.Point, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</data>
<data name="mainMenu1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="menuItem1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="menuItem1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="menuLoadEffectsFile.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="menuLoadEffectsFile.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="menuSaveEffectsFile.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="menuSaveEffectsFile.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="menuItem4.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="menuItem4.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="menuClose.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="menuClose.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="cmdNewEffect.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="cmdNewEffect.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="cmdNewEffect.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="cmdDelEffect.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="cmdDelEffect.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="cmdDelEffect.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="groupBox1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="groupBox1.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>8, 8</value>
</data>
<data name="groupBox1.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="groupBox1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="groupBox1.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="groupBox1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="cmdChangeCode.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="cmdChangeCode.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="cmdChangeCode.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="txtOptName.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="txtOptName.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="txtOptName.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="txtDefaultVal.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="txtDefaultVal.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="txtDefaultVal.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="label4.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="label4.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="label4.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="label3.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="label3.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="label3.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="txtCode.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="txtCode.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="txtCode.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="label2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="label2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="label2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="cmdChangeOpt.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="cmdChangeOpt.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="cmdChangeOpt.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="cmdRemoveOpt.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="cmdRemoveOpt.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="cmdRemoveOpt.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="cmdNewOpt.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="cmdNewOpt.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="cmdNewOpt.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="label1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="label1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="label1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lstParams.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lstParams.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lstParams.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>(Default)</value>
</data>
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Name">
<value>formEffectsEditor</value>
</data>
<data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>8, 8</value>
</data>
<data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>80</value>
</data>
<data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
</root>

BIN
SSATool/public.snk Normal file

Binary file not shown.

BIN
SSATool/ssa24ov.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
SSATool/ssa24ov.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 987 B

BIN
SSATool/ssa24ov_16.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 894 B

BIN
SSATool/ssatool.snk Normal file

Binary file not shown.

18
SSATool/todo.txt Normal file
View file

@ -0,0 +1,18 @@
Short term Fixes
-(partial) Make listview ownerdraw not flicker so much
-stop karaoke tree expanding on drag-drop
Short term Improvements/optimizations
-Auto correct simple errors with error checker
-(partial) make scripting engine support ints and maybe points
For 4.4
-Line linking (probably)
For 5.0
-Gradient Preview?
-Karaoke syllable coordinate calculation
-assignment support in scripting engine

90
SSATool/tokens.cs Normal file
View file

@ -0,0 +1,90 @@
/*
SSATool - A collection of utilities for Advanced Substation Alpha
Copyright (C) 2007 Dan Donovan
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; ONLY under version 2
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System;
namespace SSATool
{
// tokens.cs
using System;
// The System.Collections namespace is made available:
using System.Collections;
// Declare the Tokens class:
public class Tokens : IEnumerable {
private string[] elements;
public Tokens(string source, char[] delimiters) {
// Parse the string into tokens:
elements = source.Split(delimiters);
}
public Tokens(string source, char[] delimiters, int max) {
// Parse the string into tokens:
elements = source.Split(delimiters,max);
}
// IEnumerable Interface Implementation:
// Declaration of the GetEnumerator() method
// required by IEnumerable
public IEnumerator GetEnumerator() {
return new TokenEnumerator(this);
}
public int Count {
get { return elements.Length; }
}
// Inner class implements IEnumerator interface:
private class TokenEnumerator : IEnumerator {
private int position = -1;
private Tokens t;
public TokenEnumerator(Tokens t) {
this.t = t;
}
// Declare the Reset method required by IEnumerator:
public void Reset() {
position = -1;
}
// Declare the MoveNext method required by IEnumerator:
public bool MoveNext()
{
if (position < t.elements.Length - 1) {
position++;
return true;
}
else
return false;
}
// Declare the Current property required by IEnumerator:
public object Current {
get { return t.elements[position]; }
}
}
}
}

158
SSATool/util.cs Normal file
View file

@ -0,0 +1,158 @@
/*
SSATool - A collection of utilities for Advanced Substation Alpha
Copyright (C) 2007 Dan Donovan
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; ONLY under version 2
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System;
using System.Text;
using System.Drawing;
using System.Globalization;
using System.Runtime.InteropServices;
namespace SSATool {
/// <summary>
/// Summary description for util.
/// </summary>
public static class Util {
public enum ScaleRatioType {
Exponential,
Logarithmic,
Polynomial //can be linear, native to ASSA's \t
}
public struct ScaleRatioS {
public double expbase;
public ScaleRatioType srt;
}
//[DllImport("User32.dll")]
//public static extern int SendMessage(IntPtr hWnd,
// uint msg, int wParam, int lParam);
//public const uint LB_INITSTORAGE = 0x01A8;
public static double ScaleRatio(double ratio, double expbase, ScaleRatioType srt) {
unsafe {
switch(srt) {
case ScaleRatioType.Polynomial :
return Math.Pow(ratio,expbase);
case ScaleRatioType.Logarithmic :
return Math.Log(1.0 + (expbase-1.0)*ratio,expbase);
default: // exponential
return Math.Pow(expbase,ratio)/expbase;
}
}
}
public static double ScaleRatio(double ratio, ScaleRatioS srs) {
return ScaleRatio(ratio,srs.expbase,srs.srt);
}
public static readonly System.Globalization.CultureInfo cfi = System.Globalization.CultureInfo.InvariantCulture;
public static readonly System.Globalization.NumberFormatInfo nfi = cfi.NumberFormat;
public static int Precision = 2;
public static float PrecisionF = 10.0F;
public static string TimeSpanSSA(TimeSpan time, bool ceil, int PadHours) {
if (ceil)
time = TimeSpan.FromMilliseconds(Math.Ceiling(time.TotalMilliseconds / PrecisionF) * PrecisionF);
float msFloat = time.Milliseconds/PrecisionF;
int ms = Convert.ToInt32(ceil?msFloat:Math.Floor(msFloat),Util.nfi);
string msString = Convert.ToString(ms, Util.nfi).PadLeft(Precision, '0');
return String.Format("{0}:{1:D2}:{2:D2}.{3}",
time.Hours.ToString(nfi).PadLeft(PadHours, '0'),
time.Minutes, time.Seconds,msString,Precision);
}
/// <summary>
/// Returns a uint from a 32-bit RGBA string. Microsoft uses an int for this, not uint, so we need this custom function.
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static uint ReadColor(string input) {
char[] charain = input.ToCharArray();
string jColor = string.Empty;
char c;
bool ishex = false;
for(int index=0;index!=charain.Length;index+=1) {
c = charain[index];
if ((c >= 48 && c <= 57) || (c >= 65 && c <= 70) || (c >= 97 && c <= 102)) {
jColor += c;
if (c>=65) ishex = true;
}
else if (c == 'H' || c == 'h') ishex = true;
}
return Math.Max(uint.Parse(jColor,ishex?NumberStyles.HexNumber:NumberStyles.None, cfi), 0);
}
public static Color uintToColor(uint input) {
return Color.FromArgb(Convert.ToInt32(((input>>24)&0xFF),Util.nfi)
,Convert.ToInt32(((input>>16)&0xFF),Util.nfi)
,Convert.ToInt32(((input>>8)&0xFF),Util.nfi)
,Convert.ToInt32((input&0xFF),Util.nfi));
}
public static Point ParseCoordinate(string input) {
//Note: This function just ignores characters it doesn't like
char[] charain = input.ToCharArray();
string buff = string.Empty;
Point p = new Point();
for (int index=0;index!=charain.Length;index+=1) {
if (char.IsDigit(charain[index])) buff += charain[index];
else if (charain[index].Equals(',')) {
p.X = int.Parse(buff, nfi);
buff = string.Empty;
}
}
p.Y = int.Parse(buff, nfi);
return p;
}
public static bool TryParseCoordinate(string input, out Point result) {
char[] charain = input.ToCharArray();
string buff = string.Empty;
Point p = new Point();
char c;
bool FoundComma = false;
for (int index = 0; index != charain.Length; index+=1) {
c = charain[index];
if (char.IsDigit(c)) buff += c;
else if (c.Equals(',')) {
p.X = int.Parse(buff, nfi);
buff = string.Empty;
FoundComma = true;
}
else {
//invalid point
result = p; // who knows what's in here, we shouldn't be using it when false is returned anyway
return false;
}
}
if (!FoundComma || String.IsNullOrEmpty(buff)) {
result = p; // who knows what's in here, we shouldn't be using it when false is returned anyway
return false; //Invalid/empty string = invalid point
}
p.Y = int.Parse(buff, nfi);
result = p;
return true;
}
}
}