using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
namespace VPScriptEditor
{
public partial class VPScriptEditor
{
private Pointer[] inputPtr, outputPtr;
private int currPointerNb;
private string outputFileName;
private FontFile vpFont;
private Bitmap conersBmp;
public VPScriptEditor()
{
InitializeComponent();
StreamReader dfile = System.IO.File.OpenText(System.Windows.Forms.Application.StartupPath + @"\database\VP-database.xml");
vpFont = new FontFile(dfile, Color.Black);
dfile.Close();
Stream imgStream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("VPScriptEditor.corners.png");
if (imgStream == null)
throw new Exception("Can't open embedded image");
conersBmp = new Bitmap(imgStream);
this.ActiveControl = txtbxOutputPtr;
}
private Pointer[] parseXML(String content)
{
Match match = Regex.Match(content.Replace("\r\n", "\n"), "^\\n*((?:.|\\n)*?)(?:\\n\\n)?\\n*$");
if (!match.Success)
throw new Exception("Bad script format!");
MatchCollection matches = Regex.Matches(match.Groups[1].Value, "\\n(|)\\n((?:.|\\n)*?)(?=(?:\\n\\n|$))");
Pointer[] pointers = new Pointer[matches.Count];
for (int i = 0; i < matches.Count; i++)
{
int nb = int.Parse(matches[i].Groups[1].Value);
if (nb <= 0 || nb > matches.Count)
throw new Exception("Pointer no " + nb + " out of range!");
if (pointers[nb - 1] != null)
throw new Exception("Duplicate pointer no " + nb);
pointers[nb - 1] = new Pointer(matches[i].Groups[2].Value, matches[i].Groups[5].Value.Length > 0 ? WindowType.Normal : (matches[i].Groups[4].Value.Length > 0 ? WindowType.Fixed : WindowType.None), matches[i].Groups[5].Value, matches[i].Groups[6].Value, matches[i].Groups[7].Value, matches[i].Groups[8].Value, matches[i].Groups[9].Value);
}
return pointers;
}
private void OpenMenuItem_Click(System.Object sender, System.EventArgs e)
{
StreamReader sr = null;
try
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Title = "Select *original* script file";
ofd.Filter = "Valkyrie Profile script files (*.xml)|*.xml|" + "All files|*.*";
if (ofd.ShowDialog() != DialogResult.OK)
return;
String origFileName = ofd.FileName;
sr = new StreamReader(ofd.OpenFile());
inputPtr = parseXML(sr.ReadToEnd());
sr.Close();
ofd.Title = "Select *translated* script file";
while (true)
{
if (ofd.ShowDialog() != DialogResult.OK)
return;
if ((outputFileName = ofd.FileName) == origFileName)
MessageBox.Show("Select a different file than the original script!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
else
{
sr = new StreamReader(ofd.OpenFile());
outputPtr = parseXML(sr.ReadToEnd());
break;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
if (sr != null) sr.Close();
}
initInterface();
}
public string[] getText(string input)
{
string input_new = Regex.Replace(Regex.Replace(input, "(.+?)", new MatchEvaluator(delegate(Match m) { return new String(m.Groups[2].Value[0], int.Parse(m.Groups[1].Value)); })), "<.+?/>", "");
return Regex.Split(input_new, "\r\n");
}
public void updateInputPtr()
{
Pointer p = inputPtr[currPointerNb];
txtbxRoom.Text = p.rooms;
txtbxInputX.Text = p.x;
txtbxInputY.Text = p.y;
txtbxInputWidth.Text = p.width;
txtbxInputHeight.Text = p.height;
txtbxInputPtr.Text = p.content.Replace("\n", "\r\n");
}
public void updateOutputPtr()
{
Pointer p = outputPtr[currPointerNb];
txtbxOutputX.Text = p.x;
txtbxOutputY.Text = p.y;
txtbxOutputWidth.Text = p.width;
txtbxOutputHeight.Text = p.height;
txtbxOutputPtr.Text = p.content.Replace("\n", "\r\n");
bttnResize.Enabled = p.type == WindowType.Normal;
}
public void updateInterface()
{
bttnNext.Enabled = currPointerNb < inputPtr.Length - 1;
bttnPrevious.Enabled = currPointerNb > 0;
txtbxPointerNumber.Text = Convert.ToString(currPointerNb + 1);
updateInputPtr();
updateOutputPtr();
pnlInput.Invalidate();
pnlOutput.Invalidate();
}
public void updateTitle()
{
this.Text = "VPScriptEditor - " + Path.GetFileName(outputFileName);
}
public void initInterface()
{
currPointerNb = 0;
txtbxPointerNumber.Enabled = true;
bttnReset.Enabled = true;
SaveMenuItem.Enabled = SaveAsMenuItem.Enabled = true;
updateInterface();
updateTitle();
}
private void bttnNext_Click(System.Object sender, System.EventArgs e)
{
saveCurrentPointer();
++currPointerNb;
updateInterface();
}
private void bttnPrevious_Click(System.Object sender, System.EventArgs e)
{
saveCurrentPointer();
--currPointerNb;
updateInterface();
}
private void bttnReset_Click(System.Object sender, System.EventArgs e)
{
outputPtr[currPointerNb] = new Pointer(inputPtr[currPointerNb]);
updateOutputPtr();
}
private void ExitMenuItem_Click(System.Object sender, System.EventArgs e)
{
Application.Exit();
}
private void gotoPointer()
{
saveCurrentPointer();
try
{
int nb = int.Parse(txtbxPointerNumber.Text);
if (nb > 0 && nb <= inputPtr.Length)
currPointerNb = nb - 1;
else
{
MessageBox.Show("Pointer out of range. Please enter a number between 1 and " + inputPtr.Length + ".", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
}
catch (System.FormatException)
{
MessageBox.Show("Incorrect pointer number", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
finally
{
txtbxPointerNumber.Text = System.Convert.ToString(currPointerNb + 1);
}
updateInterface();
}
private bool saveOutputXML(string fileName)
{
saveCurrentPointer();
StreamWriter sw = null;
try
{
StringBuilder str = new StringBuilder("\n\n");
for (int i = 0; i < outputPtr.Length; i++)
{
Pointer p = outputPtr[i];
str.Append("\n");
if (p.type == WindowType.None)
str.Append("");
else
if (p.type == WindowType.Fixed)
str.Append("");
else
str.Append("");
str.Append("\n");
str.Append(p.content.Replace("\r\n", "\n"));
str.Append("\n\n");
}
str.Append("\n");
sw = new StreamWriter(fileName);
sw.Write(str);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
finally
{
if (sw != null) sw.Close();
}
return true;
}
private void SaveMenuItem_Click(System.Object sender, System.EventArgs e)
{
saveOutputXML(outputFileName);
}
private void SaveAsMenuItem_Click(object sender, EventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Title = "Save as";
sfd.Filter = "Valkyrie Profile script files (*.xml)|*.xml|" + "All files|*.*";
if (sfd.ShowDialog() != DialogResult.OK)
return;
if (saveOutputXML(sfd.FileName))
{
outputFileName = sfd.FileName;
updateTitle();
}
}
public void saveCurrentPointer()
{
outputPtr[currPointerNb] = new Pointer(inputPtr[currPointerNb].rooms, inputPtr[currPointerNb].type, txtbxOutputX.Text, txtbxOutputY.Text, txtbxOutputWidth.Text, txtbxOutputHeight.Text, txtbxOutputPtr.Text.Replace("\r\n", "\n"));
}
private void bttnResize_Click(System.Object sender, System.EventArgs e)
{
String[] text = getText(txtbxOutputPtr.Text);
int w = 0, h = 0;
for (int j = 0; j <= text.Length - 1; j++)
{
int curr_w = 0;
foreach (char ch in text[j])
try
{
curr_w += vpFont.getSymbolWidth(ch);
}
catch (System.Collections.Generic.KeyNotFoundException ex) { }
w = curr_w > w ? curr_w : w;
h += 14;
}
txtbxOutputWidth.Text = System.Convert.ToString(w);
txtbxOutputHeight.Text = System.Convert.ToString(h);
pnlOutput.Invalidate();
}
private Bitmap drawPointer(String[] text, string xStr, string yStr, string wStr, string hStr)
{
Bitmap bmp = new Bitmap(320, 240, PixelFormat.Format32bppArgb);
Graphics gBmp = Graphics.FromImage(bmp);
gBmp.CompositingMode = CompositingMode.SourceOver;
gBmp.FillRectangle(Brushes.White, 0, 0, bmp.Width, bmp.Height);
int x_base, x_curr, y_curr;
try
{
x_base = x_curr = int.Parse(xStr);
y_curr = int.Parse(yStr);
}
catch (System.FormatException e)
{
x_curr = x_base = y_curr = 10;
}
try
{
int h = int.Parse(hStr), w = int.Parse(wStr);
SolidBrush innerBrush = new SolidBrush(Color.FromArgb(248, 216, 96)), outerBrush = new SolidBrush(Color.FromArgb(88, 64, 8));
gBmp.FillRectangle(outerBrush, x_curr - 8, y_curr, 1, h);
gBmp.FillRectangle(innerBrush, x_curr - 7, y_curr, 2, h);
gBmp.FillRectangle(outerBrush, x_curr - 2, y_curr - 7, w + 5, 1);
gBmp.FillRectangle(innerBrush, x_curr - 2, y_curr - 6, w + 5, 2);
gBmp.FillRectangle(outerBrush, x_curr + w + 9, y_curr, 1, h);
gBmp.FillRectangle(innerBrush, x_curr + w + 7, y_curr, 2, h);
gBmp.FillRectangle(outerBrush, x_curr - 2, y_curr + h + 6, w + 5, 1);
gBmp.FillRectangle(innerBrush, x_curr - 2, y_curr + h + 4, w + 5, 2);
gBmp.DrawImage(conersBmp, x_curr - 8, y_curr - 7, new Rectangle(0, 0, 7, 7), GraphicsUnit.Pixel);
gBmp.DrawImage(conersBmp, x_curr - 8, y_curr + h, new Rectangle(0, 7, 7, 7), GraphicsUnit.Pixel);
gBmp.DrawImage(conersBmp, x_curr + w + 3, y_curr - 7, new Rectangle(7, 0, 7, 7), GraphicsUnit.Pixel);
gBmp.DrawImage(conersBmp, x_curr + w + 3, y_curr + h, new Rectangle(7, 7, 7, 7), GraphicsUnit.Pixel);
}
catch (System.FormatException e) { }
for (int j = 0; j <= text.Length - 1; j++)
{
foreach (char ch in text[j])
try
{
gBmp.DrawImage(vpFont.getBitmap(ch), x_curr, y_curr);
x_curr += vpFont.getSymbolWidth(ch);
}
catch (System.Collections.Generic.KeyNotFoundException e) { }
x_curr = x_base;
y_curr += 14;
}
return bmp;
}
private void pnlInput_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(drawPointer(getText(txtbxInputPtr.Text), txtbxInputX.Text, txtbxInputY.Text, txtbxInputWidth.Text, txtbxInputHeight.Text), 0, 0);
}
private void pnlOutput_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(drawPointer(getText(txtbxOutputPtr.Text), txtbxOutputX.Text, txtbxOutputY.Text, txtbxOutputWidth.Text, txtbxOutputHeight.Text), 0, 0);
}
private void txtbxOutput_TextChanged(object sender, EventArgs e)
{
pnlOutput.Invalidate();
}
private void txtbxPointerNumber_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Return)
{
e.Handled = true;
gotoPointer();
}
}
private void txtbxOutputPtr_KeyPress(object sender, KeyPressEventArgs e)
{
if (!vpFont.containsSymbol(e.KeyChar) && e.KeyChar >= ' ')
{
e.Handled = true;
System.Media.SystemSounds.Beep.Play();
}
}
}
}