private CarDescription GetCarDescription([NotNull] string carId, [CanBeNull] DataWrapper carData) { var carDirectory = AcPaths.GetCarDirectory(_acRoot, carId); var carKn5 = carData == null?AcPaths.GetMainCarFilename(carDirectory) : AcPaths.GetMainCarFilename(carDirectory, carData); return(new CarDescription(carKn5, carDirectory)); }
protected override IEnumerable PackOverride(CarObject t) { yield return(Add("data/ambient_shadows.ini", "data/cameras.ini", "data/dash_cam.ini", "data/driver3d.ini", "data/extra_animations.ini", "data/lights.ini", "data/mirrors.ini")); yield return(Add("animations/*.ksanim")); yield return(Add("body_shadow.png", "tyre_*_shadow.png")); var mainModel = AcPaths.GetMainCarFilename(t.Location, false); if (mainModel == null) { throw new Exception("Failed to find main car model"); } yield return(AddFile("model.kn5", mainModel)); var textureNames = Kn5.FromFile(AcPaths.GetMainCarFilename(t.Location, t.AcdData, false) ?? throw new Exception(), SkippingTextureLoader.Instance, SkippingMaterialLoader.Instance, SkippingNodeLoader.Instance).TexturesData.Keys.ToList(); foreach (var skin in _skins) { foreach (var name in textureNames) { yield return(Add($"skins/{skin.Id}/{name}")); } } }
public override IEnumerable <ContentRepairSuggestion> GetSuggestions(CarObject car) { var kn5Filename = AcPaths.GetMainCarFilename(car.Location, car.AcdData); if (kn5Filename == null || !File.Exists(kn5Filename)) { return(new ContentRepairSuggestion[0]); } var kn5 = Kn5.FromFile(kn5Filename); return(new[] { TestFrensel(car, kn5), TestSuspensionNodes(car, kn5) }.NonNull()); }
public static async Task <bool> FixSuspensionNodesAsync(CarObject car, IProgress <AsyncProgressEntry> progress = null, CancellationToken cancellation = default) { progress?.Report(AsyncProgressEntry.FromStringIndetermitate("Fixing car…")); return(await Task.Run(() => { var kn5Filename = AcPaths.GetMainCarFilename(car.Location, car.AcdData, false); if (kn5Filename == null || !File.Exists(kn5Filename)) { return false; } var kn5 = Kn5.FromFile(kn5Filename); FixSuspensionNodes(kn5); kn5.SaveRecyclingOriginal(kn5Filename); return true; })); }
private Task <bool> FixAsync([NotNull] CarObject car, Action <IKn5> fix, IProgress <AsyncProgressEntry> progress = null, CancellationToken cancellation = default) { progress?.Report(AsyncProgressEntry.FromStringIndetermitate("Fixing car…")); return(Task.Run(() => { var kn5Filename = AcPaths.GetMainCarFilename(car.Location, car.AcdData, false); if (kn5Filename == null || !File.Exists(kn5Filename)) { return false; } var kn5 = Kn5.FromFile(kn5Filename); fix.Invoke(kn5); kn5.SaveRecyclingOriginal(kn5Filename); return true; })); }
public CarLodGenerator(IEnumerable <CarLodGeneratorStageParams> stages, ICarLodGeneratorService service, string carDirectory, string temporaryDirectory) { _service = service; _carDirectory = carDirectory; _temporaryDirectory = temporaryDirectory; _carData = DataWrapper.FromCarDirectory(carDirectory); var modelOriginal = AcPaths.GetMainCarFilename(carDirectory, _carData, false); if (modelOriginal == null) { throw new Exception("Failed to find main car model"); } Stages = stages.ToArray(); _originalKn5Data = File.ReadAllBytes(modelOriginal); }
private static async Task <IReadOnlyList <UpdatePreviewError> > Run([NotNull] CarObject car, [CanBeNull] string skinId, [CanBeNull] IReadOnlyList <ToUpdatePreview> toUpdate, [CanBeNull] string presetFilename) { var carKn5 = AcPaths.GetMainCarFilename(car.Location, car.AcdData, true); if (!File.Exists(carKn5)) { ModernDialog.ShowMessage("Model not found"); return(null); } await PrepareAsync(); Kn5 kn5; using (var waiting = new WaitingDialog()) { waiting.Report("Loading model…"); kn5 = await Task.Run(() => Kn5.FromFile(carKn5)); } using (var renderer = new DarkKn5ObjectRenderer(CarDescription.FromKn5(kn5, car.Location, car.AcdData)) { AutoRotate = false, AutoAdjustTarget = false, AsyncTexturesLoading = true, AsyncOverridesLoading = true, ForceUpdateWholeCubemapAtOnce = true }) { var wrapper = new CmPreviewsFormWrapper(car, renderer, skinId, presetFilename); if (toUpdate != null) { wrapper.SetToUpdate(toUpdate); } wrapper.Form.Icon = AppIconService.GetAppIcon(); wrapper.Run(); return(wrapper.GetErrors()); } }
// Trained on Kunos cars public static string TryToGuessCarClass(CarObject car) { var tyresIni = car.AcdData?.GetIniFile("tyres.ini"); if (tyresIni == null) { return(null); } var tyres = tyresIni.GetSections("FRONT", -1).Concat(tyresIni.GetSections("REAR", -1)) .Select(x => x.GetPossiblyEmpty("NAME")).NonNull().Distinct().ToList(); if (tyres.Count == 0) { return(null); } // Suspension stiffness var suspensionIni = car.AcdData.GetIniFile("suspensions.ini"); var weight = car.AcdData.GetIniFile("car.ini")["BASIC"].GetFloat("TOTALMASS", 0f); var cg = suspensionIni["BASIC"].GetFloat("CG_LOCATION", 0.5f); var stiffness = suspensionIni["FRONT"].GetFloat("SPRING_RATE", 0f) / (weight * cg - suspensionIni["FRONT"].GetFloat("HUB_MASS", 90)); // DX ref value var minDxRef = tyresIni.GetSections("FRONT", -1).Concat(tyresIni.GetSections("REAR", -1)).Select(x => x.GetFloat("DX_REF", 100f)).MinOrDefault(); // Special case for Honda S800 if (stiffness > 0f && stiffness < 50f) { return(TryToGuessCarClassResult(car, GuessedCarClass.Street, "weak suspension: " + stiffness)); } // Special case for drift cars if (tyres.Any(tyre => DriftSpecyRegex.IsMatch(tyre))) { return(TryToGuessCarClassResult(car, GuessedCarClass.Street, "specy drift tyres")); } // At first, check some valid marks of street tyre if (tyres.Any(tyre => StreetRegex.IsMatch(tyre))) { return(TryToGuessCarClassResult(car, GuessedCarClass.Street, "sure street mark in tyres")); } // Then, some valid marks of race tyre (this way, race+street tyres car will be // considered street car) if (tyres.Any(tyre => RaceRegex.IsMatch(tyre))) { return(TryToGuessCarClassResult(car, GuessedCarClass.Race, $"sure race mark in tyres [{stiffness}, {minDxRef}]")); } // Nothing? Well, let’s check using more wobbly marks if (tyres.Any(tyre => StreetBackupRegex.IsMatch(tyre))) { return(TryToGuessCarClassResult(car, GuessedCarClass.Street, "likely street mark in tyres")); } if (tyres.Any(tyre => RaceBackupRegex.IsMatch(tyre))) { return(TryToGuessCarClassResult(car, GuessedCarClass.Race, $"likely race mark in tyres [{stiffness}, {minDxRef}]")); } // Maybe there are postfixes? if (new[] { @"\bSS$", @"\bS$", @"\bM$", @"\bH$" }.Count(x => tyres.Any(y => Regex.IsMatch(y, x))) > 2) { return(TryToGuessCarClassResult(car, GuessedCarClass.Race, "postfixes")); } // Check for license plate var textureNames = Kn5.FromFile(AcPaths.GetMainCarFilename(car.Location, car.AcdData, false), SkippingTextureLoader.Instance, SkippingMaterialLoader.Instance, SkippingNodeLoader.Instance).TexturesData.Keys.ToList(); if (textureNames.Contains("Plate_D.dds") || textureNames.Contains("plate.dds")) { return(TryToGuessCarClassResult(car, GuessedCarClass.Street, "license plate")); } // Drift cars are considered street-legal: for instance, D1 only allows street-legal cars to compete if (tyres.Any(tyre => DriftRegex.IsMatch(tyre))) { return(TryToGuessCarClassResult(car, GuessedCarClass.Street, "drift car")); } // Suspension is too stiff for car’s weight? Might be a race car if (stiffness >= 125f) { return(TryToGuessCarClassResult(car, GuessedCarClass.Race, "stiff suspension: " + stiffness)); } // Street-legal cars should have at least one headlight or brake light var lightsIni = car.AcdData.GetIniFile("lights.ini"); if (!lightsIni.GetSections("BRAKE").Any(x => x.GetVector3("COLOR").Any(y => y > 5f)) || !lightsIni.GetSections("LIGHT").Any(x => x.GetVector3("COLOR").Any(y => y > 5f))) { return(TryToGuessCarClassResult(car, GuessedCarClass.Race, "lights are missing")); } // DX ref? if (minDxRef != 0f && minDxRef != 100f) { return(TryToGuessCarClassResult(car, minDxRef < 1.54f ? GuessedCarClass.Street : GuessedCarClass.Race, "dx ref " + minDxRef)); } return(TryToGuessCarClassResult(car, GuessedCarClass.Street, $"nothing left: {stiffness}, {minDxRef}")); }
public static Task StartAsync(CarObject car, CarSkinObject skin = null, string presetFilename = null) { return(StartAsync(AcPaths.GetMainCarFilename(car.Location, car.AcdData, true), skin?.Id, presetFilename)); }
public static CarDescription FromDirectory(string carDirectory, DataWrapper data) { return(new CarDescription(AcPaths.GetMainCarFilename(carDirectory, data, true), carDirectory, data)); }
public static CarDescription FromDirectory(string carDirectory) { return(new CarDescription(AcPaths.GetMainCarFilename(carDirectory, true), carDirectory)); }
public string GetMainKn5(string carDirectory) { return(AcPaths.GetMainCarFilename(carDirectory, _data)); }
public string GetMainKn5(string carDirectory, bool considerHr) { return(AcPaths.GetMainCarFilename(carDirectory, _data, considerHr)); }
public async Task LamborghiniTest() { var path = Path.Combine(AcRootFinder.Find(), @"content\cars"); if (!Directory.Exists(path)) { Debug.WriteLine("REQUIRED ASSET IS MISSING, TEST CANNOT BE DONE"); return; } var cars = Directory.GetDirectories(path, "ks_lamborghini_*").Select(x => new { CarId = Path.GetFileName(x), CarDirectory = x, Kn5 = AcPaths.GetMainCarFilename(x) }).ToList(); var sw = Stopwatch.StartNew(); var i = 0; using (var e = cars.GetEnumerator()) { if (!e.MoveNext()) { return; } var first = e.Current; if (first == null) { return; } using (var renderer = new DarkKn5ObjectRenderer(new CarDescription(first.Kn5, first.CarDirectory))) { renderer.UseMsaa = false; renderer.UseFxaa = false; renderer.AutoRotate = false; renderer.SetCamera(new Vector3(3.867643f, 1.42359f, 4.70381f), new Vector3(0.0f, 0.7f, 0.5f), (float)(Math.PI / 180d * 30f), 0f); renderer.BackgroundColor = Color.FromArgb(220, 220, 220); renderer.Initialize(); renderer.Width = CommonAcConsts.PreviewWidth; renderer.Height = CommonAcConsts.PreviewHeight; renderer.ResolutionMultiplier = 1d; do { if (e.Current != first) { first = e.Current; if (first == null) { return; } await renderer.MainSlot.SetCarAsync(new CarDescription(first.Kn5, first.CarDirectory)); } Console.WriteLine(first.CarId); foreach (var skinDirectory in Directory.GetDirectories(Path.Combine(first.CarDirectory, "skins"))) { using (var stream = new MemoryStream()) { renderer.Shot(renderer.Width * 4, renderer.Height * 4, 1d, 1d, stream, RendererShotFormat.Png); Image.FromStream(stream).HighQualityResize(new Size(CommonAcConsts.PreviewWidth, CommonAcConsts.PreviewHeight)) .Save(Path.Combine(skinDirectory, "preview_new.jpg")); } renderer.SelectNextSkin(); i++; } } while (e.MoveNext()); } } Console.WriteLine($"Done: {i} skins ({sw.Elapsed.TotalMilliseconds / i:F1} ms per skin)"); }