diff --git a/Yafc.Model/Data/DataClasses.cs b/Yafc.Model/Data/DataClasses.cs index d3fc1676..9e357f19 100644 --- a/Yafc.Model/Data/DataClasses.cs +++ b/Yafc.Model/Data/DataClasses.cs @@ -457,6 +457,7 @@ public static bool CanAcceptModule(ModuleSpecification module, AllowedEffects ef public class EntityCrafter : EntityWithModules { public int itemInputs { get; internal set; } public int fluidInputs { get; internal set; } // fluid inputs for recipe, not including power + public bool hasVectorToPlaceResult { get; internal set; } public Goods[]? inputs { get; internal set; } public RecipeOrTechnology[] recipes { get; internal set; } = null!; // null-forgiving: Set in the first step of CalculateMaps private float _craftingSpeed = 1; diff --git a/Yafc.Model/Model/ProductionTableContent.cs b/Yafc.Model/Model/ProductionTableContent.cs index 082daea3..a9be995d 100644 --- a/Yafc.Model/Model/ProductionTableContent.cs +++ b/Yafc.Model/Model/ProductionTableContent.cs @@ -250,12 +250,21 @@ public class RecipeRow : ModelObject, IGroupedElement _entity; set { - if (SerializationMap.IsDeserializing || fixedBuildings == 0 || _entity == value) { + if (_entity == value) { + // Nothing to do + return; + } + + if (SerializationMap.IsDeserializing) { + // Just apply the deserialized entity and stop further processing _entity = value; + return; } - else if (fixedFuel && !(value?.energy.fuels ?? []).Contains(_fuel)) { - // We're changing both the entity and the fuel (changing between electric, fluid-burning, item-burning, heat-powered, and steam-powered crafter categories) - // Don't try to preserve fuel consumption in this case. + + if (fixedBuildings == 0 || (fixedFuel && !(value?.energy.fuels ?? []).Contains(_fuel))) { + // We're either changing both the entity and the fuel (changing between electric, fluid-burning, item-burning, heat-powered, and steam-powered crafter categories), + // or fixedBuilding is zero. + // Don't try to preserve fuel consumption in these cases. fixedBuildings = 0; _entity = value; } @@ -264,6 +273,9 @@ public EntityCrafter? entity { _entity = value; } } + + // By default show the total item consumption and production signals for unloading crafters (miners, recyclers, etc) when they output multiple products. + showTotalIO |= value?.hasVectorToPlaceResult == true && recipe.products.Length > 1; } } public Goods? fuel { @@ -356,6 +368,10 @@ public Goods? fixedProduct { } public int? builtBuildings { get; set; } /// + /// If , the total item consumption and production signals are shown. + /// + public bool showTotalIO { get; set; } = false; + /// /// If , the enabled checkbox for this recipe is checked. /// public bool enabled { get; set; } = true; diff --git a/Yafc.Model/Model/Project.cs b/Yafc.Model/Model/Project.cs index feeaf12d..c6dd8064 100644 --- a/Yafc.Model/Model/Project.cs +++ b/Yafc.Model/Model/Project.cs @@ -258,10 +258,6 @@ public class ProjectPreferences(Project owner) : ModelObject(owner) { /// The scale to use when drawing icons that have information stored in their background color, stored as a ratio from 0 to 1. /// public float iconScale { get; set; } = .9f; - /// - /// The and pseudo-items will be displayed at or above this ingredient/product count. - /// - public int minForTotalItems { get; set; } = 3; protected internal override void AfterDeserialize() { base.AfterDeserialize(); diff --git a/Yafc.Parser/Data/FactorioDataDeserializer_Entity.cs b/Yafc.Parser/Data/FactorioDataDeserializer_Entity.cs index f52bf47d..6abc183b 100644 --- a/Yafc.Parser/Data/FactorioDataDeserializer_Entity.cs +++ b/Yafc.Parser/Data/FactorioDataDeserializer_Entity.cs @@ -289,6 +289,10 @@ private void DeserializeEntity(LuaTable table, ErrorCollector errorCollector) { crafter.fluidInputs = CountFluidBoxes(fluidBoxes, true); } + if (table.Get("vector_to_place_result", out LuaTable? hasVectorToPlaceResult)) { + crafter.hasVectorToPlaceResult = hasVectorToPlaceResult != null; + } + Recipe? fixedRecipe = null; if (table.Get("fixed_recipe", out string? fixedRecipeName)) { @@ -360,6 +364,9 @@ private void DeserializeEntity(LuaTable table, ErrorCollector errorCollector) { drill.fluidInputs = 1; } + // All drills have/require the vector_to_place_result to drop their items + drill.hasVectorToPlaceResult = true; + foreach (string resource in resourceCategories.ArrayElements()) { recipeCrafters.Add(drill, SpecialNames.MiningRecipe + resource); } diff --git a/Yafc/Windows/PreferencesScreen.cs b/Yafc/Windows/PreferencesScreen.cs index 00c89e18..f86817de 100644 --- a/Yafc/Windows/PreferencesScreen.cs +++ b/Yafc/Windows/PreferencesScreen.cs @@ -142,7 +142,6 @@ private static void DrawGeneral(ImGui gui) { } } - float textBoxHeight; // measure the height of a text box, for use when drawing the minForTotalItems input box. using (gui.EnterRow()) { gui.BuildText("Reactor layout:", topOffset: 0.5f); if (gui.BuildTextInput(settings.reactorSizeX + "x" + settings.reactorSizeY, out string newSize, null, delayed: true)) { @@ -156,32 +155,6 @@ private static void DrawGeneral(ImGui gui) { settings.reactorSizeY = sizeY; } } - textBoxHeight = gui.lastRect.Height; - } - - string ioItemMessage = "The I and O items represent the total item input or item output of a recipe row.\nRecipes with at least this many item ingredients or item products will show the pseudo-items after all their real ingredients/products."; - using (gui.EnterRowWithHelpIcon(ioItemMessage)) { - float captionWidth = gui.GetTextDimensions(out _, "Minimum recipe ingredients or products").X; - using (gui.EnterFixedPositioning(captionWidth, 0, new())) { // the height will grow to fit the controls - gui.BuildText("Minimum recipe ingredients or products"); - using (gui.EnterRow(0)) { - // Allocate the horizontal space now but draw the icons first, so the text can be drawn vertically centered. - Rect textRect = gui.AllocateTextRect(out _, "to display the ", TextBlockDisplayStyle.Default()); - gui.BuildFactorioObjectButton(Database.itemInput, ButtonDisplayStyle.Default); - gui.BuildFactorioObjectButton(Database.itemOutput, ButtonDisplayStyle.Default); - textRect.Height = gui.lastRect.Height; - gui.DrawText(textRect, "to display the "); - gui.BuildText(" summary items"); - } - } - float spacing = (gui.lastRect.Height - textBoxHeight) / 2; - using (gui.RemainingRow().EnterFixedPositioning(0, gui.lastRect.Height, new())) { - gui.AllocateSpacing(spacing - .5f); // draw the box vertically centered, rather than top-aligned (without this) or full height (without EnterFixedPositioning) - if (gui.BuildIntegerInput(prefs.minForTotalItems, out int newValue2)) { - prefs.RecordUndo().minForTotalItems = newValue2; - gui.Rebuild(); - } - } } gui.AllocateSpacing(); diff --git a/Yafc/Workspace/ProductionTable/ProductionTableView.cs b/Yafc/Workspace/ProductionTable/ProductionTableView.cs index 6346455a..2a922f01 100644 --- a/Yafc/Workspace/ProductionTable/ProductionTableView.cs +++ b/Yafc/Workspace/ProductionTable/ProductionTableView.cs @@ -134,6 +134,10 @@ public override void BuildElement(ImGui gui, RecipeRow recipe) { view.BuildShoppingList(recipe); } + if (imgui.BuildCheckBox("Show total Input/Output", recipe.showTotalIO, out bool newShowTotalIO)) { + recipe.RecordUndo().showTotalIO = newShowTotalIO; + } + if (imgui.BuildCheckBox("Enabled", recipe.enabled, out bool newEnabled)) { recipe.RecordUndo().enabled = newEnabled; } @@ -538,7 +542,7 @@ public override void BuildElement(ImGui gui, RecipeRow recipe) { grid.Next(); view.BuildGoodsIcon(gui, goods, link, amount, ProductDropdownType.Ingredient, recipe, recipe.linkRoot, HintLocations.OnProducingRecipes, variants); } - if (recipe.fixedIngredient == Database.itemInput || recipe.Ingredients.Count() >= Project.current.preferences.minForTotalItems) { + if (recipe.fixedIngredient == Database.itemInput || recipe.showTotalIO) { grid.Next(); view.BuildGoodsIcon(gui, recipe.hierarchyEnabled ? Database.itemInput : null, null, recipe.Ingredients.Where(i => i.Goods is Item).Sum(i => i.Amount), ProductDropdownType.Ingredient, recipe, recipe.linkRoot, HintLocations.None); @@ -559,7 +563,7 @@ public override void BuildElement(ImGui gui, RecipeRow recipe) { grid.Next(); view.BuildGoodsIcon(gui, goods, link, amount, ProductDropdownType.Product, recipe, recipe.linkRoot, HintLocations.OnConsumingRecipes); } - if (recipe.fixedProduct == Database.itemOutput || recipe.Products.Count() >= Project.current.preferences.minForTotalItems) { + if (recipe.fixedProduct == Database.itemOutput || recipe.showTotalIO) { grid.Next(); view.BuildGoodsIcon(gui, recipe.hierarchyEnabled ? Database.itemOutput : null, null, recipe.Products.Where(i => i.Goods is Item).Sum(i => i.Amount), ProductDropdownType.Product, recipe, recipe.linkRoot, HintLocations.None); diff --git a/changelog.txt b/changelog.txt index 1a5e1c70..0e19147a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -19,6 +19,7 @@ Version: Date: Features: - Add pseudo-items representing a recipe's total sushi-inputs and sushi-outputs. + They can be toggled on/off in the LMB of the recipe. Bugfixes: - Fixed counts are hidden on disabled recipes, since editing them won't work properly. ----------------------------------------------------------------------------------------------------------------------