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(); } } } }