private static async Task RunInner(TrackObjectBase track, bool aiLane) { string modelsFilename = null, kn5Filename = null, aiLaneFilename = null; if (!aiLane) { modelsFilename = track.ModelsFilename; if (!File.Exists(modelsFilename)) { modelsFilename = null; kn5Filename = Path.Combine(track.Location, track.Id + ".kn5"); if (!File.Exists(kn5Filename)) { ModernDialog.ShowMessage("Model not found"); return; } } } else { aiLaneFilename = track.AiLaneFastFilename; if (!File.Exists(aiLaneFilename)) { ModernDialog.ShowMessage("AI lane not found"); return; } } await PrepareAsync(); TrackMapPreparationRenderer renderer = null; try { using (WaitingDialog.Create("Loading model…")) { renderer = aiLaneFilename == null ? modelsFilename == null ? new TrackMapPreparationRenderer(await Task.Run(() => Kn5.FromFile(kn5Filename))) : new TrackMapPreparationRenderer(await Task.Run(() => TrackComplexModelDescription.CreateLoaded(modelsFilename))) : new TrackMapPreparationRenderer(await Task.Run(() => AiSpline.FromFile(aiLaneFilename))); } var wrapper = new TrackMapRendererWrapper(track, renderer); wrapper.Form.Icon = AppIconService.GetAppIcon(); wrapper.Run(); } catch (Exception e) { NonfatalError.Notify("Can’t update map", e); } finally { renderer?.Dispose(); } }
private static LapTimesExtraTool CreateSidekickFixTool(Func <string> appDirectoryCallback) { return(new LapTimesExtraTool("Fix lap times", "Older CM versions could break some records, sorry about it. But now, you can use this button to quickly fix them!", new AsyncCommand(async() => { try { var fixedCount = 0; using (var waiting = WaitingDialog.Create("Fixing values")) { var directory = Path.Combine(appDirectoryCallback(), "personal_best"); if (Directory.Exists(directory)) { var files = await Task.Run(() => new DirectoryInfo(directory).GetFiles("*_pb.ini")); for (var i = 0; i < files.Length; i++) { var file = files[i]; if (file.Length != 11) { continue; } var bytes = File.ReadAllBytes(file.FullName); if (bytes.Length != 11 || bytes[0] != 0x80 || bytes[1] != 3 || bytes[2] != (byte)'L') { continue; } waiting.Report(file.Name, i, files.Length); var value = BitConverter.ToInt64(bytes, 3); using (var writer = new BinaryWriter(File.Create(file.FullName))) { writer.Write(new byte[] { 0x80, 3, (byte)'L' }); writer.Write(Encoding.ASCII.GetBytes(value.As <string>())); writer.Write((byte)'\n'); writer.Write((byte)'.'); } fixedCount++; await Task.Yield(); } } } Toast.Show("Records fixed", fixedCount > 0 ? PluralizingConverter.PluralizeExt(fixedCount, "{0} error") + " fixed" : "No errors found"); } catch (Exception e) { NonfatalError.Notify("Can’t fix records", e); } }))); }
public async Task ReplaceSound(CarObject donor) { if (string.Equals(donor.Id, Id, StringComparison.OrdinalIgnoreCase)) { NonfatalError.Notify(ToolsStrings.Car_ReplaceSound_CannotReplace, "Source and destination are the same."); return; } try { using (WaitingDialog.Create("Replacing…")) { await Task.Run(() => ReplaceSound(donor, Location)); } } catch (Exception e) { NonfatalError.Notify(ToolsStrings.Car_ReplaceSound_CannotReplace, ToolsStrings.Car_ReplaceSound_CannotReplace_Commentary, e); } }
public async Task RemoveEntryAsync(LapTimeEntry entry) { if (EnabledSources.Any(x => x.ReadOnly)) { NonfatalError.Notify("Can’t remove entry from read-only sources", $"Please, disable {EnabledSources.Where(x => x.ReadOnly).Select(x => x.DisplayName).JoinToReadableString()}.", solutions: new[] { new NonfatalErrorSolution("Disable read-only sources", null, token => { foreach (var source in EnabledSources) { source.IsEnabled = false; } RaiseEntriesChanged(); return(Task.Delay(0)); }), }); return; } var car = CarsManager.Instance.GetById(entry.CarId)?.DisplayName ?? entry.CarId; var track = TracksManager.Instance.GetLayoutByKunosId(entry.TrackId)?.LayoutName ?? entry.TrackId; if (ModernDialog.ShowMessage($"Are you sure you want to remove {car} on {track} lap time?", "Remove Lap Time", MessageBoxButton.YesNo) != MessageBoxResult.Yes) { return; } try { using (WaitingDialog.Create("Deleting…")) { var changed = false; foreach (var source in EnabledSources) { changed |= await source.RemoveAsync(entry.CarId, entry.TrackId); } if (changed) { Logging.Debug("Removed"); RaiseEntriesChanged(); } } } catch (Exception e) { NonfatalError.Notify("Can’t remove entry", e); } }
public static async Task RunAsync([NotNull] PythonAppObject app) { IReadOnlyList <PythonAppWindow> list; using (WaitingDialog.Create("Searching for app windows…")) { list = await app.Windows.GetValueAsync(); } if (list == null || list.Count == 0) { ShowMessage( "No app windows found. You can add lines like “# app window: Window Name” to your code to help CM figure out their names.", "No app windows found", MessageBoxButton.OK); return; } await new AppIconEditor(list).ShowDialogAsync(); }
public Task DisableMod(GenericMod mod) { return(_busy.Task(async() => { if (_enabler == null || !mod.IsEnabled) { return; } try { using (var waiting = WaitingDialog.Create("Disabling mod…")) { await _enabler.DisableAsync(mod, waiting, waiting.CancellationToken); Changed?.Invoke(this, EventArgs.Empty); if (waiting.CancellationToken.IsCancellationRequested) { waiting.Report(AsyncProgressEntry.FromStringIndetermitate("Cancellation…")); await _enabler.EnableAsync(mod); } } } catch (Exception e) { NonfatalError.Notify("Can’t disable mod", e); } })); }
private static async Task ShowCarInShowroomAsync(string carId) { if (_showingCarInShowroom) { return; } _showingCarInShowroom = true; try { var temporaryDirectory = FilesStorage.Instance.GetTemporaryDirectory("Workshop", "Showroom", carId); var temporaryFilename = Path.Combine(temporaryDirectory, "data.zip"); byte[] modelData = null; string mainSkidId = null; var carData = new VirtualDataWrapper(); using (var waiting = WaitingDialog.Create("Loading showroom…")) { await WorkshopHolder.Client.DownloadFileAsync($"/cars/{carId}/download-showroom", temporaryFilename, false, waiting, waiting.CancellationToken); waiting.Report(AsyncProgressEntry.FromStringIndetermitate("Loading…")); await Task.Run(() => { using (var stream = File.OpenRead(temporaryFilename)) using (var archive = new ZipArchive(stream)) { foreach (var entry in archive.Entries) { if (entry.Length == 0) { continue; } if (entry.FullName == @"model.kn5") { modelData = entry.Open().ReadAsBytesAndDispose(); } else if (entry.FullName.StartsWith(@"data")) { carData.Data[Path.GetFileName(entry.FullName)] = entry.Open().ReadAsStringAndDispose(); } else { if (mainSkidId == null && entry.FullName.StartsWith(@"skins")) { mainSkidId = Path.GetFileName(Path.GetDirectoryName(entry.FullName)); } var newFilename = Path.Combine(temporaryDirectory, entry.FullName); FileUtils.EnsureFileDirectoryExists(newFilename); entry.ExtractToFile(newFilename, true); } waiting.CancellationToken.ThrowIfCancellationRequested(); } } }); waiting.CancellationToken.ThrowIfCancellationRequested(); } if (modelData == null) { throw new Exception("Model is missing"); } if (mainSkidId == null) { throw new Exception("Skins are missing"); } var description = CarDescription.FromKn5(Kn5.FromBytes(modelData), temporaryDirectory, carData); var renderer = new DarkKn5ObjectRenderer(description) { FlatMirror = true, FlatMirrorReflectiveness = 0.3f, FlatMirrorReflectedLight = true, BackgroundColor = Color.White, BackgroundBrightness = 0.05f, LightBrightness = 2f, AmbientBrightness = 2f, AmbientUp = Color.FromArgb(0xEEEEEE), AmbientDown = Color.FromArgb(0x333333), UseDof = true, UseAccumulationDof = true, AccumulationDofIterations = 40, AccumulationDofApertureSize = 0f, UseSslr = true, VisibleUi = false, UseSprite = false, AnyGround = false, ToneMapping = ToneMappingFn.Uncharted2, ToneExposure = 1.2f, ToneGamma = 1f, ToneWhitePoint = 2.2f, }; renderer.SelectSkin(mainSkidId); await FormWrapperBase.PrepareAsync(); var wrapper = new LiteShowroomFormWrapper(renderer); wrapper.Form.Icon = AppIconService.GetAppIcon(); CustomShowroomWrapper.SetProperties(wrapper, renderer); wrapper.Run(); } catch (Exception e) when(!e.IsCancelled()) { Logging.Warning(e); NonfatalError.Notify("Failed to load showroom", e); } finally { _showingCarInShowroom = false; } }