1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Drawing; 5 using System.IO; 6 using System.Text; 7 using LibRender2.Primitives; 8 using OpenBveApi; 9 using OpenBveApi.Colors; 10 using OpenBveApi.Hosts; 11 using OpenBveApi.Interface; 12 using OpenBveApi.Packages; 13 using OpenBveApi.Textures; 14 using RouteManager2; 15 using Path = OpenBveApi.Path; 16 17 namespace OpenBve 18 { 19 public partial class Menu 20 { 21 private static BackgroundWorker routeWorkerThread; 22 private static BackgroundWorker packageWorkerThread; 23 private static string SearchDirectory; 24 private static string currentFile; 25 private static Encoding RouteEncoding; 26 private static RouteState RoutefileState; 27 private static readonly Picturebox routePictureBox = new Picturebox(Program.Renderer); 28 private static readonly Textbox routeDescriptionBox = new Textbox(Program.Renderer, Program.Renderer.Fonts.NormalFont, Color128.White, Color128.Black); 29 private static Dictionary<string, Texture> iconCache = new Dictionary<string, Texture>(); 30 private static Package currentPackage; 31 private static PackageOperation currentOperation; 32 private static bool packagePreview; 33 private static string installedFiles; 34 packageWorkerThread_doWork(object sender, DoWorkEventArgs e)35 private static void packageWorkerThread_doWork(object sender, DoWorkEventArgs e) 36 { 37 if (string.IsNullOrEmpty(currentFile)) 38 { 39 return; 40 } 41 42 switch (currentOperation) 43 { 44 case PackageOperation.Installing: 45 if (packagePreview) 46 { 47 try 48 { 49 currentPackage = Manipulation.ReadPackage(currentFile); 50 } 51 catch 52 { 53 // Ignored 54 } 55 56 } 57 break; 58 } 59 } 60 packageWorkerThread_completed(object sender, RunWorkerCompletedEventArgs e)61 private static void packageWorkerThread_completed(object sender, RunWorkerCompletedEventArgs e) 62 { 63 if (currentPackage != null) 64 { 65 routePictureBox.Texture = new Texture(new Bitmap(currentPackage.PackageImage)); 66 routeDescriptionBox.Text = currentPackage.Description; 67 packagePreview = false; 68 } 69 Database.SaveDatabase(); 70 } 71 routeWorkerThread_doWork(object sender, DoWorkEventArgs e)72 private static void routeWorkerThread_doWork(object sender, DoWorkEventArgs e) 73 { 74 if (string.IsNullOrEmpty(currentFile)) 75 { 76 return; 77 } 78 RouteEncoding = TextEncoding.GetSystemEncodingFromFile(currentFile); 79 Program.CurrentHost.RegisterTexture(Path.CombineFile(Program.FileSystem.DataFolder, "Menu\\loading.png"), new TextureParameters(null, null), out routePictureBox.Texture); 80 routeDescriptionBox.Text = Translations.GetInterfaceString("start_route_processing"); 81 Game.Reset(false); 82 bool loaded = false; 83 for (int i = 0; i < Program.CurrentHost.Plugins.Length; i++) 84 { 85 if (Program.CurrentHost.Plugins[i].Route != null && Program.CurrentHost.Plugins[i].Route.CanLoadRoute(currentFile)) 86 { 87 object Route = (object)Program.CurrentRoute; //must cast to allow us to use the ref keyword. 88 string RailwayFolder = Loading.GetRailwayFolder(currentFile); 89 string ObjectFolder = OpenBveApi.Path.CombineDirectory(RailwayFolder, "Object"); 90 string SoundFolder = OpenBveApi.Path.CombineDirectory(RailwayFolder, "Sound"); 91 if (Program.CurrentHost.Plugins[i].Route.LoadRoute(currentFile, RouteEncoding, null, ObjectFolder, SoundFolder, true, ref Route)) 92 { 93 Program.CurrentRoute = (CurrentRoute) Route; 94 } 95 else 96 { 97 if (Program.CurrentHost.Plugins[i].Route.LastException != null) 98 { 99 throw Program.CurrentHost.Plugins[i].Route.LastException; //Re-throw last exception generated by the route parser plugin so that the UI thread captures it 100 } 101 routeDescriptionBox.Text = "An unknown error was enountered whilst attempting to parse the routefile " + currentFile; 102 RoutefileState = RouteState.Error; 103 } 104 loaded = true; 105 break; 106 } 107 } 108 109 if (!loaded) 110 { 111 throw new Exception("No plugins capable of loading routefile " + currentFile + " were found."); 112 } 113 } 114 routeWorkerThread_completed(object sender, RunWorkerCompletedEventArgs e)115 private static void routeWorkerThread_completed(object sender, RunWorkerCompletedEventArgs e) 116 { 117 RoutefileState = RouteState.Processed; 118 if (e.Error != null || Program.CurrentRoute == null) 119 { 120 Program.CurrentHost.RegisterTexture(Path.CombineFile(Program.FileSystem.DataFolder, "Menu\\route_error.png"), new TextureParameters(null, null), out routePictureBox.Texture); 121 if (e.Error != null) 122 { 123 routeDescriptionBox.Text = e.Error.Message; 124 RoutefileState = RouteState.Error; 125 } 126 routeWorkerThread.Dispose(); 127 return; 128 } 129 try 130 { 131 // image 132 if (!string.IsNullOrEmpty(Program.CurrentRoute.Image)) 133 { 134 135 try 136 { 137 if (File.Exists(Program.CurrentRoute.Image)) 138 { 139 Program.CurrentHost.RegisterTexture(Program.CurrentRoute.Image, new TextureParameters(null, null), out routePictureBox.Texture); 140 } 141 else 142 { 143 Program.CurrentHost.RegisterTexture(Path.CombineFile(Program.FileSystem.DataFolder, "Menu\\route_unknown.png"), new TextureParameters(null, null), out routePictureBox.Texture); 144 } 145 146 } 147 catch 148 { 149 routePictureBox.Texture = null; 150 } 151 } 152 else 153 { 154 string[] f = {".png", ".bmp", ".gif", ".tiff", ".tif", ".jpeg", ".jpg"}; 155 int i; 156 for (i = 0; i < f.Length; i++) 157 { 158 string g = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(currentFile), 159 System.IO.Path.GetFileNameWithoutExtension(currentFile) + f[i]); 160 if (System.IO.File.Exists(g)) 161 { 162 try 163 { 164 using (var fs = new FileStream(g, FileMode.Open, FileAccess.Read)) 165 { 166 //pictureboxRouteImage.Image = new Bitmap(fs); 167 } 168 } 169 catch 170 { 171 //pictureboxRouteImage.Image = null; 172 } 173 break; 174 } 175 } 176 if (i == f.Length) 177 { 178 Program.CurrentHost.RegisterTexture(Path.CombineFile(Program.FileSystem.DataFolder, "Menu\\route_unknown.png"), new TextureParameters(null, null), out routePictureBox.Texture); 179 } 180 } 181 182 // description 183 string Description = Program.CurrentRoute.Comment.ConvertNewlinesToCrLf(); 184 if (Description.Length != 0) 185 { 186 routeDescriptionBox.Text = Description; 187 } 188 else 189 { 190 routeDescriptionBox.Text = System.IO.Path.GetFileNameWithoutExtension(currentFile); 191 } 192 } 193 catch (Exception ex) 194 { 195 Program.CurrentHost.RegisterTexture(Path.CombineFile(Program.FileSystem.DataFolder, "Menu\\route_error.png"), new TextureParameters(null, null), out routePictureBox.Texture); 196 routeDescriptionBox.Text = ex.Message; 197 currentFile = null; 198 } 199 } 200 OnWorkerProgressChanged(object sender, ProgressReport e)201 private static void OnWorkerProgressChanged(object sender, ProgressReport e) 202 { 203 routeDescriptionBox.Text = "Processing:" + Environment.NewLine + e.Progress + "%" + Environment.NewLine + Environment.NewLine + e.CurrentFile; 204 } 205 OnWorkerReportsProblem(object sender, ProblemReport e)206 private static void OnWorkerReportsProblem(object sender, ProblemReport e) 207 { 208 routeDescriptionBox.Text = Translations.GetInterfaceString("packages_creation_failure_error") + Environment.NewLine; 209 if (e.Exception is UnauthorizedAccessException && currentOperation != PackageOperation.Creating) 210 { 211 //User attempted to install in a directory which requires UAC access 212 routeDescriptionBox.Text += e.Exception.Message + Environment.NewLine + Environment.NewLine + Translations.GetInterfaceString("errors_security_checkaccess"); 213 if (Program.CurrentHost.Platform == HostPlatform.MicrosoftWindows) 214 { 215 routeDescriptionBox.Text += Environment.NewLine + Environment.NewLine + Translations.GetInterfaceString("errors_security_badlocation"); 216 } 217 } 218 else 219 { 220 //Non-localised string as this is a specific error message 221 routeDescriptionBox.Text += e.Exception + @"\r\n \r\n encountered whilst processing the following file: \r\n\r\n" + 222 e.CurrentFile + @" at " + e.Progress + @"% completion."; 223 //Create crash dump file 224 CrashHandler.LogCrash(e.Exception + Environment.StackTrace); 225 } 226 } 227 OnPackageOperationCompleted(object sender, CompletionReport e)228 private static void OnPackageOperationCompleted(object sender, CompletionReport e) 229 { 230 switch (e.Operation) 231 { 232 case PackageOperation.Installing: 233 routeDescriptionBox.Text = Translations.GetInterfaceString("packages_install_success") + Environment.NewLine + Environment.NewLine + Translations.GetInterfaceString("packages_install_success_files") + Environment.NewLine + installedFiles; 234 currentFile = string.Empty; 235 installedFiles = string.Empty; 236 switch (currentPackage.PackageType) 237 { 238 case PackageType.Route: 239 Database.currentDatabase.InstalledRoutes.Remove(currentPackage); 240 Database.currentDatabase.InstalledRoutes.Add(currentPackage); 241 break; 242 case PackageType.Train: 243 Database.currentDatabase.InstalledTrains.Remove(currentPackage); 244 Database.currentDatabase.InstalledTrains.Add(currentPackage); 245 break; 246 default: 247 Database.currentDatabase.InstalledOther.Remove(currentPackage); 248 Database.currentDatabase.InstalledOther.Add(currentPackage); 249 break; 250 } 251 currentPackage = null; 252 Database.SaveDatabase(); 253 break; 254 } 255 } 256 257 258 } 259 } 260