diff --git a/Yafc.Model/Analysis/Analysis.cs b/Yafc.Model/Analysis/Analysis.cs index a28b8f32..d0be4317 100644 --- a/Yafc.Model/Analysis/Analysis.cs +++ b/Yafc.Model/Analysis/Analysis.cs @@ -68,10 +68,6 @@ public static float ApproximateFlow(this FactorioObject recipe, bool atCurrentMi return CostAnalysis.Get(atCurrentMilestones).flow[recipe]; } - public static float ProductCost(this Recipe recipe, bool atCurrentMilestones = false) { - return CostAnalysis.Get(atCurrentMilestones).recipeProductCost[recipe]; - } - public static float RecipeWaste(this Recipe recipe, bool atCurrentMilestones = false) { return CostAnalysis.Get(atCurrentMilestones).recipeWastePercentage[recipe]; } diff --git a/Yafc.Model/Analysis/CostAnalysis.cs b/Yafc.Model/Analysis/CostAnalysis.cs index c75ffc60..ba4e8f02 100644 --- a/Yafc.Model/Analysis/CostAnalysis.cs +++ b/Yafc.Model/Analysis/CostAnalysis.cs @@ -32,7 +32,6 @@ public static CostAnalysis Get(bool atCurrentMilestones) { public Mapping cost; public Mapping recipeCost; - public Mapping recipeProductCost; public Mapping flow; public Mapping recipeWastePercentage; public Goods[]? importantItems; @@ -103,7 +102,6 @@ public override void Compute(Project project, ErrorCollector warnings) { } var export = Database.objects.CreateMapping(); - var recipeProductionCost = Database.recipesAndTechnologies.CreateMapping(); recipeCost = Database.recipes.CreateMapping(); flow = Database.objects.CreateMapping(); var lastVariable = Database.goods.CreateMapping(); @@ -300,10 +298,6 @@ public override void Compute(Project project, ErrorCollector warnings) { { export[o] += export[ingredient.goods] * ingredient.amount; } - - foreach (var product in recipe.products) { - recipeProductionCost[recipe] += product.amount * export[product.goods]; - } } else if (o is Entity entity) { float minimal = float.PositiveInfinity; @@ -316,7 +310,6 @@ public override void Compute(Project project, ErrorCollector warnings) { } } cost = export; - recipeProductCost = recipeProductionCost; recipeWastePercentage = Database.recipes.CreateMapping(); if (result is Solver.ResultStatus.OPTIMAL or Solver.ResultStatus.FEASIBLE) { diff --git a/Yafc.Model/Model/ProductionTable.cs b/Yafc.Model/Model/ProductionTable.cs index a9e65c3a..6d3e8764 100644 --- a/Yafc.Model/Model/ProductionTable.cs +++ b/Yafc.Model/Model/ProductionTable.cs @@ -64,7 +64,7 @@ private void Setup(List allRecipes, List allLinks) { foreach (var recipe in recipes) { if (!recipe.enabled) { - ClearDisabledRecipeContents(recipe); + ClearRecipeContents(recipe, true); continue; } @@ -74,19 +74,21 @@ private void Setup(List allRecipes, List allLinks) { } } - private static void ClearDisabledRecipeContents(RecipeRow recipe) { + private static void ClearRecipeContents(RecipeRow recipe, bool recurse) { recipe.recipesPerSecond = 0; recipe.parameters = RecipeParameters.Empty; - recipe.hierarchyEnabled = false; - var subgroup = recipe.subgroup; - if (subgroup != null) { - subgroup.flow = []; - foreach (var link in subgroup.links) { - link.flags = 0; - link.linkFlow = 0; - } - foreach (var sub in subgroup.recipes) { - ClearDisabledRecipeContents(sub); + if (recurse) { + recipe.hierarchyEnabled = false; + var subgroup = recipe.subgroup; + if (subgroup != null) { + subgroup.flow = []; + foreach (var link in subgroup.links) { + link.flags = 0; + link.linkFlow = 0; + } + foreach (var sub in subgroup.recipes) { + ClearRecipeContents(sub, true); + } } } } @@ -311,21 +313,12 @@ private static void AddLinkCoef(Constraint cst, Variable var, ProductionLink lin objective.SetMinimization(); List allRecipes = []; List allLinks = []; + Dictionary> inaccessibleProductionRecipes = []; + Dictionary> inaccessibleConsumptionRecipes = []; Setup(allRecipes, allLinks); - Variable[] vars = new Variable[allRecipes.Count]; + Variable?[] vars = new Variable?[allRecipes.Count]; float[] objCoefs = new float[allRecipes.Count]; - for (int i = 0; i < allRecipes.Count; i++) { - var recipe = allRecipes[i]; - recipe.parameters = RecipeParameters.CalculateParameters(recipe); - var variable = productionTableSolver.MakeNumVar(0f, double.PositiveInfinity, recipe.recipe.name); - if (recipe.fixedBuildings > 0f) { - double fixedRps = (double)recipe.fixedBuildings / recipe.parameters.recipeTime; - variable.SetBounds(fixedRps, fixedRps); - } - vars[i] = variable; - } - Constraint[] constraints = new Constraint[allLinks.Count]; for (int i = 0; i < allLinks.Count; i++) { var link = allLinks[i]; @@ -338,65 +331,45 @@ private static void AddLinkCoef(Constraint cst, Variable var, ProductionLink lin } for (int i = 0; i < allRecipes.Count; i++) { - var recipe = allRecipes[i]; - var recipeVar = vars[i]; - var links = recipe.links; - - for (int j = 0; j < recipe.recipe.products.Length; j++) { - var product = recipe.recipe.products[j]; - if (product.amount <= 0f) { - continue; + RecipeRow recipeRow = allRecipes[i]; + cacheRecipeLinks(recipeRow); + if (recipeRow.recipe.IsAccessible()) { + configureRecipeForSolving(productionTableSolver, ref vars[i], ref objCoefs[i], constraints, recipeRow); + } + else { + // Treat inaccessible recipes as disabled for now, but save enough information we can later re-enable them. + ClearRecipeContents(recipeRow, false); + foreach (var link in recipeRow.links.ingredients.Append(recipeRow.links.fuel).WhereNotNull()) { + recordInaccessibleRecipe(inaccessibleConsumptionRecipes, link, recipeRow); + } + foreach (var link in recipeRow.links.products.Append(recipeRow.links.spentFuel).WhereNotNull()) { + recordInaccessibleRecipe(inaccessibleProductionRecipes, link, recipeRow); } - if (recipe.FindLink(product.goods, out var link)) { - link.flags |= ProductionLink.Flags.HasProduction; - float added = product.GetAmountPerRecipe(recipe.parameters.productivity); - AddLinkCoef(constraints[link.solverIndex], recipeVar, link, recipe, added); - float cost = product.goods.Cost(); - if (cost > 0f) { - objCoefs[i] += added * cost; + static void recordInaccessibleRecipe(Dictionary> record, ProductionLink link, RecipeRow recipeRow) { + if (!record.TryGetValue(link, out var recipes)) { + record[link] = recipes = []; } + recipes.Add(recipeRow); } - - links.products[j] = link; } + } - for (int j = 0; j < recipe.recipe.ingredients.Length; j++) { - var ingredient = recipe.recipe.ingredients[j]; - var option = ingredient.variants == null ? ingredient.goods : recipe.GetVariant(ingredient.variants); - if (recipe.FindLink(option, out var link)) { - link.flags |= ProductionLink.Flags.HasConsumption; - AddLinkCoef(constraints[link.solverIndex], recipeVar, link, recipe, -ingredient.amount); + foreach (var link in allLinks) { + // If a link has no production or no consumption, enable the corresponding inaccessible recipes. + if (!link.flags.HasFlag(ProductionLink.Flags.HasProduction) && inaccessibleProductionRecipes.TryGetValue(link, out var recipes)) { + foreach (var row in recipes) { + int i = allRecipes.IndexOf(row); + configureRecipeForSolving(productionTableSolver, ref vars[i], ref objCoefs[i], constraints, row); } - - links.ingredients[j] = link; - links.ingredientGoods[j] = option; } - - links.fuel = links.spentFuel = null; - - if (recipe.fuel != null) { - float fuelAmount = recipe.parameters.fuelUsagePerSecondPerRecipe; - if (recipe.FindLink(recipe.fuel, out var link)) { - links.fuel = link; - link.flags |= ProductionLink.Flags.HasConsumption; - AddLinkCoef(constraints[link.solverIndex], recipeVar, link, recipe, -fuelAmount); - } - - if (recipe.fuel.HasSpentFuel(out var spentFuel) && recipe.FindLink(spentFuel, out link)) { - links.spentFuel = link; - link.flags |= ProductionLink.Flags.HasProduction; - AddLinkCoef(constraints[link.solverIndex], recipeVar, link, recipe, fuelAmount); - if (spentFuel.Cost() > 0f) { - objCoefs[i] += fuelAmount * spentFuel.Cost(); - } + if (!link.flags.HasFlag(ProductionLink.Flags.HasConsumption) && inaccessibleConsumptionRecipes.TryGetValue(link, out recipes)) { + foreach (var row in recipes) { + int i = allRecipes.IndexOf(row); + configureRecipeForSolving(productionTableSolver, ref vars[i], ref objCoefs[i], constraints, row); } } - recipe.links = links; - } - - foreach (var link in allLinks) { link.notMatchedFlow = 0f; if (!link.flags.HasFlags(ProductionLink.Flags.HasProductionAndConsumption)) { if (!link.flags.HasFlagAny(ProductionLink.Flags.HasProductionAndConsumption) && !link.owner.HasDisabledRecipeReferencing(link.goods)) { @@ -468,10 +441,10 @@ private static void AddLinkCoef(Constraint cst, Variable var, ProductionLink lin RecipeRow? ownerRecipe = link.owner.owner as RecipeRow; while (ownerRecipe != null) { if (link.notMatchedFlow > 0f) { - ownerRecipe.parameters.warningFlags |= WarningFlags.OverproductionRequired; + ownerRecipe.parameters = ownerRecipe.parameters.WithFlag(WarningFlags.OverproductionRequired); } else { - ownerRecipe.parameters.warningFlags |= WarningFlags.DeadlockCandidate; + ownerRecipe.parameters = ownerRecipe.parameters.WithFlag(WarningFlags.DeadlockCandidate); } ownerRecipe = ownerRecipe.owner.owner as RecipeRow; @@ -483,10 +456,10 @@ private static void AddLinkCoef(Constraint cst, Variable var, ProductionLink lin foreach (var link in linkList) { if (link.flags.HasFlags(ProductionLink.Flags.LinkRecursiveNotMatched)) { if (link.notMatchedFlow > 0f) { - recipe.parameters.warningFlags |= WarningFlags.OverproductionRequired; + recipe.parameters = recipe.parameters.WithFlag(WarningFlags.OverproductionRequired); } else { - recipe.parameters.warningFlags |= WarningFlags.DeadlockCandidate; + recipe.parameters = recipe.parameters.WithFlag(WarningFlags.DeadlockCandidate); } } } @@ -522,13 +495,97 @@ private static void AddLinkCoef(Constraint cst, Variable var, ProductionLink lin for (int i = 0; i < allRecipes.Count; i++) { var recipe = allRecipes[i]; - recipe.recipesPerSecond = vars[i].SolutionValue(); + recipe.recipesPerSecond = vars[i]?.SolutionValue() ?? 0; } bool builtCountExceeded = CheckBuiltCountExceeded(); CalculateFlow(null); return builtCountExceeded ? "This model requires more buildings than are currently built" : null; + + static void cacheRecipeLinks(RecipeRow recipe) { + var links = recipe.links; + + for (int j = 0; j < recipe.recipe.products.Length; j++) { + var product = recipe.recipe.products[j]; + if (product.amount <= 0f) { + links.products[j] = null; + continue; + } + + _ = recipe.FindLink(product.goods, out links.products[j]); + } + + for (int j = 0; j < recipe.recipe.ingredients.Length; j++) { + var ingredient = recipe.recipe.ingredients[j]; + var option = ingredient.variants == null ? ingredient.goods : recipe.GetVariant(ingredient.variants); + + _ = recipe.FindLink(option, out links.ingredients[j]); + links.ingredientGoods[j] = option; + } + + if (recipe.fuel != null) { + _ = recipe.FindLink(recipe.fuel, out links.fuel); + _ = recipe.fuel.HasSpentFuel(out var spentFuel); + _ = recipe.FindLink(spentFuel, out links.spentFuel); + } + else { + links.fuel = links.spentFuel = null; + } + + recipe.links = links; + } + + static void configureRecipeForSolving(Solver productionTableSolver, ref Variable? recipeVar, ref float objCoef, Constraint[] constraints, RecipeRow recipe) { + if (recipeVar != null) { return; } + recipe.parameters = RecipeParameters.CalculateParameters(recipe); + recipeVar = productionTableSolver.MakeNumVar(0f, double.PositiveInfinity, recipe.recipe.name); + if (recipe.fixedBuildings > 0f) { + double fixedRps = (double)recipe.fixedBuildings / recipe.parameters.recipeTime; + recipeVar.SetBounds(fixedRps, fixedRps); + } + + var links = recipe.links; + + for (int j = 0; j < recipe.recipe.products.Length; j++) { + var product = recipe.recipe.products[j]; + var link = links.products[j]; + if (link != null) { + link.flags |= ProductionLink.Flags.HasProduction; + float added = product.GetAmountPerRecipe(recipe.parameters.productivity); + AddLinkCoef(constraints[link.solverIndex], recipeVar, link, recipe, added); + float cost = product.goods.Cost(); + if (cost > 0f) { + objCoef += added * cost; + } + } + } + + for (int j = 0; j < recipe.recipe.ingredients.Length; j++) { + var link = links.ingredients[j]; + if (link != null) { + var ingredient = recipe.recipe.ingredients[j]; + link.flags |= ProductionLink.Flags.HasConsumption; + AddLinkCoef(constraints[link.solverIndex], recipeVar, link, recipe, -ingredient.amount); + } + } + + if (links.fuel != null) { + float fuelAmount = recipe.parameters.fuelUsagePerSecondPerRecipe; + var link = links.fuel; + link.flags |= ProductionLink.Flags.HasConsumption; + AddLinkCoef(constraints[link.solverIndex], recipeVar, link, recipe, -fuelAmount); + + if (links.spentFuel != null) { + link = links.spentFuel; + link.flags |= ProductionLink.Flags.HasProduction; + AddLinkCoef(constraints[link.solverIndex], recipeVar, link, recipe, fuelAmount); + if (link.goods.Cost() > 0f) { + objCoef += fuelAmount * link.goods.Cost(); + } + } + } + } } /// @@ -544,12 +601,12 @@ private bool CheckBuiltCountExceeded() { for (int i = 0; i < recipes.Count; i++) { var recipe = recipes[i]; if (recipe.buildingCount > recipe.builtBuildings) { - recipe.parameters.warningFlags |= WarningFlags.ExceedsBuiltCount; + recipe.parameters = recipe.parameters.WithFlag(WarningFlags.ExceedsBuiltCount); builtCountExceeded = true; } else if (recipe.subgroup != null) { if (recipe.subgroup.CheckBuiltCountExceeded()) { - recipe.parameters.warningFlags |= WarningFlags.ExceedsBuiltCount; + recipe.parameters = recipe.parameters.WithFlag(WarningFlags.ExceedsBuiltCount); builtCountExceeded = true; } } @@ -622,7 +679,7 @@ private static (List merges, List splits) GetInf return (sources, splits); } - public bool FindLink(Goods goods, [MaybeNullWhen(false)] out ProductionLink link) { + public bool FindLink(Goods? goods, [MaybeNullWhen(false)] out ProductionLink link) { if (goods == null) { link = null; return false; diff --git a/Yafc.Model/Model/ProductionTableContent.cs b/Yafc.Model/Model/ProductionTableContent.cs index ec05d4ca..8ffedfd5 100644 --- a/Yafc.Model/Model/ProductionTableContent.cs +++ b/Yafc.Model/Model/ProductionTableContent.cs @@ -432,7 +432,7 @@ public IEnumerable Products { internal float fuelUsagePerSecond => (float)(parameters.fuelUsagePerSecondPerRecipe * recipesPerSecond); public UsedModule usedModules => parameters.modules; public WarningFlags warningFlags => parameters.warningFlags; - public bool FindLink(Goods goods, [MaybeNullWhen(false)] out ProductionLink link) { + public bool FindLink(Goods? goods, [MaybeNullWhen(false)] out ProductionLink link) { return linkRoot.FindLink(goods, out link); } diff --git a/Yafc.Model/Model/RecipeParameters.cs b/Yafc.Model/Model/RecipeParameters.cs index ef9f19ea..ba7003d3 100644 --- a/Yafc.Model/Model/RecipeParameters.cs +++ b/Yafc.Model/Model/RecipeParameters.cs @@ -31,14 +31,8 @@ public struct UsedModule { public int beaconCount; } - internal class RecipeParameters(float recipeTime, float fuelUsagePerSecondPerBuilding, float productivity, WarningFlags warningFlags, ModuleEffects activeEffects, UsedModule modules) { + internal sealed record RecipeParameters(float recipeTime, float fuelUsagePerSecondPerBuilding, float productivity, WarningFlags warningFlags, ModuleEffects activeEffects, UsedModule modules) { public const float MIN_RECIPE_TIME = 1f / 60; - public float recipeTime { get; } = recipeTime; - public float fuelUsagePerSecondPerBuilding { get; } = fuelUsagePerSecondPerBuilding; - public float productivity { get; } = productivity; - public WarningFlags warningFlags { get; internal set; } = warningFlags; - public ModuleEffects activeEffects { get; } = activeEffects; - public UsedModule modules { get; } = modules; public static RecipeParameters Empty = new(0, 0, 0, 0, default, default); @@ -182,5 +176,7 @@ public static RecipeParameters CalculateParameters(RecipeRow row) { return new RecipeParameters(recipeTime, fuelUsagePerSecondPerBuilding, productivity, warningFlags, activeEffects, modules); } + + internal RecipeParameters WithFlag(WarningFlags additionalFlag) => this with { warningFlags = warningFlags | additionalFlag }; } } diff --git a/Yafc.UI/Core/ExceptionScreen.cs b/Yafc.UI/Core/ExceptionScreen.cs index 1d0bb016..f62396d1 100644 --- a/Yafc.UI/Core/ExceptionScreen.cs +++ b/Yafc.UI/Core/ExceptionScreen.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using SDL2; using Serilog; @@ -33,7 +34,7 @@ protected internal override void Close() { exists = false; } - protected override void BuildContents(ImGui gui) { + protected override Task BuildContents(ImGui gui) { gui.BuildText(ex.GetType().Name, Font.header); gui.BuildText(ex.Message, new TextBlockDisplayStyle(Font.subheader, true)); gui.BuildText(ex.StackTrace, TextBlockDisplayStyle.WrappedText); @@ -50,6 +51,8 @@ protected override void BuildContents(ImGui gui) { _ = SDL.SDL_SetClipboardText(ex.Message + "\n\n" + ex.StackTrace); } } + + return Task.CompletedTask; } } } diff --git a/Yafc.UI/Core/Window.cs b/Yafc.UI/Core/Window.cs index 21c8dfdc..9b2e3222 100644 --- a/Yafc.UI/Core/Window.cs +++ b/Yafc.UI/Core/Window.cs @@ -1,5 +1,6 @@ using System; using System.Numerics; +using System.Threading.Tasks; using SDL2; using Serilog; @@ -201,12 +202,12 @@ public void ShowDropDown(ImGui targetGui, Rect target, GuiBuilder builder, Paddi ShowDropDown(simpleDropDown); } - private void Build(ImGui gui) { + private async void Build(ImGui gui) { if (closed) { return; } - BuildContents(gui); + await BuildContents(gui); if (dropDown != null) { dropDown.Build(gui); if (!dropDown.active) { @@ -222,7 +223,7 @@ private void Build(ImGui gui) { } } - protected abstract void BuildContents(ImGui gui); + protected abstract Task BuildContents(ImGui gui); public virtual void Dispose() => rootGui.Dispose(); internal ImGui.DragOverlay GetDragOverlay() => draggingOverlay ??= new ImGui.DragOverlay(); diff --git a/Yafc.UI/Core/WindowMain.cs b/Yafc.UI/Core/WindowMain.cs index a1fa296f..9bbd0590 100644 --- a/Yafc.UI/Core/WindowMain.cs +++ b/Yafc.UI/Core/WindowMain.cs @@ -1,6 +1,7 @@ using System; using System.Numerics; using System.Runtime.InteropServices; +using System.Threading.Tasks; using SDL2; using Serilog; @@ -35,12 +36,12 @@ protected void Create(string title, int display, float initialWidth, float initi base.Create(); } - protected override void BuildContents(ImGui gui) { - BuildContent(gui); + protected override async Task BuildContents(ImGui gui) { + await BuildContent(gui); gui.SetContextRect(new Rect(default, size)); } - protected abstract void BuildContent(ImGui gui); + protected abstract Task BuildContent(ImGui gui); protected override void OnRepaint() { rootGui.Rebuild(); diff --git a/Yafc/Windows/AboutScreen.cs b/Yafc/Windows/AboutScreen.cs index ca9570aa..5d39e22f 100644 --- a/Yafc/Windows/AboutScreen.cs +++ b/Yafc/Windows/AboutScreen.cs @@ -1,4 +1,5 @@ -using Yafc.UI; +using System.Threading.Tasks; +using Yafc.UI; namespace Yafc { public class AboutScreen : WindowUtility { @@ -6,7 +7,7 @@ public class AboutScreen : WindowUtility { public AboutScreen(Window parent) : base(ImGuiUtils.DefaultScreenPadding) => Create("About YAFC-CE", 50, parent); - protected override void BuildContents(ImGui gui) { + protected override Task BuildContents(ImGui gui) { gui.allocator = RectAllocator.Center; gui.BuildText("Yet Another Factorio Calculator", new TextBlockDisplayStyle(Font.header, Alignment: RectAlignment.Middle)); gui.BuildText("(Community Edition)", TextBlockDisplayStyle.Centered); @@ -66,6 +67,8 @@ protected override void BuildContents(ImGui gui) { gui.allocator = RectAllocator.Center; gui.BuildText("Factorio name, content and materials are trademarks and copyrights of Wube Software"); BuildLink(gui, "https://factorio.com/"); + + return Task.CompletedTask; } private void BuildLink(ImGui gui, string url, string? text = null) { diff --git a/Yafc/Windows/FilesystemScreen.cs b/Yafc/Windows/FilesystemScreen.cs index 5cc47bdf..862f34ec 100644 --- a/Yafc/Windows/FilesystemScreen.cs +++ b/Yafc/Windows/FilesystemScreen.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using System.Numerics; +using System.Threading.Tasks; using SDL2; using Yafc.UI; @@ -42,7 +43,7 @@ public FilesystemScreen(string? header, string description, string button, strin previousFocus = InputSystem.Instance.SetDefaultKeyboardFocus(this); } - protected override void BuildContents(ImGui gui) { + protected override Task BuildContents(ImGui gui) { gui.BuildText(description, TextBlockDisplayStyle.WrappedText); if (gui.BuildTextInput(location, out string newLocation, null)) { if (Directory.Exists(newLocation)) { @@ -62,6 +63,8 @@ protected override void BuildContents(ImGui gui) { } } } + + return Task.CompletedTask; } private void BuildSelectButton(ImGui gui) { diff --git a/Yafc/Windows/MainScreen.cs b/Yafc/Windows/MainScreen.cs index 184481ea..d9888b52 100644 --- a/Yafc/Windows/MainScreen.cs +++ b/Yafc/Windows/MainScreen.cs @@ -95,23 +95,27 @@ private void SetProject(Project project) { _ = InputSystem.Instance.SetDefaultKeyboardFocus(this); } - private void ProjectSettingsChanged(bool visualOnly) { + private async void ProjectSettingsChanged(bool visualOnly) { if (visualOnly) { return; } if (topScreen == null) { - ReRunAnalysis(); + await ReRunAnalysis(); } else { analysisUpdatePending = true; } } - private void ReRunAnalysis() { + private async Task ReRunAnalysis() { analysisUpdatePending = false; ErrorCollector collector = new ErrorCollector(); Analysis.ProcessAnalyses(this, project, collector); + project.pages.ForEach(p => p.SetToRecalculate()); + Task primary = (activePage?.RunSolveJob() ?? Task.CompletedTask); + await (secondaryPage?.RunSolveJob() ?? Task.CompletedTask); + await primary; rootGui.MarkEverythingForRebuild(); if (collector.severity > ErrorSeverity.None) { ErrorListPanel.Show(collector); @@ -205,7 +209,7 @@ public void RebuildProjectView() { secondaryPageView?.bodyContent.MarkEverythingForRebuild(); } - protected override void BuildContent(ImGui gui) { + protected override async Task BuildContent(ImGui gui) { if (pseudoScreens.Count > 0) { var top = pseudoScreens[0]; if (gui.isBuilding) { @@ -224,7 +228,7 @@ protected override void BuildContent(ImGui gui) { _ = InputSystem.Instance.SetDefaultKeyboardFocus(this); topScreen = null; if (analysisUpdatePending) { - ReRunAnalysis(); + await ReRunAnalysis(); } } BuildTabBar(gui); diff --git a/Yafc/Windows/WelcomeScreen.cs b/Yafc/Windows/WelcomeScreen.cs index 487c5161..9624e4ee 100644 --- a/Yafc/Windows/WelcomeScreen.cs +++ b/Yafc/Windows/WelcomeScreen.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Runtime.InteropServices; +using System.Threading.Tasks; using SDL2; using Serilog; using Yafc.Model; @@ -97,7 +98,7 @@ private void BuildError(ImGui gui) { gui.DrawRectangle(gui.lastRect, SchemeColor.Error); } - protected override void BuildContents(ImGui gui) { + protected override Task BuildContents(ImGui gui) { gui.spacing = 1.5f; gui.BuildText("Yet Another Factorio Calculator", new TextBlockDisplayStyle(Font.header, Alignment: RectAlignment.Middle)); if (loading) { @@ -185,6 +186,8 @@ protected override void BuildContents(ImGui gui) { } } } + + return Task.CompletedTask; } private void ProjectErrorMoreInfo(ImGui gui) { diff --git a/changelog.txt b/changelog.txt index c2750549..74bace6e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -30,6 +30,7 @@ Date: the launch-settings from the most-recently opened project. Bugfixes: - Several fixes to the legacy summary page, including a regression in 0.8.1. + - Milestone-locked and inaccessible recipes will be avoided when multiple recipes are available. Internal changes: - Add .git-blame-ignore revs. It doesn't work with Visual Studio, but it might be useful in CLI or other IDEs. - Add the ability for tests to load lua and run tests that need parts of a Yafc project.