public async Task ATest() { var path = AcRootFinder.Find(); if (!Directory.Exists(path)) { Debug.WriteLine("REQUIRED ASSET IS MISSING, TEST CANNOT BE DONE"); return; } var cars = Directory.GetDirectories(Path.Combine(path, "content", "cars"), "ks_*").Select(x => new { CarId = Path.GetFileName(x), SkinsIds = Directory.GetDirectories(Path.Combine(x, "skins")).Select(Path.GetFileName).ToList() }).Where(x => Regex.IsMatch(x.CarId, @"^ks_[a]")).ToList(); var sw = Stopwatch.StartNew(); var i = 0; using (var updater = new DarkPreviewsUpdater(path)) { foreach (var car in cars) { foreach (var skin in car.SkinsIds) { await updater.ShotAsync(car.CarId, skin); i++; } } } Console.WriteLine($"Done: {i} skins ({sw.Elapsed.TotalMilliseconds / i:F1} ms per skin)"); }
private void PrepareUpdater() { var options = Settings.ToPreviewsOptions(); if (_previewsUpdater == null) { _previewsUpdater = new DarkPreviewsUpdater(AcRootDirectory.Instance.RequireValue, options); } else { _previewsUpdater.SetOptions(options); } }
public Updater([NotNull] IReadOnlyList <ToUpdatePreview> entries, [NotNull] DarkPreviewsOptions options, [CanBeNull] string presetName, [CanBeNull] DarkPreviewsUpdater updater) { _entries = entries; _options = options; _presetName = presetName; if (updater == null) { _localUpdater = true; _updater = new DarkPreviewsUpdater(AcRootDirectory.Instance.RequireValue, options); } else { _updater = updater; _updater.SetOptions(options); } }
private static int MainInner(string[] args) { var presets = args.Where(x => x.EndsWith(".pu-preset")).ToList(); var actualList = new List <string>(); foreach (var preset in presets) { try { actualList.AddRange( File.ReadAllLines(preset) .Where(x => !x.StartsWith("#")) .Select(x => x.Split(new[] { " #" }, StringSplitOptions.None)[0].Trim()) .Where(x => x.Length > 0)); } catch (Exception e) { Console.Error.WriteLine($"Can't load preset {preset}: {e.Message}."); } } actualList.AddRange(args.ApartFrom(presets)); var options = new Options(); if (!Parser.Default.ParseArguments(actualList.ToArray(), options)) { return(1); } if (options.ColorGradingFilename != null && presets.Count > 0 && !File.Exists(options.ColorGradingFilename)) { var locations = presets.Select(Path.GetDirectoryName).ToList(); var current = Environment.CurrentDirectory; foreach (var location in locations) { Environment.CurrentDirectory = location; var path = Path.GetFullPath(options.ColorGradingFilename); if (File.Exists(path)) { options.ColorGradingFilename = path; } } Environment.CurrentDirectory = current; } var acRoot = options.AcRoot == null?AcRootFinder.TryToFind() : Path.GetFullPath(options.AcRoot); if (acRoot == null) { Console.Error.WriteLine("Can't find AC root directory, you need to specify it manually."); Console.ReadLine(); return(1); } var ids = options.Ids.ApartFrom(presets).ToList(); if (ids.Count == 0) { Console.Error.WriteLine("You forgot to specify what cars to update: either list their IDs or filters."); Console.Error.WriteLine("To process all cars, use filter \"*\"."); Console.ReadLine(); return(1); } IFilter <string> filter; try { filter = Filter.Create(new CarTester(acRoot), ids.Select(x => "(" + (x.EndsWith("/") ? x.Substring(0, x.Length - 1) : x) + ")").JoinToString("|"), true); if (options.FilterTest) { Console.WriteLine(Directory.GetDirectories(FileUtils.GetCarsDirectory(acRoot)) .Select(Path.GetFileName).Where(x => filter.Test(x)).JoinToString(", ")); return(0); } if (options.Verbose) { Console.WriteLine("Filter: " + filter); } } catch (Exception e) { Console.Error.WriteLine("Can't parse filter: " + e.Message + "."); Console.ReadLine(); return(2); } if (options.Verbose) { Console.WriteLine("AC root: " + acRoot); Console.WriteLine("ImageMagick: " + ImageUtils.IsMagickSupported); Console.WriteLine("Starting shoting..."); } var sw = Stopwatch.StartNew(); int i = 0, j = 0; using (var thing = new DarkPreviewsUpdater(acRoot, new DarkPreviewsOptions { PreviewName = options.FileName, Showroom = options.Showroom, AlignCar = options.AlignCar, AlignCameraHorizontally = options.AlignCamera, AlignCameraHorizontallyOffset = options.AlignCameraOffset.Split(',').Select(x => FlexibleParser.TryParseDouble(x) ?? 0d).ToArray()[0], // TODO SsaaMultiplier = options.SsaaMultiplier, UseFxaa = options.UseFxaa, UseMsaa = options.UseMsaa, SoftwareDownsize = options.SoftwareDownsize, MsaaSampleCount = options.MsaaSampleCount, PreviewWidth = options.PreviewWidth, PreviewHeight = options.PreviewHeight, BloomRadiusMultiplier = options.BloomRadiusMultiplier, FlatMirror = options.FlatMirror, WireframeMode = options.WireframeMode, MeshDebugMode = options.MeshDebugMode, SuspensionDebugMode = options.SuspensionDebugMode, HeadlightsEnabled = options.HeadlightsEnabled, BrakeLightsEnabled = options.BrakeLightsEnabled, LeftDoorOpen = options.LeftDoorOpen, RightDoorOpen = options.RightDoorOpen, SteerDeg = options.SteerAngle, CameraPosition = options.CameraPosition.Split(',').Select(x => FlexibleParser.TryParseDouble(x) ?? 0d).ToArray(), CameraLookAt = options.LookAt.Split(',').Select(x => FlexibleParser.TryParseDouble(x) ?? 0d).ToArray(), CameraFov = options.Fov, BackgroundColor = ParseColor(options.BackgroundColor), LightColor = ParseColor(options.LightColor), AmbientUp = ParseColor(options.AmbientUp), AmbientDown = ParseColor(options.AmbientDown), AmbientBrightness = options.AmbientBrightness, LightBrightness = options.LightBrightness, DelayedConvertation = !options.SingleThread, UseSslr = options.UseSslr, UseAo = options.UseSsao, UsePcss = options.UsePcss, EnableShadows = options.EnableShadows, ShadowMapSize = options.ShadowMapSize, MaterialsReflectiveness = options.ReflectionMultiplier, ReflectionCubemapAtCamera = options.ReflectionCubemapAtCamera, ReflectionsWithShadows = !options.NoShadowsWithReflections, FlatMirrorBlurred = options.FlatMirrorBlurred, FlatMirrorReflectiveness = options.FlatMirrorReflectiveness, LightDirection = options.LightDirection.Split(',').Select(x => FlexibleParser.TryParseDouble(x) ?? 0d).ToArray(), })) { foreach (var carId in Directory.GetDirectories(FileUtils.GetCarsDirectory(acRoot)) .Select(Path.GetFileName).Where(x => filter.Test(x))) { Console.WriteLine($" {carId}..."); j++; foreach (var skinId in Directory.GetDirectories(FileUtils.GetCarSkinsDirectory(acRoot, carId)) .Where(x => !options.WithoutPreviews || !File.Exists(Path.Combine(x, options.FileName))) .Select(Path.GetFileName)) { var success = false; for (var a = 0; a < options.AttemptsCount || a == 0; a++) { try { if (options.Verbose) { Console.Write($" {skinId}... "); } thing.Shot(carId, skinId); success = true; break; } catch (Exception e) { Console.Error.WriteLine(e.Message); if (options.Verbose) { Console.Error.WriteLine(e.StackTrace); } } } if (success) { i++; if (options.Verbose) { Console.WriteLine("OK"); } } } if (options.Verbose && j % 10 == 0) { Console.WriteLine( $"At this moment done: {i} skins ({sw.Elapsed.TotalMilliseconds / j:F1} ms per car; {sw.Elapsed.TotalMilliseconds / i:F1} ms per skin)"); Console.WriteLine($"Time taken: {ToMillisecondsString(sw.Elapsed)}"); } } Console.Write("Finishing convertation... "); } Console.WriteLine("OK"); Console.WriteLine($"Done: {i} skins ({sw.Elapsed.TotalMilliseconds / j:F1} ms per car; {sw.Elapsed.TotalMilliseconds / i:F1} ms per skin)"); Console.WriteLine($"Time taken: {ToMillisecondsString(sw.Elapsed)}"); return(0); }
private static async Task <IReadOnlyList <UpdatePreviewError> > UpdatePreview(IReadOnlyList <ToUpdatePreview> entries, DarkPreviewsOptions options, string presetName = null, DarkPreviewsUpdater updater = null) { var localUpdater = updater == null; if (localUpdater) { updater = new DarkPreviewsUpdater(AcRootDirectory.Instance.RequireValue, options); } else { updater.SetOptions(options); } var errors = new List <UpdatePreviewError>(); try { if (options.Showroom != null && ShowroomsManager.Instance.GetById(options.Showroom) == null) { if (options.Showroom == "at_previews" && MissingShowroomHelper != null) { await MissingShowroomHelper.OfferToInstall("Kunos Previews Showroom (AT Previews Special)", "at_previews", "http://www.assettocorsa.net/assetto-corsa-v1-5-dev-diary-part-33/"); if (ShowroomsManager.Instance.GetById(options.Showroom) != null) { goto Action; } } throw new InformativeException("Can’t update preview", $"Showroom “{options.Showroom}” is missing"); } Action: var checksum = options.GetChecksum(); var finished = false; var j = 0; using (var waiting = new WaitingDialog()) { var cancellation = waiting.CancellationToken; var singleMode = entries.Count == 1; var verySingleMode = singleMode && entries[0].Skins?.Count == 1; var recycled = 0; if (!verySingleMode) { waiting.SetImage(null); if (SettingsHolder.CustomShowroom.PreviewsRecycleOld) { waiting.SetMultiline(true); } } var step = 1d / entries.Count; var postfix = string.Empty; var started = Stopwatch.StartNew(); var approximateSkinsPerCarCars = 1; var approximateSkinsPerCarSkins = 10; Action <int> updateApproximate = skinsPerCar => { approximateSkinsPerCarCars++; approximateSkinsPerCarSkins += skinsPerCar; }; Func <int, int> leftSkins = currentEntry => { var skinsPerCar = (double)approximateSkinsPerCarSkins / approximateSkinsPerCarCars; var result = 0d; for (var k = currentEntry; k < entries.Count; k++) { var entry = entries[k]; result += entry.Skins?.Count ?? skinsPerCar; } return(result.RoundToInt()); }; var shotSkins = 0; var recyclingWarning = false; Func <CarObject, CarSkinObject, int?, IEnumerable <string> > getDetails = (car, skin, currentEntrySkinsLeft) => { var left = leftSkins(j) + (currentEntrySkinsLeft ?? approximateSkinsPerCarSkins / approximateSkinsPerCarCars); // ReSharper disable once AccessToModifiedClosure var speed = shotSkins / started.Elapsed.TotalMinutes; var remainingTime = speed < 0.0001 ? "Unknown" : $"About {TimeSpan.FromMinutes(left / speed).ToReadableTime()}"; var remainingItems = $"About {left} {PluralizingConverter.Pluralize(left, ControlsStrings.CustomShowroom_SkinHeader).ToSentenceMember()}"; return(new[] { $"Car: {car?.DisplayName}", $"Skin: {skin?.DisplayName ?? "?"}", $"Speed: {speed:F2} {PluralizingConverter.Pluralize(10, ControlsStrings.CustomShowroom_SkinHeader).ToSentenceMember()}/{"min"}", $"Time remaining: {remainingTime}", $"Items remaining: {remainingItems}", // ReSharper disable once AccessToModifiedClosure recyclingWarning ? "[i]Recycling seems to take too long? If so, it can always be disabled in Settings.[/i]" : null }.NonNull()); }; for (j = 0; j < entries.Count; j++) { if (cancellation.IsCancellationRequested) { goto Cancel; } var entry = entries[j]; var progress = step * j; var car = entry.Car; var skins = entry.Skins; if (skins == null) { waiting.Report(new AsyncProgressEntry("Loading skins…" + postfix, verySingleMode ? 0d : progress)); waiting.SetDetails(getDetails(car, null, null)); await car.SkinsManager.EnsureLoadedAsync(); if (cancellation.IsCancellationRequested) { goto Cancel; } skins = car.EnabledOnlySkins.ToList(); updateApproximate(skins.Count); } var halfstep = step * 0.5 / skins.Count; for (var i = 0; i < skins.Count; i++) { if (cancellation.IsCancellationRequested) { goto Cancel; } var skin = skins[i]; waiting.SetDetails(getDetails(car, skin, skins.Count - i)); var subprogress = progress + step * (0.1 + 0.8 * i / skins.Count); if (SettingsHolder.CustomShowroom.PreviewsRecycleOld && File.Exists(skin.PreviewImage)) { if (++recycled > 5) { recyclingWarning = true; } waiting.Report(new AsyncProgressEntry($"Recycling current preview for {skin.DisplayName}…" + postfix, verySingleMode ? 0d : subprogress)); await Task.Run(() => FileUtils.Recycle(skin.PreviewImage)); } waiting.Report(new AsyncProgressEntry($"Updating skin {skin.DisplayName}…" + postfix, verySingleMode ? 0d : subprogress + halfstep)); try { await updater.ShotAsync(car.Id, skin.Id, skin.PreviewImage, car.AcdData, GetInformation(car, skin, presetName, checksum), () => { if (!verySingleMode) { ActionExtension.InvokeInMainThreadAsync(() => { // ReSharper disable once AccessToModifiedClosure if (!finished) { // ReSharper disable once AccessToDisposedClosure waiting.SetImage(skin.PreviewImage); } }); } }); shotSkins++; } catch (Exception e) { if (errors.All(x => x.ToUpdate != entry)) { errors.Add(new UpdatePreviewError(entry, e.Message, null)); } } } } waiting.Report(new AsyncProgressEntry("Saving…" + postfix, verySingleMode ? 0d : 0.999999d)); await updater.WaitForProcessing(); finished = true; } if (errors.Count > 0) { NonfatalError.Notify("Can’t update previews:\n" + errors.Select(x => @"• " + x.Message.ToSentence()).JoinToString(";" + Environment.NewLine)); } goto End; Cancel: for (; j < entries.Count; j++) { errors.Add(new UpdatePreviewError(entries[j], ControlsStrings.Common_Cancelled, null)); } End: return(errors); } catch (Exception e) { NonfatalError.Notify("Can’t update preview", e); return(null); } finally { if (localUpdater) { updater.Dispose(); GC.Collect(); } } }