Aegisub/SSATool/ManualTransform.cs

181 lines
5.4 KiB
C#

/*
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; }
}
}
}
}
}