public void Start(GLOFC.WinForm.GLWinFormControl glwfc, GalacticMapping edsmmapping, GalacticMapping eliteregions) { this.glwfc = glwfc; this.edsmmapping = edsmmapping; this.elitemapping = eliteregions; hptimer.Start(); items.Add(new GLMatrixCalcUniformBlock(), "MCUB"); // create a matrix uniform block int lyscale = 1; int front = -20000 / lyscale, back = front + 90000 / lyscale, left = -45000 / lyscale, right = left + 90000 / lyscale, vsize = 2000 / lyscale; if (false) // debug bounding box { Vector4[] displaylines = new Vector4[] { new Vector4(left, -vsize, front, 1), new Vector4(left, +vsize, front, 1), new Vector4(left, +vsize, front, 1), new Vector4(right, +vsize, front, 1), new Vector4(right, +vsize, front, 1), new Vector4(right, -vsize, front, 1), new Vector4(right, -vsize, front, 1), new Vector4(left, -vsize, front, 1), new Vector4(left, -vsize, back, 1), new Vector4(left, +vsize, back, 1), new Vector4(left, +vsize, back, 1), new Vector4(right, +vsize, back, 1), new Vector4(right, +vsize, back, 1), new Vector4(right, -vsize, back, 1), new Vector4(right, -vsize, back, 1), new Vector4(left, -vsize, back, 1), new Vector4(left, -vsize, front, 1), new Vector4(left, -vsize, back, 1), new Vector4(left, +vsize, front, 1), new Vector4(left, +vsize, back, 1), new Vector4(right, -vsize, front, 1), new Vector4(right, -vsize, back, 1), new Vector4(right, +vsize, front, 1), new Vector4(right, +vsize, back, 1), }; GLRenderState rl = GLRenderState.Lines(1); items.Add(new GLShaderPipeline(new GLPLVertexShaderWorldCoord(), new GLPLFragmentShaderFixedColor(Color.Yellow)), "LINEYELLOW"); rObjects.Add(items.Shader("LINEYELLOW"), GLRenderableItem.CreateVector4(items, PrimitiveType.Lines, rl, displaylines)); items.Add(new GLColorShaderWorld(), "COS-1L"); float h = 0; int dist = 1000 / lyscale; Color cr = Color.FromArgb(100, Color.White); rObjects.Add(items.Shader("COS-1L"), // horizontal GLRenderableItem.CreateVector4Color4(items, PrimitiveType.Lines, rl, GLShapeObjectFactory.CreateLines(new Vector3(left, h, front), new Vector3(left, h, back), new Vector3(dist, 0, 0), (back - front) / dist + 1), new OpenTK.Graphics.Color4[] { cr }) ); rObjects.Add(items.Shader("COS-1L"), GLRenderableItem.CreateVector4Color4(items, PrimitiveType.Lines, rl, GLShapeObjectFactory.CreateLines(new Vector3(left, h, front), new Vector3(right, h, front), new Vector3(0, 0, dist), (right - left) / dist + 1), new OpenTK.Graphics.Color4[] { cr }) ); rObjects.Add(new GLOperationClearDepthBuffer()); } int ctrlo = 2048 | 32 | 64; ctrlo = -1; if ((ctrlo & 1) != 0) // galaxy { volumetricboundingbox = new Vector4[] { new Vector4(left, -vsize, front, 1), new Vector4(left, vsize, front, 1), new Vector4(right, vsize, front, 1), new Vector4(right, -vsize, front, 1), new Vector4(left, -vsize, back, 1), new Vector4(left, vsize, back, 1), new Vector4(right, vsize, back, 1), new Vector4(right, -vsize, back, 1), }; const int gnoisetexbinding = 3; //tex bindings are attached per shaders so are not global const int gdisttexbinding = 4; const int galtexbinding = 1; volumetricblock = new GLVolumetricUniformBlock(volumenticuniformblock); items.Add(volumetricblock, "VB"); int sc = 1; GLTexture3D noise3d = new GLTexture3D(1024 * sc, 64 * sc, 1024 * sc, OpenTK.Graphics.OpenGL4.SizedInternalFormat.R32f); // red channel only items.Add(noise3d, "Noise"); ComputeShaderNoise3D csn = new ComputeShaderNoise3D(noise3d.Width, noise3d.Height, noise3d.Depth, 128 * sc, 16 * sc, 128 * sc, gnoisetexbinding); // must be a multiple of localgroupsize in csn csn.StartAction += (A, m) => { noise3d.BindImage(gnoisetexbinding); }; csn.Run(); // compute noise csn.Dispose(); GLTexture1D gaussiantex = new GLTexture1D(1024, OpenTK.Graphics.OpenGL4.SizedInternalFormat.R32f); // red channel only items.Add(gaussiantex, "Gaussian"); // set centre=width, higher widths means more curve, higher std dev compensate. // fill the gaussiantex with data ComputeShaderGaussian gsn = new ComputeShaderGaussian(gaussiantex.Width, 2.0f, 2.0f, 1.4f, gdisttexbinding); gsn.StartAction += (A, m) => { gaussiantex.BindImage(gdisttexbinding); }; gsn.Run(); // compute noise gsn.Dispose(); GL.MemoryBarrier(MemoryBarrierFlags.AllBarrierBits); // load one upside down and horz flipped, because the volumetric co-ords are 0,0,0 bottom left, 1,1,1 top right GLTexture2D galtex = new GLTexture2D(Properties.Resources.Galaxy_L180, SizedInternalFormat.Rgba8); items.Add(galtex, "galtex"); galaxyshader = new GalaxyShader(volumenticuniformblock, galtexbinding, gnoisetexbinding, gdisttexbinding); items.Add(galaxyshader, "Galaxy-sh"); // bind the galaxy texture, the 3dnoise, and the gaussian 1-d texture for the shader galaxyshader.StartAction += (a, m) => { galtex.Bind(galtexbinding); noise3d.Bind(gnoisetexbinding); gaussiantex.Bind(gdisttexbinding); }; // shader requires these, so bind using shader GLRenderState rt = GLRenderState.Tri(); galaxyrenderable = GLRenderableItem.CreateNullVertex(OpenTK.Graphics.OpenGL4.PrimitiveType.Points, rt); // no vertexes, all data from bound volumetric uniform, no instances as yet rObjects.Add(galaxyshader, "galshader", galaxyrenderable); } if ((ctrlo & 2) != 0) { var corr = new GalMapRegions.ManualCorrections[] { // nerf the centeroid position slightly new GalMapRegions.ManualCorrections("The Galactic Aphelion", y: -2000), new GalMapRegions.ManualCorrections("The Abyss", y: +3000), new GalMapRegions.ManualCorrections("Eurus", y: -3000), new GalMapRegions.ManualCorrections("The Perseus Transit", x: -3000, y: -3000), new GalMapRegions.ManualCorrections("Zephyrus", x: 0, y: 2000), }; edsmgalmapregions = new GalMapRegions(); edsmgalmapregions.CreateObjects("edsmregions", items, rObjects, edsmmapping, 8000, corr: corr); } if ((ctrlo & 4) != 0) { elitemapregions = new GalMapRegions(); elitemapregions.CreateObjects("eliteregions", items, rObjects, eliteregions, 8000); EliteRegionsEnable = false; } if ((ctrlo & 8) != 0) { int gran = 8; Bitmap img = Properties.Resources.Galaxy_L180; Bitmap heat = img.Function(img.Width / gran, img.Height / gran, mode: GLOFC.Utils.BitMapHelpers.BitmapFunction.HeatMap); heat.Save(@"c:\code\heatmap.jpg", System.Drawing.Imaging.ImageFormat.Jpeg); Random rnd = new Random(23); GLBuffer buf = items.NewBuffer(16 * 350000, false); // since RND is fixed, should get the same number every time. buf.StartWrite(0); // get a ptr to the whole schebang int xcw = (right - left) / heat.Width; int zch = (back - front) / heat.Height; int points = 0; for (int x = 0; x < heat.Width; x++) { for (int z = 0; z < heat.Height; z++) { int i = heat.GetPixel(x, z).R; if (i > 32) { int gx = left + x * xcw; int gz = front + z * zch; float dx = (float)Math.Abs(gx) / 45000; float dz = (float)Math.Abs(25889 - gz) / 45000; double d = Math.Sqrt(dx * dx + dz * dz); // 0 - 0.1412 d = 1 - d; // 1 = centre, 0 = unit circle d = d * 2 - 1; // -1 to +1 double dist = ObjectExtensionsNumbersBool.GaussianDist(d, 1, 1.4); int c = Math.Min(Math.Max(i * i * i / 120000, 1), 40); //int c = Math.Min(Math.Max(i * i * i / 24000000, 1), 40); dist *= 2000 / lyscale; //System.Diagnostics.Debug.WriteLine("{0} {1} : dist {2} c {3}", x, z, dist, c); //System.Diagnostics.Debug.Write(c); GLPointsFactory.RandomStars4(buf, c, gx, gx + xcw, gz, gz + zch, (int)dist, (int)-dist, rnd, w: 0.8f); points += c; System.Diagnostics.Debug.Assert(points < buf.Length / 16); } } //System.Diagnostics.Debug.WriteLine("."); } buf.StopReadWrite(); stardots = new GalaxyStarDots(); items.Add(stardots); GLRenderState rc = GLRenderState.Points(1); rc.DepthTest = false; // note, if this is true, there is a wierd different between left and right in view.. not sure why rObjects.Add(stardots, "stardots", GLRenderableItem.CreateVector4(items, OpenTK.Graphics.OpenGL4.PrimitiveType.Points, rc, buf, points)); System.Diagnostics.Debug.WriteLine("Stars " + points); } rObjects.Add(new GLOperationClearDepthBuffer()); // clear depth buffer and now use full depth testing on the rest if ((ctrlo & 16) != 0) { items.Add(new GLTexture2D(Properties.Resources.StarFlare2, SizedInternalFormat.Rgba8), "lensflare"); items.Add(new GLPointSpriteShader(items.Tex("lensflare"), 64, 40), "PS"); var p = GLPointsFactory.RandomStars4(1000, 0, 25899 / lyscale, 10000 / lyscale, 1000 / lyscale, -1000 / lyscale); GLRenderState rps = GLRenderState.PointSprites(); rObjects.Add(items.Shader("PS"), "starsprites", GLRenderableItem.CreateVector4Color4(items, OpenTK.Graphics.OpenGL4.PrimitiveType.Points, rps, p, new Color4[] { Color.White })); } if ((ctrlo & 32) != 0) { gridvertshader = new DynamicGridVertexShader(Color.Cyan); //items.Add(gridvertshader, "PLGRIDVertShader"); var frag = new GLPLFragmentShaderVSColor(); //items.Add(frag, "PLGRIDFragShader"); GLRenderState rl = GLRenderState.Lines(1); items.Add(new GLShaderPipeline(gridvertshader, frag), "DYNGRID"); gridrenderable = GLRenderableItem.CreateNullVertex(OpenTK.Graphics.OpenGL4.PrimitiveType.Lines, rl, drawcount: 2); rObjects.Add(items.Shader("DYNGRID"), "DYNGRIDRENDER", gridrenderable); } if ((ctrlo & 64) != 0) { gridbitmapvertshader = new DynamicGridCoordVertexShader(); var frag = new GLPLFragmentShaderTexture2DIndexed(0); GLRenderState rl = GLRenderState.Tri(cullface: false); GLTexture2DArray gridtexcoords = new GLTexture2DArray(); items.Add(gridtexcoords, "PLGridBitmapTextures"); GLShaderPipeline sp = new GLShaderPipeline(gridbitmapvertshader, frag); items.Add(sp, "DYNGRIDBitmap"); rObjects.Add(items.Shader("DYNGRIDBitmap"), "DYNGRIDBitmapRENDER", GLRenderableItem.CreateNullVertex(OpenTK.Graphics.OpenGL4.PrimitiveType.TriangleStrip, rl, drawcount: 4, instancecount: 9)); } GLStorageBlock findresults = items.NewStorageBlock(findblock); float sunsize = .5f; if ((ctrlo & 128) != 0) { Random rnd = new Random(52); List <HistoryEntry> pos = new List <HistoryEntry>(); DateTime start = new DateTime(2020, 1, 1); Color[] colors = new Color[] { Color.Red, Color.Green, Color.Blue, Color.White, Color.Black, Color.Purple, Color.Yellow }; for (int j = 0; j <= 200; j++) { Color jc = colors[j % colors.Length]; int i = j * 10; string name = "Kyli Flyuae AA-B h" + j.ToString(); if (i < 30000) { pos.Add(new HistoryEntry(start, name, i + rnd.Next(50), rnd.Next(50), i, jc)); } else if (i < 60000) { pos.Add(new HistoryEntry(start, name, 60000 - i + rnd.Next(50), rnd.Next(50), i, jc)); } else if (i < 90000) { pos.Add(new HistoryEntry(start, name, -(i - 60000) + rnd.Next(50), rnd.Next(50), 120000 - i, jc)); } else { pos.Add(new HistoryEntry(start, name, -30000 + (i - 90000) + rnd.Next(50), rnd.Next(50), -i + 120000, jc)); } start = start.AddDays(1); } // tested to 50k stars travelpath = new TravelPath(1000); travelpath.Create(items, rObjects, pos, sunsize, sunsize, findresults, true); travelpath.SetSystem(0); } if ((ctrlo & 256) != 0) { galmapobjects = new GalMapObjects(); galmapobjects.CreateObjects(items, rObjects, edsmmapping, findresults, true); } if ((ctrlo & 512) != 0) { // galaxystars = new GalaxyStars(items, rObjects, sunsize, findresults); } if ((ctrlo & 1024) != 0) { rightclickmenu = new GLContextMenu("RightClickMenu", new GLMenuItem("RCMInfo", "Information") { MouseClick = (s, e) => { var nl = NameLocationDescription(rightclickmenu.Tag); System.Diagnostics.Debug.WriteLine($"Info {nl.Item1} {nl.Item2}"); // logical name is important as menu uses it to close down GLMessageBox msg = new GLMessageBox("InfoBoxForm-1", displaycontrol, e.WindowLocation, nl.Item3, $"{nl.Item1} @ {nl.Item2.X:#.#},{nl.Item2.Y:#.#},{nl.Item2.Z:#.#}", GLMessageBox.MessageBoxButtons.OK, null, Color.FromArgb(220, 60, 60, 70), Color.DarkOrange); } }, new GLMenuItem("RCMZoomIn", "Goto Zoom In") { MouseClick = (s1, e1) => { var nl = NameLocationDescription(rightclickmenu.Tag); gl3dcontroller.SlewToPositionZoom(nl.Item2, 100, -1); } }, new GLMenuItem("RCMGoto", "Goto Position") { MouseClick = (s1, e1) => { var nl = NameLocationDescription(rightclickmenu.Tag); System.Diagnostics.Debug.WriteLine($"Goto {nl.Item1} {nl.Item2}"); gl3dcontroller.SlewToPosition(nl.Item2, -1); } }, new GLMenuItem("RCMLookAt", "Look At") { MouseClick = (s1, e1) => { var nl = NameLocationDescription(rightclickmenu.Tag); gl3dcontroller.PanTo(nl.Item2, -1); } } ); } if ((ctrlo & 2048) != 0) { bookmarks = new Bookmarks(); var syslist = new List <SystemClass> { new SystemClass("bk1", 1000, 0, 0), new SystemClass("bk1", 1000, 0, 2000), }; bookmarks.Create(items, rObjects, syslist, 10, findresults, false); } // Matrix calc holding transform info matrixcalc = new GLMatrixCalc(); matrixcalc.PerspectiveNearZDistance = 1f; matrixcalc.PerspectiveFarZDistance = 120000f / lyscale; matrixcalc.InPerspectiveMode = true; matrixcalc.ResizeViewPort(this, glwfc.Size); // must establish size before starting // menu system displaycontrol = new GLControlDisplay(items, glwfc, matrixcalc, true, 0.00001f, 0.00001f); // hook form to the window - its the master displaycontrol.Font = new Font("Arial", 10f); displaycontrol.Focusable = true; // we want to be able to focus and receive key presses. displaycontrol.SetFocus(); // 3d controller gl3dcontroller = new Controller3D(); gl3dcontroller.PosCamera.ZoomMax = 600; // gives 5ly gl3dcontroller.ZoomDistance = 3000F / lyscale; gl3dcontroller.PosCamera.ZoomMin = 0.1f; gl3dcontroller.PosCamera.ZoomScaling = 1.1f; gl3dcontroller.YHoldMovement = true; gl3dcontroller.PaintObjects = Controller3DDraw; gl3dcontroller.KeyboardTravelSpeed = (ms, eyedist) => { double eyedistr = Math.Pow(eyedist, 1.0); float v = (float)Math.Max(eyedistr / 1200, 0); //System.Diagnostics.Debug.WriteLine("Speed " + eyedistr + " "+ v); return((float)ms * v); }; // hook gl3dcontroller to display control - its the slave. Do not register mouse UI, we will deal with that. gl3dcontroller.Start(matrixcalc, displaycontrol, new Vector3(0, 0, 0), new Vector3(140.75f, 0, 0), 0.5F, false, true); //gl3dcontroller.Start(matrixcalc, displaycontrol, new Vector3(0, 0, 0), new Vector3(90F, 0, 0), 0.5F, false, true); if (displaycontrol != null) { displaycontrol.Paint += (o, ts) => // subscribing after start means we paint over the scene, letting transparency work { // MCUB set up by Controller3DDraw which did the work first galaxymenu.UpdateCoords(gl3dcontroller.MatrixCalc, gl3dcontroller.PosCamera.ZoomFactor); // debug this galaxymenu.DebugStatusText(gl3dcontroller.PosCamera.StringPositionCamera); gl3dcontroller.PosCamera.SetPositionCamera(gl3dcontroller.PosCamera.StringPositionCamera); displaycontrol.Animate(glwfc.ElapsedTimems); displaycontrol.Render(glwfc.RenderState, ts); }; } displaycontrol.MouseClick += MouseClickOnMap; displaycontrol.MouseUp += MouseUpOnMap; displaycontrol.MouseDown += MouseDownOnMap; displaycontrol.MouseMove += MouseMoveOnMap; displaycontrol.MouseWheel += MouseWheelOnMap; galaxymenu = new MapMenu(this); // Autocomplete text box at top for searching GLTextBoxAutoComplete tbac = ((GLTextBoxAutoComplete)displaycontrol[MapMenu.EntryTextName]); tbac.PerformAutoCompleteInUIThread = (s, a, set) => { System.Diagnostics.Debug.Assert(Application.MessageLoop); // must be in UI thread var glist = edsmmapping.galacticMapObjects.Where(x => s.Length < 3 ? x.name.StartsWith(s, StringComparison.InvariantCultureIgnoreCase) : x.name.Contains(s, StringComparison.InvariantCultureIgnoreCase)).Select(x => x).ToList(); List <string> list = glist.Select(x => x.name).ToList(); list.AddRange(travelpath.CurrentList.Where(x => s.Length < 3 ? x.System.Name.StartsWith(s, StringComparison.InvariantCultureIgnoreCase) : x.System.Name.Contains(s, StringComparison.InvariantCultureIgnoreCase)).Select(x => x.System.Name)); foreach (var x in list) { set.Add(x); } }; tbac.SelectedEntry = (a) => // in UI thread { System.Diagnostics.Debug.Assert(Application.MessageLoop); // must be in UI thread System.Diagnostics.Debug.WriteLine("Selected " + tbac.Text); var gmo = edsmmapping.galacticMapObjects.Find(x => x.name.Equals(tbac.Text, StringComparison.InvariantCultureIgnoreCase)); if (gmo != null) { System.Diagnostics.Debug.WriteLine("Move to gmo " + gmo.points[0]); gl3dcontroller.SlewToPosition(new Vector3((float)gmo.points[0].X, (float)gmo.points[0].Y, (float)gmo.points[0].Z), -1); } else { var he = travelpath.CurrentList.Find(x => x.System.Name.Equals(tbac.Text, StringComparison.InvariantCultureIgnoreCase)); if (he != null) { System.Diagnostics.Debug.WriteLine("Move to sys " + he.System.Name); gl3dcontroller.SlewToPosition(new Vector3((float)he.System.X, (float)he.System.Y, (float)he.System.Z), -1); } else { tbac.InErrorCondition = true; } } }; if (galaxystars != null) { galaxystars.Start(); } if (false) // enable for debug buffer { debugbuffer = new GLStorageBlock(31, true); debugbuffer.AllocateBytes(32000, OpenTK.Graphics.OpenGL4.BufferUsageHint.DynamicCopy); // set size of vec buffer } if (false) // enable for debug { items.Add(new GLColorShaderObjectTranslation(), "COSOT"); GLRenderState rc = GLRenderState.Tri(cullface: false); rc.DepthTest = false; Vector3[] markers = new Vector3[] { new Vector3(0, 0, 0), new Vector3(0, -5, 0), new Vector3(0, -5 - 3.125f / 2f, 0) }; for (int i = 0; i < markers.Length; i++) { rObjects.Add(items.Shader("COSOT"), "marker" + i, GLRenderableItem.CreateVector4Color4(items, PrimitiveType.Triangles, rc, GLCubeObjectFactory.CreateSolidCubeFromTriangles(0.5f), new Color4[] { Color4.Red, Color4.Green, Color4.Blue, Color4.White, Color4.Cyan, Color4.Orange }, new GLRenderDataTranslationRotation(markers[i]) )); } } }
private static int StartApplication(SingleApplicationHelper.IMutex mutex, string fileToOpen, Stopwatch stopwatch) { ApplicationSettings settings = ApplicationSettings.Create(); settings.Restore(out var neededPatching); settings.AllowSave = false; //< We will allow saving once the app is fully booted if (neededPatching) { // TODO: Save settings right again to complete the upgrade // (maybe we should preserve an old version) } var bookmarks = Bookmarks.Create(); bookmarks.Restore(); var services = new ServiceContainer(); services.RegisterInstance <ILogFileSettings>(settings.LogFile); var actionCenter = new ActionCenter(); using (var taskScheduler = new DefaultTaskScheduler()) using (var serialTaskScheduler = new SerialTaskScheduler()) { services.RegisterInstance <ITaskScheduler>(taskScheduler); services.RegisterInstance <ISerialTaskScheduler>(serialTaskScheduler); var navigationService = new NavigationService(); services.RegisterInstance <INavigationService>(navigationService); var filesystem = new Filesystem(taskScheduler); services.RegisterInstance <IFilesystem>(filesystem); using (var pluginArchiveLoader = new PluginArchiveLoader(filesystem, Constants.PluginPath, Constants.DownloadedPluginsPath)) { var pluginUpdater = new PluginUpdater(pluginArchiveLoader); services.RegisterInstance <IPluginUpdater>(pluginUpdater); var pluginSystem = CreatePluginSystem(pluginArchiveLoader); services.RegisterInstance <IPluginLoader>(pluginSystem); var logFileFormatRegistry = new LogFileFormatRegistry(pluginSystem, settings.CustomFormats); services.RegisterInstance <ILogFileFormatRepository>(logFileFormatRegistry); services.RegisterInstance <ILogFileFormatRegistry>(logFileFormatRegistry); var logFileFormatMatcher = new LogFileFormatMatcher(services); services.RegisterInstance <ILogFileFormatMatcher>(logFileFormatMatcher); var textLogFileParserPlugin = new LogEntryParserFactory(services); services.RegisterInstance <ILogEntryParserPlugin>(textLogFileParserPlugin); var propertyPresenter = new PropertyPresenterRegistry(pluginSystem); services.RegisterInstance <IPropertyPresenterPlugin>(propertyPresenter); var fileLogSourceFactory = new StreamingTextLogSourceFactory(filesystem, taskScheduler); services.RegisterInstance <IRawFileLogSourceFactory>(fileLogSourceFactory); var parsingLogSourceFactory = new ParsingLogSourceFactory(services); services.RegisterInstance <ILogSourceParserPlugin>(parsingLogSourceFactory); var customDataSourcePlugins = pluginSystem.LoadAllOfTypeWithDescription <ICustomDataSourcePlugin>(); var logFileFactory = new PluginLogSourceFactory(services, customDataSourcePlugins); using (var dataSources = new DataSources(logFileFactory, taskScheduler, filesystem, settings.DataSources, bookmarks)) using (var updater = new AutoUpdater(actionCenter, settings.AutoUpdate)) { if (fileToOpen != null) { if (File.Exists(fileToOpen)) { // Not only do we want to add this file to the list of data sources, // but we also want to select it so the user can view it immediately, regardless // of what was selected previously. var dataSource = dataSources.AddFile(fileToOpen); settings.DataSources.SelectedItem = dataSource.Id; } else { Log.ErrorFormat("File '{0}' does not exist, won't open it!", fileToOpen); } } if (settings.AutoUpdate.CheckForUpdates) { // Our initial check for updates is not due to a user action // and therefore we don't need to show a notification when the // application is up-to-date. updater.CheckForUpdates(addNotificationWhenUpToDate: false); } var quickFilters = new QuickFilters(settings.QuickFilters); var highlighters = new HighlighterCollection(); services.RegisterInstance <IHighlighters>(highlighters); actionCenter.Add(Build.Current); actionCenter.Add(Change.Merge(Changelog.MostRecentPatches)); var application = new App(); var dispatcher = Dispatcher.CurrentDispatcher; var uiDispatcher = new UiDispatcher(dispatcher); services.RegisterInstance <IDispatcher>(uiDispatcher); dispatcher.UnhandledException += actionCenter.ReportUnhandledException; TaskScheduler.UnobservedTaskException += actionCenter.ReportUnhandledException; var windowViewModel = new MainWindowViewModel(services, settings, dataSources, quickFilters, actionCenter, updater); navigationService.MainWindow = windowViewModel; var window = new MainWindow(settings, windowViewModel); settings.MainWindow.ClipToBounds(Desktop.Current); settings.MainWindow.RestoreTo(window); settings.AllowSave = true; stopwatch.Stop(); Log.InfoFormat("Tailviewer started (took {0}ms), showing window...", stopwatch.ElapsedMilliseconds); window.Show(); mutex?.SetListener(window); return(application.Run()); } } } }